From 7714b2cd326a14573fc57e176138ceb2469ddb8e Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Mon, 8 Apr 2024 13:12:06 +0100 Subject: [PATCH 01/20] Add more logs tracking gesture and recents animation in RecentsView Bug: 332635097 Test: manual Flag: None Change-Id: I6f83806f783344c07f7f59fe87c37b7cc377fff2 --- quickstep/src/com/android/quickstep/views/RecentsView.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index eca70b74ba..486c090de1 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -2569,6 +2569,7 @@ public abstract class RecentsView Date: Mon, 8 Apr 2024 18:20:10 +0000 Subject: [PATCH 02/20] [Launcher/Archive] remove all checks for the archiving system property No longer needed Change-Id: I62c8843aa04a245d1dcc30f7787c71d17993f5d1 BUG: 331165939 Test: builds --- src/com/android/launcher3/LauncherAppState.java | 2 +- src/com/android/launcher3/Utilities.java | 6 ------ src/com/android/launcher3/icons/IconCache.java | 3 ++- src/com/android/launcher3/model/AllAppsList.java | 3 ++- src/com/android/launcher3/model/ItemInstallQueue.java | 3 ++- src/com/android/launcher3/model/LoaderTask.java | 4 ++-- src/com/android/launcher3/model/PackageUpdatedTask.java | 2 +- src/com/android/launcher3/model/WorkspaceItemProcessor.kt | 7 ++++--- src/com/android/launcher3/model/data/AppInfo.java | 2 +- src/com/android/launcher3/model/data/ItemInfoWithIcon.java | 3 ++- src/com/android/launcher3/pm/InstallSessionHelper.java | 5 +++-- src/com/android/launcher3/pm/InstallSessionTracker.java | 3 ++- src/com/android/launcher3/touch/ItemClickHandler.java | 3 ++- src/com/android/launcher3/util/PackageManagerHelper.java | 5 +++-- 14 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index 60a6be6c9e..50a597d407 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -110,7 +110,7 @@ public class LauncherAppState implements SafeCloseable { mOnTerminateCallback.add(() -> mContext.getSystemService(LauncherApps.class).unregisterCallback(callbacks)); - if (Utilities.enableSupportForArchiving()) { + if (Flags.enableSupportForArchiving()) { ArchiveCompatibilityParams params = new ArchiveCompatibilityParams(); params.setEnableUnarchivalConfirmation(false); launcherApps.setArchiveCompatibility(params); diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index d44438f5bc..2b886e4570 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -830,10 +830,4 @@ public final class Utilities { // No-Op } } - - /** Encapsulates two flag checks into a single one. */ - public static boolean enableSupportForArchiving() { - return Flags.enableSupportForArchiving() - || getSystemProperty("pm.archiving.enabled", "false").equals("true"); - } } diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java index 1633eba5e1..af704a88f0 100644 --- a/src/com/android/launcher3/icons/IconCache.java +++ b/src/com/android/launcher3/icons/IconCache.java @@ -51,6 +51,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.core.util.Pair; +import com.android.launcher3.Flags; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Utilities; import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic; @@ -248,7 +249,7 @@ public class IconCache extends BaseIconCache { @SuppressWarnings("NewApi") public synchronized void getTitleAndIcon(ItemInfoWithIcon info, LauncherActivityInfo activityInfo, boolean useLowResIcon) { - boolean isAppArchived = Utilities.enableSupportForArchiving() && activityInfo != null + boolean isAppArchived = Flags.enableSupportForArchiving() && activityInfo != null && activityInfo.getActivityInfo().isArchived; // If we already have activity info, no need to use package icon getTitleAndIcon(info, () -> activityInfo, isAppArchived, useLowResIcon, diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java index 8659471d27..8c5ea79034 100644 --- a/src/com/android/launcher3/model/AllAppsList.java +++ b/src/com/android/launcher3/model/AllAppsList.java @@ -33,6 +33,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.AppFilter; +import com.android.launcher3.Flags; import com.android.launcher3.Utilities; import com.android.launcher3.compat.AlphabeticIndexCompat; import com.android.launcher3.icons.IconCache; @@ -330,7 +331,7 @@ public class AllAppsList { PackageManagerHelper.getLoadingProgress(info), PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING); applicationInfo.intent = launchIntent; - if (Utilities.enableSupportForArchiving()) { + if (Flags.enableSupportForArchiving()) { // In case an app is archived, the respective item flag corresponding to // archiving should also be applied during package updates if (info.getActivityInfo().isArchived) { diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java index d35087980a..90aba2a2de 100644 --- a/src/com/android/launcher3/model/ItemInstallQueue.java +++ b/src/com/android/launcher3/model/ItemInstallQueue.java @@ -40,6 +40,7 @@ import android.util.Pair; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import com.android.launcher3.Flags; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; @@ -300,7 +301,7 @@ public class ItemInstallQueue { } else { lai = laiList.get(0); si.intent = makeLaunchIntent(lai); - if (Utilities.enableSupportForArchiving() + if (Flags.enableSupportForArchiving() && lai.getActivityInfo().isArchived) { si.runtimeStatusFlags |= FLAG_ARCHIVED; } diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index e0ced83855..ac4c087e02 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -421,7 +421,7 @@ public class LoaderTask implements Runnable { final HashMap installingPkgs = mSessionHelper.getActiveSessions(); - if (Utilities.enableSupportForArchiving()) { + if (Flags.enableSupportForArchiving()) { mInstallingPkgsCached = installingPkgs; } installingPkgs.forEach(mApp.getIconCache()::updateSessionCache); @@ -695,7 +695,7 @@ public class LoaderTask implements Runnable { for (int i = 0; i < apps.size(); i++) { LauncherActivityInfo app = apps.get(i); AppInfo appInfo = new AppInfo(app, mUserCache.getUserInfo(user), quietMode); - if (Utilities.enableSupportForArchiving() && app.getApplicationInfo().isArchived) { + if (Flags.enableSupportForArchiving() && app.getApplicationInfo().isArchived) { // For archived apps, include progress info in case there is a pending // install session post restart of device. String appPackageName = app.getApplicationInfo().packageName; diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index ea1ae2ed24..e8767bf311 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -276,7 +276,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING); // In case an app is archived, we need to make sure that archived state // in WorkspaceItemInfo is refreshed. - if (Utilities.enableSupportForArchiving() && !activities.isEmpty()) { + if (Flags.enableSupportForArchiving() && !activities.isEmpty()) { boolean newArchivalState = activities.get( 0).getActivityInfo().isArchived; if (newArchivalState != si.isArchived()) { diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt index d27be727af..633279dd59 100644 --- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt +++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt @@ -26,6 +26,7 @@ import android.graphics.Point import android.text.TextUtils import android.util.Log import android.util.LongSparseArray +import com.android.launcher3.Flags import com.android.launcher3.InvariantDeviceProfile import com.android.launcher3.LauncherAppState import com.android.launcher3.LauncherSettings.Favorites @@ -334,7 +335,7 @@ class WorkspaceItemProcessor( } if ( (c.restoreFlag != 0 || - Utilities.enableSupportForArchiving() && + Flags.enableSupportForArchiving() && activityInfo != null && activityInfo.applicationInfo.isArchived) && !TextUtils.isEmpty(targetPkg) ) { @@ -346,7 +347,7 @@ class WorkspaceItemProcessor( ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE.inv() } else if ( activityInfo == null || - (Utilities.enableSupportForArchiving() && + (Flags.enableSupportForArchiving() && activityInfo.applicationInfo.isArchived) ) { // For archived apps, include progress info in case there is @@ -472,7 +473,7 @@ class WorkspaceItemProcessor( !isSafeMode && (si == null) && (lapi == null) && - !(Utilities.enableSupportForArchiving() && + !(Flags.enableSupportForArchiving() && pmHelper.isAppArchived(component.packageName)) ) { // Restore never started diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java index 210d720bca..93ba619099 100644 --- a/src/com/android/launcher3/model/data/AppInfo.java +++ b/src/com/android/launcher3/model/data/AppInfo.java @@ -181,7 +181,7 @@ public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory { if (PackageManagerHelper.isAppSuspended(appInfo)) { info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED; } - if (Utilities.enableSupportForArchiving() && lai.getActivityInfo().isArchived) { + if (Flags.enableSupportForArchiving() && lai.getActivityInfo().isArchived) { info.runtimeStatusFlags |= FLAG_ARCHIVED; } info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java index be3aa101ac..19bb4657a9 100644 --- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java +++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java @@ -22,6 +22,7 @@ import android.os.Process; import androidx.annotation.Nullable; +import com.android.launcher3.Flags; import com.android.launcher3.Utilities; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.BitmapInfo.DrawableCreationFlags; @@ -162,7 +163,7 @@ public abstract class ItemInfoWithIcon extends ItemInfo { * Returns true if the app corresponding to the item is archived. */ public boolean isArchived() { - if (!Utilities.enableSupportForArchiving()) { + if (!Flags.enableSupportForArchiving()) { return false; } return (runtimeStatusFlags & FLAG_ARCHIVED) != 0; diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java index f3769d535f..4a3318e834 100644 --- a/src/com/android/launcher3/pm/InstallSessionHelper.java +++ b/src/com/android/launcher3/pm/InstallSessionHelper.java @@ -29,6 +29,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import com.android.launcher3.Flags; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.SessionCommitReceiver; import com.android.launcher3.Utilities; @@ -217,7 +218,7 @@ public class InstallSessionHelper { && !promiseIconAddedForId(sessionInfo.getSessionId())) { // In case of unarchival, we do not want to add a workspace promise icon if one is // not already present. For general app installations however, we do support it. - if (!Utilities.enableSupportForArchiving() || !sessionInfo.isUnarchival()) { + if (!Flags.enableSupportForArchiving() || !sessionInfo.isUnarchival()) { FileLog.d(LOG, "Adding package name to install queue: " + sessionInfo.getAppPackageName()); @@ -232,7 +233,7 @@ public class InstallSessionHelper { public boolean verifySessionInfo(@Nullable final PackageInstaller.SessionInfo sessionInfo) { // For archived apps we always want to show promise icons and the checks below don't apply. - if (Utilities.enableSupportForArchiving() && sessionInfo != null + if (Flags.enableSupportForArchiving() && sessionInfo != null && sessionInfo.isUnarchival()) { return true; } diff --git a/src/com/android/launcher3/pm/InstallSessionTracker.java b/src/com/android/launcher3/pm/InstallSessionTracker.java index eacbc11821..24d58f3e98 100644 --- a/src/com/android/launcher3/pm/InstallSessionTracker.java +++ b/src/com/android/launcher3/pm/InstallSessionTracker.java @@ -31,6 +31,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import com.android.launcher3.Flags; import com.android.launcher3.Utilities; import com.android.launcher3.util.PackageUserKey; @@ -80,7 +81,7 @@ public class InstallSessionTracker extends PackageInstaller.SessionCallback { helper.tryQueuePromiseAppIcon(sessionInfo); - if (Utilities.enableSupportForArchiving() && sessionInfo != null + if (Flags.enableSupportForArchiving() && sessionInfo != null && sessionInfo.isUnarchival()) { // For archived apps, icon could already be present on the workspace. To make sure // the icon state is updated, we send a change event. diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java index 50df7757ec..2dfebde2c1 100644 --- a/src/com/android/launcher3/touch/ItemClickHandler.java +++ b/src/com/android/launcher3/touch/ItemClickHandler.java @@ -41,6 +41,7 @@ import android.widget.Toast; import com.android.launcher3.BubbleTextView; import com.android.launcher3.BuildConfig; +import com.android.launcher3.Flags; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherSettings; @@ -346,7 +347,7 @@ public class ItemClickHandler { // Check for abandoned promise if ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi() - && (!Utilities.enableSupportForArchiving() || !shortcut.isArchived())) { + && (!Flags.enableSupportForArchiving() || !shortcut.isArchived())) { String packageName = shortcut.getIntent().getComponent() != null ? shortcut.getIntent().getComponent().getPackageName() : shortcut.getIntent().getPackage(); diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java index 316506ab4a..82e6f890e8 100644 --- a/src/com/android/launcher3/util/PackageManagerHelper.java +++ b/src/com/android/launcher3/util/PackageManagerHelper.java @@ -38,6 +38,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.launcher3.Flags; import com.android.launcher3.PendingAddItemInfo; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -109,7 +110,7 @@ public class PackageManagerHelper { @SuppressWarnings("NewApi") public boolean isAppArchivedForUser(@NonNull final String packageName, @NonNull final UserHandle user) { - if (!Utilities.enableSupportForArchiving()) { + if (!Flags.enableSupportForArchiving()) { return false; } final ApplicationInfo info = getApplicationInfo( @@ -274,6 +275,6 @@ public class PackageManagerHelper { @SuppressWarnings("NewApi") private boolean isPackageInstalledOrArchived(ApplicationInfo info) { return (info.flags & ApplicationInfo.FLAG_INSTALLED) != 0 || ( - Utilities.enableSupportForArchiving() && info.isArchived); + Flags.enableSupportForArchiving() && info.isArchived); } } From 6a60c3b1130c96ba349b09e4f2fb5b95102b2949 Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Fri, 5 Apr 2024 16:21:55 -0700 Subject: [PATCH 03/20] Prevent menu items from showing on split tasks This CL changes the TaskShortcutFactory for SCREENSHOT and MODAL so that the associated menu options ("Screenshot" and "Select") don't show up on split tasks. These actions are not fully supported on splitscreen tiles (they will only work on one of the two apps), so we disable them. Bug: 327434215 Flag: N/A Test: Manual Change-Id: I121a9c28fa7570f10e13be2de6489182e3362cfc --- .../src/com/android/quickstep/TaskOverlayFactory.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java index cc582d1e09..2fa3001725 100644 --- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java @@ -82,9 +82,10 @@ public class TaskOverlayFactory implements ResourceBasedOverride { boolean isTablet = activity.getDeviceProfile().isTablet; boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview(); - // Add overview actions to the menu when in in-place rotate landscape mode, or in - // grid-only overview. - if ((!canLauncherRotate && isInLandscape) || isGridOnlyOverview) { + // Add overview actions to the menu when: + // - single task is showing + // - in in-place rotate landscape mode, or in grid-only overview. + if (!hasMultipleTasks && ((!canLauncherRotate && isInLandscape) || isGridOnlyOverview)) { // Add screenshot action to task menu. List screenshotShortcuts = TaskShortcutFactory.SCREENSHOT .getShortcuts(activity, taskContainer); From 3c0729c4623a5aeb6108fe0000315953a7a0e299 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Fri, 22 Mar 2024 14:23:50 +0000 Subject: [PATCH 04/20] Add task menu item to move task to Desktop - Call SystemUiProxy.moveToDesktop to move existing Overview tasks to desktop - Animation polish will be handled separately - Refactored AbstractFloatingView method into a helper to allow testing Fix: 320310347 Test: DesktopSystemShortcutTest, AbstractFloatingViewHelperTest Flag: ACONFIG com.android.window.flags.enable_desktop_windowing_mode DEVELOPMENT Change-Id: I2e4e04182e46ba4750e0683ee1789ba8fada06ea --- quickstep/res/values/strings.xml | 2 + .../DesktopRecentsTransitionController.kt | 8 +- .../HotseatPredictionController.java | 2 +- .../quickstep/DesktopSystemShortcut.kt | 81 ++++++++++ .../com/android/quickstep/SystemUiProxy.java | 11 ++ .../android/quickstep/TaskOverlayFactory.java | 3 +- .../quickstep/TaskShortcutFactory.java | 6 +- .../android/quickstep/views/RecentsView.java | 21 +++ .../com/android/quickstep/views/TaskView.java | 6 +- .../quickstep/DesktopSystemShortcutTest.kt | 139 ++++++++++++++++++ .../launcher3/AbstractFloatingView.java | 13 +- .../launcher3/AbstractFloatingViewHelper.kt | 38 +++++ .../launcher3/logging/StatsLogManager.java | 3 + .../launcher3/popup/SystemShortcut.java | 29 ++-- .../AbstractFloatingViewHelperTest.kt | 106 +++++++++++++ 15 files changed, 434 insertions(+), 34 deletions(-) create mode 100644 quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt create mode 100644 quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt create mode 100644 src/com/android/launcher3/AbstractFloatingViewHelper.kt create mode 100644 tests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml index eb9c5f0029..71855eb61f 100644 --- a/quickstep/res/values/strings.xml +++ b/quickstep/res/values/strings.xml @@ -26,6 +26,8 @@ Pin Freeform + + Desktop No recent items diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt index 10733fbbea..64fe30c538 100644 --- a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt +++ b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt @@ -56,6 +56,11 @@ class DesktopRecentsTransitionController( systemUiProxy.showDesktopApps(desktopTaskView.display.displayId, transition) } + /** Launch desktop tasks from recents view */ + fun moveToDesktop(taskId: Int) { + systemUiProxy.moveToDesktop(taskId) + } + private class RemoteDesktopLaunchTransitionRunner( private val desktopTaskView: DesktopTaskView, private val stateManager: StateManager<*>, @@ -99,8 +104,7 @@ class DesktopRecentsTransitionController( finishCallback: IRemoteTransitionFinishedCallback ) {} - override fun onTransitionConsumed(transition: IBinder?, aborted: Boolean) { - } + override fun onTransitionConsumed(transition: IBinder?, aborted: Boolean) {} } companion object { diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java index 672bd1decf..1c5a75dd1c 100644 --- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java +++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java @@ -499,7 +499,7 @@ public class HotseatPredictionController implements DragController.DragListener, @Override public void onClick(View view) { - dismissTaskMenuView(mTarget); + dismissTaskMenuView(); pinPrediction(mItemInfo); } } diff --git a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt new file mode 100644 index 0000000000..8c71d925e4 --- /dev/null +++ b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.quickstep + +import android.view.View +import com.android.launcher3.AbstractFloatingViewHelper +import com.android.launcher3.BaseDraggingActivity +import com.android.launcher3.R +import com.android.launcher3.logging.StatsLogManager.LauncherEvent +import com.android.launcher3.popup.SystemShortcut +import com.android.quickstep.views.RecentsView +import com.android.quickstep.views.TaskView.TaskIdAttributeContainer +import com.android.window.flags.Flags + +/** A menu item, "Desktop", that allows the user to bring the current app into Desktop Windowing. */ +class DesktopSystemShortcut( + activity: BaseDraggingActivity, + private val mTaskContainer: TaskIdAttributeContainer, + abstractFloatingViewHelper: AbstractFloatingViewHelper +) : + SystemShortcut( + R.drawable.ic_caption_desktop_button_foreground, + R.string.recent_task_option_desktop, + activity, + mTaskContainer.itemInfo, + mTaskContainer.taskView, + abstractFloatingViewHelper + ) { + override fun onClick(view: View) { + dismissTaskMenuView() + val recentsView = mTarget!!.getOverviewPanel>() + recentsView.moveTaskToDesktop(mTaskContainer) { + mTarget.statsLogManager + .logger() + .withItemInfo(mTaskContainer.itemInfo) + .log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP) + } + } + + companion object { + /** Creates a factory for creating Desktop system shorcuts. */ + @JvmOverloads + fun createFactory( + abstractFloatingViewHelper: AbstractFloatingViewHelper = AbstractFloatingViewHelper() + ): TaskShortcutFactory { + return object : TaskShortcutFactory { + override fun getShortcuts( + activity: BaseDraggingActivity, + taskContainer: TaskIdAttributeContainer + ): List? { + return if (!Flags.enableDesktopWindowingMode()) null + else if (!taskContainer.task.isDockable) null + else + listOf( + DesktopSystemShortcut( + activity, + taskContainer, + abstractFloatingViewHelper + ) + ) + } + + override fun showForSplitscreen() = true + } + } + } +} diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index ab609fd686..53c1d50ee9 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -1473,6 +1473,17 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle { } } + /** Call shell to move a task with given `taskId` to desktop */ + public void moveToDesktop(int taskId) { + if (mDesktopMode != null) { + try { + mDesktopMode.moveToDesktop(taskId); + } catch (RemoteException e) { + Log.w(TAG, "Failed call moveToDesktop", e); + } + } + } + // // Unfold transition // diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java index cc582d1e09..8a4989bc98 100644 --- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java @@ -136,6 +136,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride { TaskShortcutFactory.PIN, TaskShortcutFactory.INSTALL, TaskShortcutFactory.FREE_FORM, + DesktopSystemShortcut.Companion.createFactory(), TaskShortcutFactory.WELLBEING, TaskShortcutFactory.SAVE_APP_PAIR }; @@ -315,7 +316,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride { @Override public void onClick(View view) { saveScreenshot(mThumbnailView.getTaskView().getTask()); - dismissTaskMenuView(mActivity); + dismissTaskMenuView(); } } diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java index 147a3e2408..5e970f1bd7 100644 --- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java +++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java @@ -145,7 +145,7 @@ public interface TaskShortcutFactory { @Override public void onClick(View view) { - dismissTaskMenuView(mTarget); + dismissTaskMenuView(); ((RecentsView) mTarget.getOverviewPanel()) .getSplitSelectController().getAppPairsController().saveAppPair(mTaskView); } @@ -174,7 +174,7 @@ public interface TaskShortcutFactory { @Override public void onClick(View view) { - dismissTaskMenuView(mTarget); + dismissTaskMenuView(); RecentsView rv = mTarget.getOverviewPanel(); rv.switchToScreenshot(() -> { rv.finishRecentsAnimation(true /* toRecents */, false /* shouldPip */, () -> { @@ -420,7 +420,7 @@ public interface TaskShortcutFactory { SystemUiProxy.INSTANCE.get(mTarget).startScreenPinning( mTaskView.getTask().key.id); } - dismissTaskMenuView(mTarget); + dismissTaskMenuView(); mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo()) .log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP); } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index eca70b74ba..7c54cecf32 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -6200,6 +6200,27 @@ public abstract class RecentsView mActivity.setLocusContext(id, Bundle.EMPTY)); } + /** + * Moves the provided task into desktop mode, and invoke {@code successCallback} if succeeded. + */ + public void moveTaskToDesktop(TaskIdAttributeContainer taskContainer, + Runnable successCallback) { + if (!enableDesktopWindowingMode()) { + return; + } + switchToScreenshot(() -> finishRecentsAnimation(/* toRecents= */true, /* shouldPip= */false, + () -> moveTaskToDesktopInternal(taskContainer, successCallback))); + } + + private void moveTaskToDesktopInternal(TaskIdAttributeContainer taskContainer, + Runnable successCallback) { + if (mDesktopRecentsTransitionController == null) { + return; + } + mDesktopRecentsTransitionController.moveToDesktop(taskContainer.getTask().key.id); + successCallback.run(); + } + public interface TaskLaunchListener { void onTaskLaunched(); } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index cec09824bf..3b31cd7b43 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -486,7 +486,11 @@ public class TaskView extends FrameLayout implements Reusable { return getItemInfo(mTask); } - protected WorkspaceItemInfo getItemInfo(@Nullable Task task) { + /** + * Builds proto for logging + */ + @VisibleForTesting + public WorkspaceItemInfo getItemInfo(@Nullable Task task) { WorkspaceItemInfo stubInfo = new WorkspaceItemInfo(); stubInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK; stubInfo.container = LauncherSettings.Favorites.CONTAINER_TASKSWITCHER; diff --git a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt new file mode 100644 index 0000000000..b90839d5a8 --- /dev/null +++ b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.quickstep + +import android.content.ComponentName +import android.content.Intent +import android.platform.test.flag.junit.SetFlagsRule +import com.android.launcher3.AbstractFloatingView +import com.android.launcher3.AbstractFloatingViewHelper +import com.android.launcher3.Launcher +import com.android.launcher3.logging.StatsLogManager +import com.android.launcher3.logging.StatsLogManager.LauncherEvent +import com.android.launcher3.model.data.WorkspaceItemInfo +import com.android.launcher3.util.SplitConfigurationOptions +import com.android.quickstep.views.LauncherRecentsView +import com.android.quickstep.views.TaskView +import com.android.systemui.shared.recents.model.Task +import com.android.systemui.shared.recents.model.Task.TaskKey +import com.android.window.flags.Flags +import com.google.common.truth.Truth.assertThat +import org.junit.Rule +import org.junit.Test +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +/** Test for DesktopSystemShortcut */ +class DesktopSystemShortcutTest { + + @get:Rule val setFlagsRule = SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT) + + private val launcher: Launcher = mock() + private val statsLogManager: StatsLogManager = mock() + private val statsLogger: StatsLogManager.StatsLogger = mock() + private val recentsView: LauncherRecentsView = mock() + private val taskView: TaskView = mock() + private val workspaceItemInfo: WorkspaceItemInfo = mock() + private val abstractFloatingViewHelper: AbstractFloatingViewHelper = mock() + private val factory: TaskShortcutFactory = + DesktopSystemShortcut.createFactory(abstractFloatingViewHelper) + + @Test + fun createDesktopTaskShortcutFactory_featureOff() { + setFlagsRule.disableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) + + val task = + Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply { + isDockable = true + } + val taskContainer = + taskView.TaskIdAttributeContainer( + task, + null, + null, + SplitConfigurationOptions.STAGE_POSITION_UNDEFINED + ) + + val shortcuts = factory.getShortcuts(launcher, taskContainer) + assertThat(shortcuts).isNull() + } + + @Test + fun createDesktopTaskShortcutFactory_undockable() { + setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) + + val task = + Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply { + isDockable = false + } + val taskContainer = + taskView.TaskIdAttributeContainer( + task, + null, + null, + SplitConfigurationOptions.STAGE_POSITION_UNDEFINED + ) + + val shortcuts = factory.getShortcuts(launcher, taskContainer) + assertThat(shortcuts).isNull() + } + + @Test + fun desktopSystemShortcutClicked() { + setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) + + val task = + Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply { + isDockable = true + } + val taskContainer = + taskView.TaskIdAttributeContainer( + task, + null, + null, + SplitConfigurationOptions.STAGE_POSITION_UNDEFINED + ) + + whenever(launcher.getOverviewPanel()).thenReturn(recentsView) + whenever(launcher.statsLogManager).thenReturn(statsLogManager) + whenever(statsLogManager.logger()).thenReturn(statsLogger) + whenever(statsLogger.withItemInfo(any())).thenReturn(statsLogger) + whenever(taskView.getItemInfo(task)).thenReturn(workspaceItemInfo) + whenever(recentsView.moveTaskToDesktop(any(), any())).thenAnswer { + val successCallback = it.getArgument(1) + successCallback.run() + } + + val shortcuts = factory.getShortcuts(launcher, taskContainer) + assertThat(shortcuts).hasSize(1) + assertThat(shortcuts!!.first()).isInstanceOf(DesktopSystemShortcut::class.java) + + val desktopShortcut = shortcuts.first() as DesktopSystemShortcut + + desktopShortcut.onClick(taskView) + + val allTypesExceptRebindSafe = + AbstractFloatingView.TYPE_ALL and AbstractFloatingView.TYPE_REBIND_SAFE.inv() + verify(abstractFloatingViewHelper).closeOpenViews(launcher, true, allTypesExceptRebindSafe) + verify(recentsView).moveTaskToDesktop(eq(taskContainer), any()) + verify(statsLogger).withItemInfo(workspaceItemInfo) + verify(statsLogger).log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP) + } +} diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java index e7b88dc9b9..4ccf3dbdfb 100644 --- a/src/com/android/launcher3/AbstractFloatingView.java +++ b/src/com/android/launcher3/AbstractFloatingView.java @@ -278,18 +278,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch public static void closeOpenViews(ActivityContext activity, boolean animate, @FloatingViewType int type) { - BaseDragLayer dragLayer = activity.getDragLayer(); - // Iterate in reverse order. AbstractFloatingView is added later to the dragLayer, - // and will be one of the last views. - for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) { - View child = dragLayer.getChildAt(i); - if (child instanceof AbstractFloatingView) { - AbstractFloatingView abs = (AbstractFloatingView) child; - if (abs.isOfType(type)) { - abs.close(animate); - } - } - } + new AbstractFloatingViewHelper().closeOpenViews(activity, animate, type); } public static void closeAllOpenViews(ActivityContext activity, boolean animate) { diff --git a/src/com/android/launcher3/AbstractFloatingViewHelper.kt b/src/com/android/launcher3/AbstractFloatingViewHelper.kt new file mode 100644 index 0000000000..0bfbc6e9fe --- /dev/null +++ b/src/com/android/launcher3/AbstractFloatingViewHelper.kt @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3 + +import com.android.launcher3.AbstractFloatingView.FloatingViewType +import com.android.launcher3.views.ActivityContext + +/** + * Helper class for manaing AbstractFloatingViews which shows a floating UI on top of the launcher + * UI. + */ +class AbstractFloatingViewHelper { + fun closeOpenViews(activity: ActivityContext, animate: Boolean, @FloatingViewType type: Int) { + val dragLayer = activity.getDragLayer() + // Iterate in reverse order. AbstractFloatingView is added later to the dragLayer, + // and will be one of the last views. + for (i in dragLayer.getChildCount() - 1 downTo 0) { + val child = dragLayer.getChildAt(i) + if (child is AbstractFloatingView && child.isOfType(type)) { + child.close(animate) + } + } + } +} diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index e8f8ae25ea..441bbb579d 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -218,6 +218,9 @@ public class StatsLogManager implements ResourceBasedOverride { @UiEvent(doc = "User tapped on free form icon on a task menu.") LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP(519), + @UiEvent(doc = "User tapped on desktop icon on a task menu.") + LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP(1706), + @UiEvent(doc = "User tapped on pause app system shortcut.") LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP(521), diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java index 0af7e677ed..bd32358035 100644 --- a/src/com/android/launcher3/popup/SystemShortcut.java +++ b/src/com/android/launcher3/popup/SystemShortcut.java @@ -22,6 +22,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.AbstractFloatingViewHelper; import com.android.launcher3.Flags; import com.android.launcher3.R; import com.android.launcher3.SecondaryDropTarget; @@ -61,23 +62,23 @@ public abstract class SystemShortcut extends ItemInfo protected final ItemInfo mItemInfo; protected final View mOriginalView; + private final AbstractFloatingViewHelper mAbstractFloatingViewHelper; + public SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo, View originalView) { + this(iconResId, labelResId, target, itemInfo, originalView, + new AbstractFloatingViewHelper()); + } + + public SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo, + View originalView, AbstractFloatingViewHelper abstractFloatingViewHelper) { mIconResId = iconResId; mLabelResId = labelResId; mAccessibilityActionId = labelResId; mTarget = target; mItemInfo = itemInfo; mOriginalView = originalView; - } - - public SystemShortcut(SystemShortcut other) { - mIconResId = other.mIconResId; - mLabelResId = other.mLabelResId; - mAccessibilityActionId = other.mAccessibilityActionId; - mTarget = other.mTarget; - mItemInfo = other.mItemInfo; - mOriginalView = other.mOriginalView; + mAbstractFloatingViewHelper = abstractFloatingViewHelper; } public void setIconAndLabelFor(View iconView, TextView labelView) { @@ -178,7 +179,7 @@ public abstract class SystemShortcut extends ItemInfo @Override public void onClick(View view) { - dismissTaskMenuView(mTarget); + dismissTaskMenuView(); Rect sourceBounds = Utilities.getViewBounds(view); new PackageManagerHelper(view.getContext()).startDetailsActivityForInfo( mItemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle()); @@ -327,7 +328,7 @@ public abstract class SystemShortcut extends ItemInfo @Override public void onClick(View view) { - dismissTaskMenuView(mTarget); + dismissTaskMenuView(); mTarget.getStatsLogManager().logger() .withItemInfo(mItemInfo) .log(LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP); @@ -370,7 +371,7 @@ public abstract class SystemShortcut extends ItemInfo @Override public void onClick(View view) { - dismissTaskMenuView(mTarget); + dismissTaskMenuView(); SecondaryDropTarget.performUninstall(view.getContext(), mComponentName, mItemInfo); mTarget.getStatsLogManager() .logger() @@ -379,8 +380,8 @@ public abstract class SystemShortcut extends ItemInfo } } - public static void dismissTaskMenuView(T activity) { - AbstractFloatingView.closeOpenViews(activity, true, + protected void dismissTaskMenuView() { + mAbstractFloatingViewHelper.closeOpenViews(mTarget, true, AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE); } } diff --git a/tests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt b/tests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt new file mode 100644 index 0000000000..7ff544d9f7 --- /dev/null +++ b/tests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3 + +import android.view.View +import com.android.launcher3.dragndrop.DragLayer +import com.android.launcher3.views.ActivityContext +import org.junit.Before +import org.junit.Test +import org.mockito.kotlin.any +import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.verify +import org.mockito.kotlin.verifyZeroInteractions +import org.mockito.kotlin.whenever + +/** Test for AbstractFloatingViewHelper */ +class AbstractFloatingViewHelperTest { + private val activityContext: ActivityContext = mock() + private val dragLayer: DragLayer = mock() + private val view: View = mock() + private val folderView: AbstractFloatingView = mock() + private val taskMenuView: AbstractFloatingView = mock() + private val abstractFloatingViewHelper = AbstractFloatingViewHelper() + + @Before + fun setup() { + whenever(activityContext.dragLayer).thenReturn(dragLayer) + whenever(dragLayer.childCount).thenReturn(3) + whenever(dragLayer.getChildAt(0)).thenReturn(view) + whenever(dragLayer.getChildAt(1)).thenReturn(folderView) + whenever(dragLayer.getChildAt(2)).thenReturn(taskMenuView) + whenever(folderView.isOfType(any())).thenAnswer { + (it.getArgument(0) and AbstractFloatingView.TYPE_FOLDER) != 0 + } + whenever(taskMenuView.isOfType(any())).thenAnswer { + (it.getArgument(0) and AbstractFloatingView.TYPE_TASK_MENU) != 0 + } + } + + @Test + fun closeOpenViews_all() { + abstractFloatingViewHelper.closeOpenViews( + activityContext, + true, + AbstractFloatingView.TYPE_ALL + ) + + verifyZeroInteractions(view) + verify(folderView).close(true) + verify(taskMenuView).close(true) + } + + @Test + fun closeOpenViews_taskMenu() { + abstractFloatingViewHelper.closeOpenViews( + activityContext, + true, + AbstractFloatingView.TYPE_TASK_MENU + ) + + verifyZeroInteractions(view) + verify(folderView, never()).close(any()) + verify(taskMenuView).close(true) + } + + @Test + fun closeOpenViews_other() { + abstractFloatingViewHelper.closeOpenViews( + activityContext, + true, + AbstractFloatingView.TYPE_PIN_IME_POPUP + ) + + verifyZeroInteractions(view) + verify(folderView, never()).close(any()) + verify(taskMenuView, never()).close(any()) + } + + @Test + fun closeOpenViews_both_animationOff() { + abstractFloatingViewHelper.closeOpenViews( + activityContext, + false, + AbstractFloatingView.TYPE_FOLDER or AbstractFloatingView.TYPE_TASK_MENU + ) + + verifyZeroInteractions(view) + verify(folderView).close(false) + verify(taskMenuView).close(false) + } +} From 34bfc7a80bca363bf9cb6fd5caf747ba00d965a7 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Tue, 9 Apr 2024 17:45:30 +0100 Subject: [PATCH 05/20] Add debug log for TaskView.onClick Bug: 310064698 Test: manual Flag: None Change-Id: Ib772dd8995442d3b1af84aec0668b11828ab62e6 --- quickstep/src/com/android/quickstep/views/TaskView.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index cec09824bf..bd95a65a67 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -812,12 +812,18 @@ public class TaskView extends FrameLayout implements Reusable { private void onClick(View view) { if (getTask() == null) { + Log.d("b/310064698", "onClick - task is null"); return; } if (confirmSecondSplitSelectApp()) { + Log.d("b/310064698", mTask + " - onClick - split select is active"); return; } - launchTasks(); + RunnableList callbackList = launchTasks(); + Log.d("b/310064698", mTask + " - onClick - callbackList: " + callbackList); + if (callbackList != null) { + callbackList.add(() -> Log.d("b/310064698", mTask + " - onClick - launchCompleted")); + } mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo()) .log(LAUNCHER_TASK_LAUNCH_TAP); } From 45162f9cf0c8cc52a94cc1f86d9fb1e041d08470 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Tue, 9 Apr 2024 17:46:38 +0100 Subject: [PATCH 06/20] Add debug log for RecentsView touch down Bug: 318590728 Test: manual Flag: None Change-Id: I591ed74af748f0fe424e1b58b4f610a21a106124 --- .../src/com/android/quickstep/views/RecentsView.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index eca70b74ba..ddf6887f04 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -1503,6 +1503,15 @@ public abstract class RecentsView deviceProfile.availableWidthPx * SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE; } + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + boolean intercept = super.onInterceptTouchEvent(ev); + if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { + Log.d("b/318590728", "onInterceptTouchEvent: " + ev); + } + return intercept; + } + @Override public boolean onTouchEvent(MotionEvent ev) { super.onTouchEvent(ev); From 9b11c40b010770b9925414817ae68dd3eb839e41 Mon Sep 17 00:00:00 2001 From: Holly Sun Date: Thu, 4 Apr 2024 12:00:39 -0700 Subject: [PATCH 07/20] [omni] Read and use touch slop multiplier for LPNH. 1) This part is missing from the previous set of CLs. `getLPNHCustomSlopMultiplier` is defined but unused. Similar as reading LPNHDuration, we should also read the touch slot multiplier in Launcher for LPNH. 2) Also, change type to float, which is consistent with our existing implementation and the definition in OverviewProxyService. 3) Slop value is in percentage and Launcher divide it by 100. We haven't got AGSA implementation yet so we can predefine this part. Bug: 330444720 Bug: 330446188 Test: manual Flag: legacy CUSTOM_LPNH_THRESHOLDS disabled Change-Id: Id606a4bc765fe01464ef36a2806c280ee42d30cd --- .../android/quickstep/RecentsAnimationDeviceState.java | 8 +++++--- .../com/android/quickstep/util/AssistStateManager.java | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index 43e564cadf..4b4f914ed2 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -67,6 +67,7 @@ import com.android.launcher3.util.NavigationMode; import com.android.launcher3.util.SettingsCache; import com.android.quickstep.TopTaskTracker.CachedTaskInfo; import com.android.quickstep.util.ActiveGestureLog; +import com.android.quickstep.util.AssistStateManager; import com.android.quickstep.util.GestureExclusionManager; import com.android.quickstep.util.GestureExclusionManager.ExclusionListener; import com.android.quickstep.util.NavBarPosition; @@ -96,7 +97,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E private final DisplayController mDisplayController; private final GestureExclusionManager mExclusionManager; - + private final AssistStateManager mAssistStateManager; private final RotationTouchHelper mRotationTouchHelper; private final TaskStackChangeListener mPipListener; @@ -147,6 +148,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E mContext = context; mDisplayController = DisplayController.INSTANCE.get(context); mExclusionManager = exclusionManager; + mAssistStateManager = AssistStateManager.INSTANCE.get(context); mIsOneHandedModeSupported = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false); mRotationTouchHelper = RotationTouchHelper.INSTANCE.get(context); if (isInstanceForTouches) { @@ -587,8 +589,8 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E : QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON; float touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); - if (DeviceConfigWrapper.get().getCustomLpnhThresholds()) { - float customSlopMultiplier = DeviceConfigWrapper.get().getLpnhSlopPercentage() / 100f; + if (mAssistStateManager.getLPNHCustomSlopMultiplier().isPresent()) { + float customSlopMultiplier = mAssistStateManager.getLPNHCustomSlopMultiplier().get(); return customSlopMultiplier * slopMultiplier * touchSlop; } else { return slopMultiplier * touchSlop; diff --git a/quickstep/src/com/android/quickstep/util/AssistStateManager.java b/quickstep/src/com/android/quickstep/util/AssistStateManager.java index a1fdbbb127..87d51387ed 100644 --- a/quickstep/src/com/android/quickstep/util/AssistStateManager.java +++ b/quickstep/src/com/android/quickstep/util/AssistStateManager.java @@ -58,7 +58,7 @@ public class AssistStateManager implements ResourceBasedOverride { } /** Get the Launcher overridden long press touch slop multiplier to trigger Assistant. */ - public Optional getLPNHCustomSlopMultiplier() { + public Optional getLPNHCustomSlopMultiplier() { return Optional.empty(); } From 2dee591601577b861bdfefafe935583e1b6b2559 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Tue, 9 Apr 2024 14:04:34 -0400 Subject: [PATCH 08/20] Fix BinderTests#testSwitchToOverview This test has been failing because the "unexpected" Binder call is actually expected. Updated the test to account for this. Flag: N/A Fixes: 315075477 Test: BinderTests#testSwitchToOverview Change-Id: I2f5d3d07f6ec373f394e7a6f3887000af5f63c7e --- quickstep/src/com/android/quickstep/views/RecentsView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 2aa16a948a..1f52d1e1af 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -163,6 +163,7 @@ import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds; import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource; import com.android.launcher3.util.SplitConfigurationOptions.StagePosition; import com.android.launcher3.util.Themes; +import com.android.launcher3.util.TraceHelper; import com.android.launcher3.util.TranslateEdgeEffect; import com.android.launcher3.util.VibratorWrapper; import com.android.launcher3.util.ViewPool; @@ -4290,7 +4291,8 @@ public abstract class RecentsView mActivity.getDisplay().getRotation()); mOrientationState.setRecentsRotation(rotation); } From 11117d9b2a2a6469e9bd6addbf1c5ce6e1291b1c Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 25 Mar 2024 16:12:10 -0700 Subject: [PATCH 09/20] Using resource override instead of code-swap for ApiWrapper Bug: 330920490 Flag: None Test: Presubmit Change-Id: Iac19f32e64d2c76ed5b4f8592943ee4ae7af51b5 --- quickstep/res/values/config.xml | 1 + .../taskbar/TaskbarActivityContext.java | 4 +- .../launcher3/uioverrides/ApiWrapper.java | 201 ------------------ .../launcher3/uioverrides/SystemApiWrapper.kt | 133 ++++++++++++ res/values/config.xml | 1 + .../android/launcher3/AutoInstallsLayout.java | 4 +- src/com/android/launcher3/DeviceProfile.java | 5 +- .../allapps/PrivateProfileManager.java | 46 ++-- .../launcher3/dragndrop/AddItemActivity.java | 5 +- .../launcher3/model/PackageUpdatedTask.java | 4 +- .../launcher3/model/WorkspaceItemProcessor.kt | 4 +- .../model/data/ItemInfoWithIcon.java | 6 +- .../model/data/WorkspaceItemInfo.java | 4 +- src/com/android/launcher3/pm/UserCache.java | 4 +- .../launcher3/popup/SystemShortcut.java | 13 +- .../launcher3/provider/RestoreDbTask.java | 7 +- .../launcher3/touch/ItemClickHandler.java | 8 +- .../android/launcher3/util}/ApiWrapper.java | 56 +++-- .../launcher3/util/PackageManagerHelper.java | 11 +- .../util/window/WindowManagerProxy.java | 7 + .../launcher3/AbstractDeviceProfileTest.kt | 14 +- .../allapps/PrivateProfileManagerTest.java | 10 +- 22 files changed, 247 insertions(+), 301 deletions(-) delete mode 100644 quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java create mode 100644 quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt rename {src_no_quickstep/com/android/launcher3/uioverrides => src/com/android/launcher3/util}/ApiWrapper.java (68%) diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml index 31d40710bc..c4ee11a8d1 100644 --- a/quickstep/res/values/config.xml +++ b/quickstep/res/values/config.xml @@ -38,6 +38,7 @@ + com.android.launcher3.uioverrides.SystemApiWrapper diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 390dec9a66..98ce2edae4 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -113,8 +113,8 @@ import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.touch.ItemClickHandler.ItemClickProxy; -import com.android.launcher3.uioverrides.ApiWrapper; import com.android.launcher3.util.ActivityOptionsWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.Executors; @@ -1120,7 +1120,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } else if (info.isPromise()) { TestLogging.recordEvent( TestProtocol.SEQUENCE_MAIN, "start: taskbarPromiseIcon"); - intent = ApiWrapper.getAppMarketActivityIntent(this, + intent = ApiWrapper.INSTANCE.get(this).getAppMarketActivityIntent( info.getTargetPackage(), Process.myUserHandle()); startActivity(intent); diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java deleted file mode 100644 index 873dea80e3..0000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2017 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.uioverrides; - -import android.app.ActivityOptions; -import android.app.PendingIntent; -import android.app.Person; -import android.content.Context; -import android.content.Intent; -import android.content.IntentSender; -import android.content.pm.ActivityInfo; -import android.content.pm.LauncherActivityInfo; -import android.content.pm.LauncherApps; -import android.content.pm.LauncherUserInfo; -import android.content.pm.ShortcutInfo; -import android.graphics.drawable.ColorDrawable; -import android.net.Uri; -import android.os.UserHandle; -import android.os.UserManager; -import android.util.ArrayMap; -import android.window.RemoteTransition; - -import com.android.launcher3.Flags; -import com.android.launcher3.Utilities; -import com.android.launcher3.proxy.ProxyActivityStarter; -import com.android.launcher3.util.StartActivityParams; -import com.android.launcher3.util.UserIconInfo; -import com.android.quickstep.util.FadeOutRemoteTransition; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * A wrapper for the hidden API calls - */ -public class ApiWrapper { - - public static final boolean TASKBAR_DRAWN_IN_PROCESS = true; - - public static Person[] getPersons(ShortcutInfo si) { - Person[] persons = si.getPersons(); - return persons == null ? Utilities.EMPTY_PERSON_ARRAY : persons; - } - - public static Map getActivityOverrides(Context context) { - return context.getSystemService(LauncherApps.class).getActivityOverrides(); - } - - /** - * Creates an ActivityOptions to play fade-out animation on closing targets - */ - public static ActivityOptions createFadeOutAnimOptions(Context context) { - ActivityOptions options = ActivityOptions.makeBasic(); - options.setRemoteTransition(new RemoteTransition(new FadeOutRemoteTransition())); - return options; - } - - /** - * Returns a map of all users on the device to their corresponding UI properties - */ - public static Map queryAllUsers(Context context) { - UserManager um = context.getSystemService(UserManager.class); - Map users = new ArrayMap<>(); - List usersActual = um.getUserProfiles(); - if (usersActual != null) { - for (UserHandle user : usersActual) { - if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace()) { - LauncherApps launcherApps = context.getSystemService(LauncherApps.class); - LauncherUserInfo launcherUserInfo = launcherApps.getLauncherUserInfo(user); - if (launcherUserInfo == null) { - continue; - } - // UserTypes not supported in Launcher are deemed to be the current - // Foreground User. - int userType = switch (launcherUserInfo.getUserType()) { - case UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK; - case UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED; - case UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE; - default -> UserIconInfo.TYPE_MAIN; - }; - long serial = launcherUserInfo.getUserSerialNumber(); - users.put(user, new UserIconInfo(user, userType, serial)); - } else { - long serial = um.getSerialNumberForUser(user); - - // Simple check to check if the provided user is work profile - // TODO: Migrate to a better platform API - NoopDrawable d = new NoopDrawable(); - boolean isWork = (d != context.getPackageManager().getUserBadgedIcon(d, user)); - UserIconInfo info = new UserIconInfo( - user, - isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN, - serial); - users.put(user, info); - } - } - } - return users; - } - - /** - * Returns the list of the system packages that are installed at user creation. - * An empty list denotes that all system packages are installed for that user at creation. - */ - public static List getPreInstalledSystemPackages(Context context, UserHandle user) { - LauncherApps launcherApps = context.getSystemService(LauncherApps.class); - if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace() - && Flags.privateSpaceSysAppsSeparation()) { - return launcherApps.getPreInstalledSystemPackages(user); - } else { - return new ArrayList<>(); - } - } - - /** - * Returns an intent which can be used to start the App Market activity (Installer - * Activity). - */ - public static Intent getAppMarketActivityIntent(Context context, String packageName, - UserHandle user) { - LauncherApps launcherApps = context.getSystemService(LauncherApps.class); - if (android.os.Flags.allowPrivateProfile() - && Flags.enablePrivateSpace() - && (Flags.privateSpaceAppInstallerButton() - || Flags.enablePrivateSpaceInstallShortcut())) { - StartActivityParams params = new StartActivityParams((PendingIntent) null, 0); - params.intentSender = launcherApps.getAppMarketActivityIntent(packageName, user); - ActivityOptions options = ActivityOptions.makeBasic() - .setPendingIntentBackgroundActivityStartMode(ActivityOptions - .MODE_BACKGROUND_ACTIVITY_START_ALLOWED); - params.options = options.toBundle(); - params.requireActivityResult = false; - return ProxyActivityStarter.getLaunchIntent(context, params); - } else { - return new Intent(Intent.ACTION_VIEW) - .setData(new Uri.Builder() - .scheme("market") - .authority("details") - .appendQueryParameter("id", packageName) - .build()) - .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app") - .authority(context.getPackageName()).build()); - } - } - - /** - * Returns an intent which can be used to open Private Space Settings. - */ - public static Intent getPrivateSpaceSettingsIntent(Context context) { - if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace()) { - LauncherApps launcherApps = context.getSystemService(LauncherApps.class); - IntentSender intentSender = launcherApps.getPrivateSpaceSettingsIntent(); - if (intentSender == null) { - return null; - } - StartActivityParams params = new StartActivityParams((PendingIntent) null, 0); - params.intentSender = intentSender; - ActivityOptions options = ActivityOptions.makeBasic() - .setPendingIntentBackgroundActivityStartMode(ActivityOptions - .MODE_BACKGROUND_ACTIVITY_START_ALLOWED); - params.options = options.toBundle(); - params.requireActivityResult = false; - return ProxyActivityStarter.getLaunchIntent(context, params); - } - return null; - } - - /** - * Checks if an activity is flagged as non-resizeable. - */ - public static boolean isNonResizeableActivity(LauncherActivityInfo lai) { - return lai.getActivityInfo().resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE; - } - - private static class NoopDrawable extends ColorDrawable { - @Override - public int getIntrinsicHeight() { - return 1; - } - - @Override - public int getIntrinsicWidth() { - return 1; - } - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt new file mode 100644 index 0000000000..535b4c2986 --- /dev/null +++ b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2024 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.uioverrides + +import android.app.ActivityOptions +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.content.pm.ActivityInfo +import android.content.pm.LauncherActivityInfo +import android.content.pm.LauncherApps +import android.content.pm.ShortcutInfo +import android.os.Flags.allowPrivateProfile +import android.os.UserHandle +import android.os.UserManager +import android.util.ArrayMap +import android.window.RemoteTransition +import com.android.launcher3.Flags.enablePrivateSpace +import com.android.launcher3.Flags.enablePrivateSpaceInstallShortcut +import com.android.launcher3.Flags.privateSpaceAppInstallerButton +import com.android.launcher3.Flags.privateSpaceSysAppsSeparation +import com.android.launcher3.Utilities +import com.android.launcher3.proxy.ProxyActivityStarter +import com.android.launcher3.util.ApiWrapper +import com.android.launcher3.util.StartActivityParams +import com.android.launcher3.util.UserIconInfo +import com.android.quickstep.util.FadeOutRemoteTransition + +/** A wrapper for the hidden API calls */ +class SystemApiWrapper(context: Context?) : ApiWrapper(context) { + + override fun getPersons(si: ShortcutInfo) = si.persons ?: Utilities.EMPTY_PERSON_ARRAY + + override fun getActivityOverrides(): Map = + mContext.getSystemService(LauncherApps::class.java)!!.activityOverrides + + override fun createFadeOutAnimOptions(): ActivityOptions = + ActivityOptions.makeBasic().apply { + remoteTransition = RemoteTransition(FadeOutRemoteTransition()) + } + + override fun queryAllUsers(): Map { + if (!allowPrivateProfile() || !enablePrivateSpace()) { + return super.queryAllUsers() + } + val users = ArrayMap() + mContext.getSystemService(UserManager::class.java)!!.userProfiles?.forEach { user -> + mContext.getSystemService(LauncherApps::class.java)!!.getLauncherUserInfo(user)?.apply { + users[user] = + UserIconInfo( + user, + when (userType) { + UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK + UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED + UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE + else -> UserIconInfo.TYPE_MAIN + }, + userSerialNumber.toLong() + ) + } + } + return users + } + + override fun getPreInstalledSystemPackages(user: UserHandle): List = + if (allowPrivateProfile() && enablePrivateSpace() && privateSpaceSysAppsSeparation()) + mContext + .getSystemService(LauncherApps::class.java)!! + .getPreInstalledSystemPackages(user) + else ArrayList() + + override fun getAppMarketActivityIntent(packageName: String, user: UserHandle): Intent = + if ( + allowPrivateProfile() && + enablePrivateSpace() && + (privateSpaceAppInstallerButton() || enablePrivateSpaceInstallShortcut()) + ) + ProxyActivityStarter.getLaunchIntent( + mContext, + StartActivityParams(null as PendingIntent?, 0).apply { + intentSender = + mContext + .getSystemService(LauncherApps::class.java)!! + .getAppMarketActivityIntent(packageName, user) + options = + ActivityOptions.makeBasic() + .setPendingIntentBackgroundActivityStartMode( + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED + ) + .toBundle() + requireActivityResult = false + } + ) + else super.getAppMarketActivityIntent(packageName, user) + + /** Returns an intent which can be used to open Private Space Settings. */ + override fun getPrivateSpaceSettingsIntent(): Intent? = + if (allowPrivateProfile() && enablePrivateSpace()) + ProxyActivityStarter.getLaunchIntent( + mContext, + StartActivityParams(null as PendingIntent?, 0).apply { + intentSender = + mContext + .getSystemService(LauncherApps::class.java) + ?.privateSpaceSettingsIntent + ?: return null + options = + ActivityOptions.makeBasic() + .setPendingIntentBackgroundActivityStartMode( + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED + ) + .toBundle() + requireActivityResult = false + } + ) + else null + + override fun isNonResizeableActivity(lai: LauncherActivityInfo) = + lai.activityInfo.resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE +} diff --git a/res/values/config.xml b/res/values/config.xml index 599584b64b..f820e763fb 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -78,6 +78,7 @@ + diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java index c7cdfa8c69..cf865288c4 100644 --- a/src/com/android/launcher3/AutoInstallsLayout.java +++ b/src/com/android/launcher3/AutoInstallsLayout.java @@ -52,7 +52,7 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.qsb.QsbContainerView; import com.android.launcher3.shortcuts.ShortcutKey; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.Partner; import com.android.launcher3.util.Thunk; @@ -203,7 +203,7 @@ public class AutoInstallsLayout { mIdp = LauncherAppState.getIDP(context); mRowCount = mIdp.numRows; mColumnCount = mIdp.numColumns; - mActivityOverride = ApiWrapper.getActivityOverrides(context); + mActivityOverride = ApiWrapper.INSTANCE.get(context).getActivityOverrides(); } /** diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 3ddc7aa5e7..6cb33a8c29 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -63,13 +63,13 @@ import com.android.launcher3.responsive.ResponsiveCellSpecsProvider; import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType; import com.android.launcher3.responsive.ResponsiveSpec.DimensionType; import com.android.launcher3.responsive.ResponsiveSpecsProvider; -import com.android.launcher3.uioverrides.ApiWrapper; import com.android.launcher3.util.CellContentDimensions; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.IconSizeSteps; import com.android.launcher3.util.ResourceHelper; import com.android.launcher3.util.WindowBounds; +import com.android.launcher3.util.window.WindowManagerProxy; import java.io.PrintWriter; import java.util.Locale; @@ -350,7 +350,8 @@ public class DeviceProfile { isTablet = info.isTablet(windowBounds); isPhone = !isTablet; isTwoPanels = isTablet && isMultiDisplay; - isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS; + isTaskbarPresent = isTablet + && WindowManagerProxy.INSTANCE.get(context).isTaskbarDrawnInProcess(); // Some more constants. context = getContext(context, info, isVerticalBarLayout() || (isTablet && isLandscape) diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java index be120cce75..1def8a33ac 100644 --- a/src/com/android/launcher3/allapps/PrivateProfileManager.java +++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java @@ -72,7 +72,7 @@ import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.PrivateSpaceInstallAppButtonInfo; import com.android.launcher3.pm.UserCache; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.Preconditions; import com.android.launcher3.util.SettingsCache; import com.android.launcher3.views.ActivityContext; @@ -122,7 +122,9 @@ public class PrivateProfileManager extends UserProfileManager { super(userManager, statsLogManager, userCache); mAllApps = allApps; mPrivateProfileMatcher = (user) -> userCache.getUserInfo(user).isPrivate(); - UI_HELPER_EXECUTOR.post(this::initializeInBackgroundThread); + + Context appContext = allApps.getContext().getApplicationContext(); + UI_HELPER_EXECUTOR.post(() -> initializeInBackgroundThread(appContext)); mPsHeaderHeight = mAllApps.getContext().getResources().getDimensionPixelSize( R.dimen.ps_header_height); } @@ -187,7 +189,7 @@ public class PrivateProfileManager extends UserProfileManager { /** Whether private profile should be hidden on Launcher. */ public boolean isPrivateSpaceHidden() { return getCurrentState() == STATE_DISABLED && SettingsCache.INSTANCE - .get(mAllApps.mActivityContext).getValue(PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI, 0); + .get(mAllApps.getContext()).getValue(PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI, 0); } /** @@ -215,8 +217,8 @@ public class PrivateProfileManager extends UserProfileManager { /** Opens the Private Space Settings Page. */ public void openPrivateSpaceSettings() { if (mPrivateSpaceSettingsAvailable) { - mAllApps.getContext() - .startActivity(ApiWrapper.getPrivateSpaceSettingsIntent(mAllApps.getContext())); + mAllApps.getContext().startActivity( + ApiWrapper.INSTANCE.get(mAllApps.getContext()).getPrivateSpaceSettingsIntent()); } } @@ -239,33 +241,17 @@ public class PrivateProfileManager extends UserProfileManager { * This case should still be ok, as locking the Private Space container and unlocking it, * reloads the values, fixing the incorrect UI. */ - private void initializeInBackgroundThread() { + private void initializeInBackgroundThread(Context appContext) { Preconditions.assertNonUiThread(); - setPreInstalledSystemPackages(); - setAppInstallerIntent(); - initializePrivateSpaceSettingsState(); - } - - private void initializePrivateSpaceSettingsState() { - Preconditions.assertNonUiThread(); - Intent psSettingsIntent = ApiWrapper.getPrivateSpaceSettingsIntent(mAllApps.getContext()); - setPrivateSpaceSettingsAvailable(psSettingsIntent != null); - } - - private void setPreInstalledSystemPackages() { - Preconditions.assertNonUiThread(); - if (getProfileUser() != null) { - mPreInstalledSystemPackages = new HashSet<>(ApiWrapper - .getPreInstalledSystemPackages(mAllApps.getContext(), getProfileUser())); - } - } - - private void setAppInstallerIntent() { - Preconditions.assertNonUiThread(); - if (getProfileUser() != null) { - mAppInstallerIntent = ApiWrapper.getAppMarketActivityIntent(mAllApps.getContext(), - BuildConfig.APPLICATION_ID, getProfileUser()); + ApiWrapper apiWrapper = ApiWrapper.INSTANCE.get(appContext); + UserHandle profileUser = getProfileUser(); + if (profileUser != null) { + mPreInstalledSystemPackages = new HashSet<>( + apiWrapper.getPreInstalledSystemPackages(profileUser)); + mAppInstallerIntent = apiWrapper + .getAppMarketActivityIntent(BuildConfig.APPLICATION_ID, profileUser); } + setPrivateSpaceSettingsAvailable(apiWrapper.getPrivateSpaceSettingsIntent() != null); } @VisibleForTesting diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java index 29aa216a3b..05fdcef461 100644 --- a/src/com/android/launcher3/dragndrop/AddItemActivity.java +++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java @@ -67,7 +67,7 @@ import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.PackageItemInfo; import com.android.launcher3.pm.PinRequestHelper; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.views.AbstractSlideInView; @@ -259,7 +259,8 @@ public class AddItemActivity extends BaseActivity .setPackage(getPackageName()) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Launcher.ACTIVITY_TRACKER.registerCallback(listener, "AddItemActivity.onLongClick"); - startActivity(homeIntent, ApiWrapper.createFadeOutAnimOptions(this).toBundle()); + startActivity(homeIntent, + ApiWrapper.INSTANCE.get(this).createFadeOutAnimOptions().toBundle()); logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_DRAGGED); mFinishOnPause = true; return false; diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index ea1ae2ed24..e42e67924b 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -48,7 +48,7 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.PackageInstallInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.shortcuts.ShortcutRequest; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.FlagOp; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ItemInfoMatcher; @@ -286,7 +286,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { } if (si.itemType == Favorites.ITEM_TYPE_APPLICATION) { if (activities != null && !activities.isEmpty()) { - si.status = ApiWrapper + si.status = ApiWrapper.INSTANCE.get(context) .isNonResizeableActivity(activities.get(0)) ? si.status | WorkspaceItemInfo.FLAG_NON_RESIZEABLE : si.status & ~WorkspaceItemInfo.FLAG_NON_RESIZEABLE; diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt index a900d1fa55..ff95bbbb73 100644 --- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt +++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt @@ -41,7 +41,7 @@ import com.android.launcher3.model.data.LauncherAppWidgetInfo import com.android.launcher3.model.data.WorkspaceItemInfo import com.android.launcher3.pm.PackageInstallInfo import com.android.launcher3.shortcuts.ShortcutKey -import com.android.launcher3.uioverrides.ApiWrapper +import com.android.launcher3.util.ApiWrapper import com.android.launcher3.util.ComponentKey import com.android.launcher3.util.PackageManagerHelper import com.android.launcher3.util.PackageUserKey @@ -325,7 +325,7 @@ class WorkspaceItemProcessor( } val activityInfo = c.launcherActivityInfo if (activityInfo != null) { - if (ApiWrapper.isNonResizeableActivity(activityInfo)) { + if (ApiWrapper.INSTANCE.get(app.context).isNonResizeableActivity(activityInfo)) { info.status = info.status or WorkspaceItemInfo.FLAG_NON_RESIZEABLE } info.setProgressLevel( diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java index be3aa101ac..faeed29c78 100644 --- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java +++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java @@ -28,7 +28,7 @@ import com.android.launcher3.icons.BitmapInfo.DrawableCreationFlags; import com.android.launcher3.icons.FastBitmapDrawable; import com.android.launcher3.logging.FileLog; import com.android.launcher3.pm.PackageInstallInfo; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; /** * Represents an ItemInfo which also holds an icon. @@ -251,8 +251,8 @@ public abstract class ItemInfoWithIcon extends ItemInfo { String targetPackage = getTargetPackage(); return targetPackage != null - ? ApiWrapper.getAppMarketActivityIntent( - context, targetPackage, Process.myUserHandle()) + ? ApiWrapper.INSTANCE.get(context).getAppMarketActivityIntent( + targetPackage, Process.myUserHandle()) : null; } diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java index 9917ad7a64..5ae70039ab 100644 --- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java +++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java @@ -32,7 +32,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.icons.IconCache; import com.android.launcher3.pm.UserCache; import com.android.launcher3.shortcuts.ShortcutKey; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ContentWriter; import java.util.Arrays; @@ -201,7 +201,7 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon { runtimeStatusFlags &= ~FLAG_DISABLED_VERSION_LOWER; } - Person[] persons = ApiWrapper.getPersons(shortcutInfo); + Person[] persons = ApiWrapper.INSTANCE.get(context).getPersons(shortcutInfo); personKeys = persons.length == 0 ? Utilities.EMPTY_STRING_ARRAY : Arrays.stream(persons).map(Person::getKey).sorted().toArray(String[]::new); } diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java index 032de31ed7..185e0b55bd 100644 --- a/src/com/android/launcher3/pm/UserCache.java +++ b/src/com/android/launcher3/pm/UserCache.java @@ -17,7 +17,6 @@ package com.android.launcher3.pm; import static com.android.launcher3.Utilities.ATLEAST_U; -import static com.android.launcher3.uioverrides.ApiWrapper.queryAllUsers; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.content.Context; @@ -34,6 +33,7 @@ import androidx.annotation.WorkerThread; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.UserBadgeDrawable; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.FlagOp; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.SafeCloseable; @@ -119,7 +119,7 @@ public class UserCache implements SafeCloseable { @WorkerThread private void updateCache() { - mUserToSerialMap = queryAllUsers(mContext); + mUserToSerialMap = ApiWrapper.INSTANCE.get(mContext).queryAllUsers(); } /** diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java index 0af7e677ed..0c5a0ec171 100644 --- a/src/com/android/launcher3/popup/SystemShortcut.java +++ b/src/com/android/launcher3/popup/SystemShortcut.java @@ -31,7 +31,7 @@ import com.android.launcher3.model.WidgetItem; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.UserCache; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.util.PackageManagerHelper; @@ -259,10 +259,8 @@ public abstract class SystemShortcut extends ItemInfo @Override public void onClick(View view) { Intent intent = - ApiWrapper.getAppMarketActivityIntent( - view.getContext(), - mItemInfo.getTargetComponent().getPackageName(), - mSpaceUser); + ApiWrapper.INSTANCE.get(view.getContext()).getAppMarketActivityIntent( + mItemInfo.getTargetComponent().getPackageName(), mSpaceUser); mTarget.startActivitySafely(view, intent, mItemInfo); AbstractFloatingView.closeAllOpenViews(mTarget); mTarget.getStatsLogManager() @@ -303,9 +301,8 @@ public abstract class SystemShortcut extends ItemInfo @Override public void onClick(View view) { - Intent intent = ApiWrapper.getAppMarketActivityIntent(view.getContext(), - mItemInfo.getTargetComponent().getPackageName(), - Process.myUserHandle()); + Intent intent = ApiWrapper.INSTANCE.get(view.getContext()).getAppMarketActivityIntent( + mItemInfo.getTargetComponent().getPackageName(), Process.myUserHandle()); mTarget.startActivitySafely(view, intent, mItemInfo); AbstractFloatingView.closeAllOpenViews(mTarget); } diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java index b4e6365d66..d702e51881 100644 --- a/src/com/android/launcher3/provider/RestoreDbTask.java +++ b/src/com/android/launcher3/provider/RestoreDbTask.java @@ -70,7 +70,7 @@ import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ContentWriter; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.LogConfig; @@ -560,9 +560,8 @@ public class RestoreDbTask { protected static void maybeOverrideShortcuts(Context context, ModelDbController controller, SQLiteDatabase db, long currentUser) { - Map activityOverrides = ApiWrapper.getActivityOverrides( - context); - + Map activityOverrides = + ApiWrapper.INSTANCE.get(context).getActivityOverrides(); if (activityOverrides == null || activityOverrides.isEmpty()) { return; } diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java index 50df7757ec..49ec0cb3f4 100644 --- a/src/com/android/launcher3/touch/ItemClickHandler.java +++ b/src/com/android/launcher3/touch/ItemClickHandler.java @@ -63,7 +63,7 @@ import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.views.FloatingIconView; import com.android.launcher3.views.Snackbar; @@ -234,7 +234,7 @@ public class ItemClickHandler { } } // Fallback to using custom market intent. - Intent intent = ApiWrapper.getAppMarketActivityIntent(launcher, + Intent intent = ApiWrapper.INSTANCE.get(launcher).getAppMarketActivityIntent( packageName, Process.myUserHandle()); launcher.startActivitySafely(v, intent, item); }; @@ -372,12 +372,12 @@ public class ItemClickHandler { if (item instanceof ItemInfoWithIcon itemInfoWithIcon) { if ((itemInfoWithIcon.runtimeStatusFlags & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) { - intent = ApiWrapper.getAppMarketActivityIntent(launcher, + intent = ApiWrapper.INSTANCE.get(launcher).getAppMarketActivityIntent( itemInfoWithIcon.getTargetComponent().getPackageName(), Process.myUserHandle()); } else if (itemInfoWithIcon.itemType == LauncherSettings.Favorites.ITEM_TYPE_PRIVATE_SPACE_INSTALL_APP_BUTTON) { - intent = ApiWrapper.getAppMarketActivityIntent(launcher, + intent = ApiWrapper.INSTANCE.get(launcher).getAppMarketActivityIntent( BuildConfig.APPLICATION_ID, launcher.getAppsView().getPrivateProfileManager().getProfileUser()); launcher.getStatsLogManager().logger().log( diff --git a/src_no_quickstep/com/android/launcher3/uioverrides/ApiWrapper.java b/src/com/android/launcher3/util/ApiWrapper.java similarity index 68% rename from src_no_quickstep/com/android/launcher3/uioverrides/ApiWrapper.java rename to src/com/android/launcher3/util/ApiWrapper.java index 90271c1cae..6429a437bf 100644 --- a/src_no_quickstep/com/android/launcher3/uioverrides/ApiWrapper.java +++ b/src/com/android/launcher3/util/ApiWrapper.java @@ -14,7 +14,9 @@ * limitations under the License. */ -package com.android.launcher3.uioverrides; +package com.android.launcher3.util; + +import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; import android.app.ActivityOptions; import android.app.Person; @@ -28,10 +30,12 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.ArrayMap; -import com.android.launcher3.Utilities; -import com.android.launcher3.util.UserIconInfo; +import androidx.annotation.Nullable; + +import com.android.launcher3.BuildConfig; +import com.android.launcher3.R; +import com.android.launcher3.Utilities; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -39,30 +43,40 @@ import java.util.Map; /** * A wrapper for the hidden API calls */ -public class ApiWrapper { +public class ApiWrapper implements ResourceBasedOverride, SafeCloseable { - public static final boolean TASKBAR_DRAWN_IN_PROCESS = false; + public static final MainThreadInitializedObject INSTANCE = + forOverride(ApiWrapper.class, R.string.api_wrapper_class); - public static Person[] getPersons(ShortcutInfo si) { + protected final Context mContext; + + public ApiWrapper(Context context) { + mContext = context; + } + + /** + * Returns the list of persons associated with the provided shortcut info + */ + public Person[] getPersons(ShortcutInfo si) { return Utilities.EMPTY_PERSON_ARRAY; } - public static Map getActivityOverrides(Context context) { + public Map getActivityOverrides() { return Collections.emptyMap(); } /** * Creates an ActivityOptions to play fade-out animation on closing targets */ - public static ActivityOptions createFadeOutAnimOptions(Context context) { - return ActivityOptions.makeCustomAnimation(context, 0, android.R.anim.fade_out); + public ActivityOptions createFadeOutAnimOptions() { + return ActivityOptions.makeCustomAnimation(mContext, 0, android.R.anim.fade_out); } /** * Returns a map of all users on the device to their corresponding UI properties */ - public static Map queryAllUsers(Context context) { - UserManager um = context.getSystemService(UserManager.class); + public Map queryAllUsers() { + UserManager um = mContext.getSystemService(UserManager.class); Map users = new ArrayMap<>(); List usersActual = um.getUserProfiles(); if (usersActual != null) { @@ -72,7 +86,7 @@ public class ApiWrapper { // Simple check to check if the provided user is work profile // TODO: Migrate to a better platform API NoopDrawable d = new NoopDrawable(); - boolean isWork = (d != context.getPackageManager().getUserBadgedIcon(d, user)); + boolean isWork = (d != mContext.getPackageManager().getUserBadgedIcon(d, user)); UserIconInfo info = new UserIconInfo( user, isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN, @@ -87,16 +101,15 @@ public class ApiWrapper { * Returns the list of the system packages that are installed at user creation. * An empty list denotes that all system packages are installed for that user at creation. */ - public static List getPreInstalledSystemPackages(Context context, UserHandle user) { - return new ArrayList<>(); + public List getPreInstalledSystemPackages(UserHandle user) { + return Collections.emptyList(); } /** * Returns an intent which can be used to start the App Market activity (Installer * Activity). */ - public static Intent getAppMarketActivityIntent(Context context, String packageName, - UserHandle user) { + public Intent getAppMarketActivityIntent(String packageName, UserHandle user) { return new Intent(Intent.ACTION_VIEW) .setData(new Uri.Builder() .scheme("market") @@ -104,24 +117,27 @@ public class ApiWrapper { .appendQueryParameter("id", packageName) .build()) .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app") - .authority(context.getPackageName()).build()); + .authority(BuildConfig.APPLICATION_ID).build()); } /** * Returns an intent which can be used to open Private Space Settings. */ - public static Intent getPrivateSpaceSettingsIntent(Context context) { + @Nullable + public Intent getPrivateSpaceSettingsIntent() { return null; } /** * Checks if an activity is flagged as non-resizeable. */ - public static boolean isNonResizeableActivity(LauncherActivityInfo lai) { + public boolean isNonResizeableActivity(LauncherActivityInfo lai) { // Overridden in quickstep return false; } + @Override + public void close() { } private static class NoopDrawable extends ColorDrawable { @Override diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java index 316506ab4a..6ed875de91 100644 --- a/src/com/android/launcher3/util/PackageManagerHelper.java +++ b/src/com/android/launcher3/util/PackageManagerHelper.java @@ -16,6 +16,8 @@ package com.android.launcher3.util; +import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE; + import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; @@ -46,7 +48,6 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; -import com.android.launcher3.uioverrides.ApiWrapper; import java.util.List; import java.util.Objects; @@ -169,11 +170,9 @@ public class PackageManagerHelper { * Starts the details activity for {@code info} */ public void startDetailsActivityForInfo(ItemInfo info, Rect sourceBounds, Bundle opts) { - if (info instanceof ItemInfoWithIcon - && (((ItemInfoWithIcon) info).runtimeStatusFlags - & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) { - ItemInfoWithIcon appInfo = (ItemInfoWithIcon) info; - mContext.startActivity(ApiWrapper.getAppMarketActivityIntent(mContext, + if (info instanceof ItemInfoWithIcon appInfo + && (appInfo.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) { + mContext.startActivity(ApiWrapper.INSTANCE.get(mContext).getAppMarketActivityIntent( appInfo.getTargetComponent().getPackageName(), Process.myUserHandle())); return; } diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java index 4a906d33e1..998191e7fc 100644 --- a/src/com/android/launcher3/util/window/WindowManagerProxy.java +++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java @@ -93,6 +93,13 @@ public class WindowManagerProxy implements ResourceBasedOverride { mTaskbarDrawnInProcess = taskbarDrawnInProcess; } + /** + * Returns true if taskbar is drawn in process + */ + public boolean isTaskbarDrawnInProcess() { + return mTaskbarDrawnInProcess; + } + /** * Returns a map of normalized info of internal displays to estimated window bounds * for that display diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt index ffcf83f303..577334bec3 100644 --- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt +++ b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt @@ -38,17 +38,18 @@ import com.android.launcher3.util.rule.setFlags import com.android.launcher3.util.window.CachedDisplayInfo import com.android.launcher3.util.window.WindowManagerProxy import com.google.common.truth.Truth -import org.junit.Rule -import org.mockito.kotlin.any -import org.mockito.kotlin.mock -import org.mockito.kotlin.spy -import org.mockito.kotlin.whenever import java.io.BufferedReader import java.io.File import java.io.PrintWriter import java.io.StringWriter import kotlin.math.max import kotlin.math.min +import org.junit.Rule +import org.mockito.kotlin.any +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.spy +import org.mockito.kotlin.whenever /** * This is an abstract class for DeviceProfile tests that create an InvariantDeviceProfile based on @@ -286,6 +287,9 @@ abstract class AbstractDeviceProfileTest { .thenReturn( if (isGestureMode) NavigationMode.NO_BUTTON else NavigationMode.THREE_BUTTONS ) + doReturn(WindowManagerProxy.INSTANCE[runningContext].isTaskbarDrawnInProcess) + .whenever(windowManagerProxy) + .isTaskbarDrawnInProcess() val density = densityDpi / DisplayMetrics.DENSITY_DEFAULT.toFloat() val config = diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java index e9d2f6e61a..8f398a66ff 100644 --- a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java +++ b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java @@ -47,8 +47,8 @@ import androidx.test.runner.AndroidJUnit4; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.pm.UserCache; -import com.android.launcher3.uioverrides.ApiWrapper; import com.android.launcher3.util.ActivityContextWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.UserIconInfo; import com.android.launcher3.util.rule.TestStabilityRule; @@ -108,7 +108,8 @@ public class PrivateProfileManagerTest { when(mUserCache.getUserInfo(Process.myUserHandle())).thenReturn(MAIN_ICON_INFO); when(mUserCache.getUserInfo(PRIVATE_HANDLE)).thenReturn(PRIVATE_ICON_INFO); when(mAllApps.getContext()).thenReturn(mContext); - when(mAllApps.getContext().getResources()).thenReturn(mResources); + when(mContext.getResources()).thenReturn(mResources); + when(mContext.getApplicationContext()).thenReturn(getApplicationContext()); when(mAllApps.getAppsStore()).thenReturn(mAllAppsStore); when(mAllApps.getActiveRecyclerView()).thenReturn(mAllAppsRecyclerView); when(mContext.getPackageManager()).thenReturn(mPackageManager); @@ -200,14 +201,15 @@ public class PrivateProfileManagerTest { @Test public void openPrivateSpaceSettings_triggersCorrectIntent() { - Intent expectedIntent = ApiWrapper.getPrivateSpaceSettingsIntent(mContext); + Intent expectedIntent = ApiWrapper.INSTANCE.get(mContext).getPrivateSpaceSettingsIntent(); ArgumentCaptor acIntent = ArgumentCaptor.forClass(Intent.class); mPrivateProfileManager.setPrivateSpaceSettingsAvailable(true); mPrivateProfileManager.openPrivateSpaceSettings(); Mockito.verify(mContext).startActivity(acIntent.capture()); - assertEquals("Intent Action is different", expectedIntent, acIntent.getValue()); + assertEquals("Intent Action is different", + expectedIntent.toUri(0), acIntent.getValue().toUri(0)); } private static void awaitTasksCompleted() throws Exception { From 59ab86218b7af461dd6afcc25616f04984c6ea13 Mon Sep 17 00:00:00 2001 From: Anushree Ganjam Date: Tue, 9 Apr 2024 10:52:42 -0700 Subject: [PATCH 10/20] Fill CellX , CellY and Rank for predictionRowView iteminfo. HotseatPreditionController already does this: https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:packages/apps/Launcher3/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java;l=239;drc=fe3f542e614df52cdcfa761074dd52957788a670;bpv=0;bpt=0 PreparePredictionInfo: https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:packages/apps/Launcher3/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java;l=413-419;drc=6cdf7ce91a2643e02156d5ab8fb0f1c416f80c29;bpv=0;bpt=0 adb shell dumpsys activity NexusLauncherActivity Before: https://paste.googleplex.com/4907497231482880 After: https://paste.googleplex.com/5157313861648384 Test: Manual Flag: NA Bug: 332171918 Change-Id: Ic9522238b2df06eb7c96b7f8961bc174fae17c9c --- .../android/launcher3/appprediction/PredictionRowView.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java index 3e9272d435..70e01f53a0 100644 --- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java +++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java @@ -240,7 +240,11 @@ public class PredictionRowView icon.reset(); if (predictionCount > i) { icon.setVisibility(View.VISIBLE); - icon.applyFromWorkspaceItem(mPredictedApps.get(i)); + WorkspaceItemInfo predictedItem = mPredictedApps.get(i); + predictedItem.rank = i; + predictedItem.cellX = i; + predictedItem.cellY = 0; + icon.applyFromWorkspaceItem(predictedItem); } else { icon.setVisibility(predictionCount == 0 ? GONE : INVISIBLE); } From 0d400993a9383c21c73ecbee79f4775a88f500a7 Mon Sep 17 00:00:00 2001 From: Himanshu Gupta Date: Mon, 8 Apr 2024 14:48:59 +0100 Subject: [PATCH 11/20] Adding TAPL tests for Private Space in Quickstep. This CL adds an initial test, that creates private profile and verifies the elements present in unlocked state. More tests will be followed in next CL. Doc: go/private-space-tapl Bug: 322882655 Test: TaplPrivateSpaceTest Flag: NA Change-Id: I6032f4531818031991a5d51e23cfad22518250e6 --- .../quickstep/TaplPrivateSpaceTest.java | 146 ++++++++++++++++++ .../com/android/launcher3/tapl/AllApps.java | 8 + .../launcher3/tapl/PrivateSpaceContainer.java | 60 +++++++ .../launcher3/tapl/PrivateSpaceHeader.java | 77 +++++++++ 4 files changed, 291 insertions(+) create mode 100644 quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java create mode 100644 tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java create mode 100644 tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java new file mode 100644 index 0000000000..0c143b4b70 --- /dev/null +++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.quickstep; + +import static com.android.launcher3.LauncherState.ALL_APPS; +import static com.android.launcher3.LauncherState.NORMAL; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import android.util.Log; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.LargeTest; + +import com.android.launcher3.tapl.LauncherInstrumentation; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.util.Objects; + +@LargeTest +@RunWith(AndroidJUnit4.class) +public class TaplPrivateSpaceTest extends AbstractQuickStepTest { + + private int mProfileUserId; + private boolean mPrivateProfileSetupSuccessful; + private static final String TAG = "TaplPrivateSpaceTest"; + + @Override + public void setUp() throws Exception { + super.setUp(); + initialize(this); + + createAndStartPrivateProfileUser(); + assumeTrue("Private Profile Setup not successful, aborting", + mPrivateProfileSetupSuccessful); + + mDevice.pressHome(); + waitForLauncherCondition("Launcher didn't start", Objects::nonNull); + waitForStateTransitionToEnd("Launcher internal state didn't switch to Normal", + () -> NORMAL); + waitForResumed("Launcher internal state is still Background"); + mLauncher.getWorkspace().switchToAllApps(); + waitForStateTransitionToEnd("Launcher internal state didn't switch to All Apps", + () -> ALL_APPS); + + // Wait for Private Space being available in Launcher. + waitForPrivateSpaceSetup(); + // Wait for Launcher UI to be updated with Private Space Items. + waitForLauncherUIUpdate(); + } + + private void createAndStartPrivateProfileUser() { + String createUserOutput = executeShellCommand("pm create-user --profileOf 0 --user-type " + + "android.os.usertype.profile.PRIVATE LauncherPrivateProfile"); + updatePrivateProfileSetupSuccessful("pm create-user", createUserOutput); + String[] tokens = createUserOutput.split("\\s+"); + mProfileUserId = Integer.parseInt(tokens[tokens.length - 1]); + StringBuilder logStr = new StringBuilder().append("profileId: ").append(mProfileUserId); + for (String str : tokens) { + logStr.append(str).append("\n"); + } + String startUserOutput = executeShellCommand("am start-user " + mProfileUserId); + updatePrivateProfileSetupSuccessful("am start-user", startUserOutput); + } + + @After + public void removePrivateProfile() { + String output = executeShellCommand("pm remove-user " + mProfileUserId); + updateProfileRemovalSuccessful("pm remove-user", output); + waitForPrivateSpaceRemoval(); + } + + @Test + public void testPrivateSpaceContainerIsPresent() { + assumeTrue(mPrivateProfileSetupSuccessful); + // Scroll to the bottom of All Apps + executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader()); + waitForResumed("Launcher internal state is still Background"); + + // Verify Unlocked View elements are present. + assertNotNull("Private Space Unlocked View not found, or is not correct", + mLauncher.getAllApps().getPrivateSpaceUnlockedView()); + } + + private void waitForPrivateSpaceSetup() { + waitForLauncherCondition("Private Profile not setup", + launcher -> launcher.getAppsView().hasPrivateProfile(), + LauncherInstrumentation.WAIT_TIME_MS); + } + + private void waitForPrivateSpaceRemoval() { + waitForLauncherCondition("Private Profile not setup", + launcher -> !launcher.getAppsView().hasPrivateProfile(), + LauncherInstrumentation.WAIT_TIME_MS); + } + + private void waitForLauncherUIUpdate() { + // Wait for model thread completion as it may be processing + // the install event from the SystemService + mLauncher.waitForModelQueueCleared(); + // Wait for Launcher UI thread completion, as it may be processing updating the UI in + // response to the model update. Not that `waitForLauncherInitialized` is just a proxy + // method, we can use any method which touches Launcher UI thread, + mLauncher.waitForLauncherInitialized(); + } + + private void updatePrivateProfileSetupSuccessful(String cli, String output) { + Log.d(TAG, "updatePrivateProfileSetupSuccessful, cli=" + cli + " " + "output=" + + output); + mPrivateProfileSetupSuccessful = output.startsWith("Success"); + } + + private void updateProfileRemovalSuccessful(String cli, String output) { + Log.d(TAG, "updateProfileRemovalSuccessful, cli=" + cli + " " + "output=" + output); + assertTrue(output, output.startsWith("Success")); + } + + private String executeShellCommand(String command) { + try { + return mDevice.executeShellCommand(command); + } catch (IOException e) { + Log.e(TAG, "error running shell command", e); + throw new RuntimeException(e); + } + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index 847dc4b627..245ec0911c 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -416,6 +416,14 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer } } + /** Returns PrivateSpaceContainer if present in view. */ + @NonNull + public PrivateSpaceContainer getPrivateSpaceUnlockedView() { + final UiObject2 allAppsContainer = verifyActiveContainer(); + final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer); + return new PrivateSpaceContainer(mLauncher, appListRecycler); + } + protected abstract void verifyVisibleContainerOnDismiss(); /** diff --git a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java new file mode 100644 index 0000000000..2c16e015c2 --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.tapl; + +import androidx.test.uiautomator.UiObject2; + +/** + * View containing Private Space elements. + */ +public class PrivateSpaceContainer { + private static final String PS_HEADER_RES_ID = "ps_header_layout"; + private static final String INSTALL_APP_TITLE = "Install apps"; + private static final String DIVIDER_RES_ID = "private_space_divider"; + + private final LauncherInstrumentation mLauncher; + private final UiObject2 mAppListRecycler; + + PrivateSpaceContainer(LauncherInstrumentation launcherInstrumentation, + UiObject2 appListRecycler) { + mLauncher = launcherInstrumentation; + mAppListRecycler = appListRecycler; + + verifyHeaderIsPresent(); + verifyInstallAppButtonIsPresent(); + verifyDividerIsPresent(); + } + + // Assert PS Header is in view. + // Assert PS header has the correct elements. + private void verifyHeaderIsPresent() { + final UiObject2 psHeader = mLauncher.waitForObjectInContainer(mAppListRecycler, + PS_HEADER_RES_ID); + new PrivateSpaceHeader(mLauncher, psHeader, true); + } + + + // Assert Install App Item is present in view. + private void verifyInstallAppButtonIsPresent() { + mLauncher.getAllApps().getAppIcon(INSTALL_APP_TITLE); + } + + // Assert Sys App Divider is present in view. + private void verifyDividerIsPresent() { + mLauncher.waitForObjectInContainer(mAppListRecycler, DIVIDER_RES_ID); + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java new file mode 100644 index 0000000000..3a7f0380a7 --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.tapl; + +import androidx.test.uiautomator.UiObject2; + +/** + * View containing Private Space Header. + */ +public class PrivateSpaceHeader { + private static final String PS_HEADER_TEXT_RES_ID = "ps_container_header"; + private static final String SETTINGS_BUTTON_RES_ID = "ps_settings_button"; + private static final String UNLOCK_BUTTON_VIEW_RES_ID = "ps_lock_unlock_button"; + private static final String LOCK_ICON_RES_ID = "lock_icon"; + private static final String LOCK_TEXT_RES_ID = "lock_text"; + + private final UiObject2 mPrivateSpaceHeader; + private final boolean mPrivateSpaceEnabled; + private final LauncherInstrumentation mLauncher; + + PrivateSpaceHeader(LauncherInstrumentation launcherInstrumentation, + UiObject2 privateSpaceHeader, boolean privateSpaceEnabled) { + mLauncher = launcherInstrumentation; + mPrivateSpaceHeader = privateSpaceHeader; + mPrivateSpaceEnabled = privateSpaceEnabled; + verifyPrivateSpaceHeaderState(); + } + + /** Verify elements in Private Space Header as per state */ + private void verifyPrivateSpaceHeaderState() { + if (mPrivateSpaceEnabled) { + verifyUnlockedState(); + } else { + mLauncher.fail("Private Space found in non enabled state"); + } + } + + /** Verify Unlocked State elements in Private Space Header */ + private void verifyUnlockedState() { + UiObject2 headerText = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader, + PS_HEADER_TEXT_RES_ID); + mLauncher.assertEquals("PS Header Text is incorrect ", + "Private", headerText.getText()); + + UiObject2 settingsButton = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader, + SETTINGS_BUTTON_RES_ID); + mLauncher.waitForObjectEnabled(settingsButton, "Private Space Settings Button"); + mLauncher.assertTrue("PS Settings button is non-clickable", settingsButton.isClickable()); + + UiObject2 unLockButtonView = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader, + UNLOCK_BUTTON_VIEW_RES_ID); + mLauncher.waitForObjectEnabled(unLockButtonView, "Private Space Unlock Button"); + mLauncher.assertTrue("PS Unlock Button is non-clickable", unLockButtonView.isClickable()); + + mLauncher.waitForObjectInContainer(mPrivateSpaceHeader, + LOCK_ICON_RES_ID); + + UiObject2 lockText = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader, + LOCK_TEXT_RES_ID); + mLauncher.assertEquals("PS lock text is incorrect", "Lock", lockText.getText()); + + } +} From 6d8b85e83aa517dbcbe6550bb44fd726613e1004 Mon Sep 17 00:00:00 2001 From: Holly Sun Date: Fri, 5 Apr 2024 11:16:39 -0700 Subject: [PATCH 12/20] [omni] Log LP duration & slop's data source and value. For duration, the data source and value should be the same for LPNH and LPH. E.g., if AGSA overrides duration, it applies for both LPNH and LPH. When there is no AGSA override, there are cases that one of our feature flag is enabled and the other one is disabled. We just simply rely on LPNH's feature flag in this case. This should be fine because the purpose is to cross check the data source and its value. Bug: 332722082 Test: manual Flag: legacy CUSTOM_LPNH_THRESHOLDS enabled Change-Id: I3f10b944257e7021ae7c930b782f1d963c0e505b --- .../quickstep/util/AssistStateManager.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/AssistStateManager.java b/quickstep/src/com/android/quickstep/util/AssistStateManager.java index 87d51387ed..a3904bc3e6 100644 --- a/quickstep/src/com/android/quickstep/util/AssistStateManager.java +++ b/quickstep/src/com/android/quickstep/util/AssistStateManager.java @@ -52,16 +52,38 @@ public class AssistStateManager implements ResourceBasedOverride { return Optional.empty(); } - /** Get the Launcher overridden long press duration to trigger Assistant. */ + /** Get the Launcher overridden long press nav handle duration to trigger Assistant. */ public Optional getLPNHDurationMillis() { return Optional.empty(); } - /** Get the Launcher overridden long press touch slop multiplier to trigger Assistant. */ + /** + * Get the Launcher overridden long press nav handle touch slop multiplier to trigger Assistant. + */ public Optional getLPNHCustomSlopMultiplier() { return Optional.empty(); } + /** Get the Launcher overridden long press home duration to trigger Assistant. */ + public Optional getLPHDurationMillis() { + return Optional.empty(); + } + + /** Get the Launcher overridden long press home touch slop multiplier to trigger Assistant. */ + public Optional getLPHCustomSlopMultiplier() { + return Optional.empty(); + } + + /** Get the long press duration data source. */ + public int getDurationDataSource() { + return 0; + } + + /** Get the long press touch slop multiplier data source. */ + public int getSlopDataSource() { + return 0; + } + /** Return {@code true} if the Settings toggle is enabled. */ public boolean isSettingsAllEntrypointsEnabled() { return false; From 59091e46125b49a7ae7a41b7c01d35c3b8a41fb6 Mon Sep 17 00:00:00 2001 From: Fengjiang Li Date: Mon, 8 Apr 2024 18:13:23 -0700 Subject: [PATCH 13/20] [2/2] Fix widget resize frame show up at skewed location. Wait until launcher is not animating to show resize frame Fix: 331433240 Test: manual - took a photo Flag: NONE Change-Id: I3aec7f8bf2b6081134004b30de3d389e5b1ab253 --- src/com/android/launcher3/Launcher.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 3273f27731..dbd594ee64 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1551,7 +1551,13 @@ public class Launcher extends StatefulActivity LauncherAppWidgetInfo launcherInfo, CellPos presenterPos) { CellLayout cellLayout = getCellLayout(launcherInfo.container, presenterPos.screenId); - if (mStateManager.getState() == NORMAL) { + // We should wait until launcher is not animating to show resize frame so that + // {@link View#hasIdentityMatrix()} returns true (no scale effect) from CellLayout and + // Workspace (they are widget's parent view). Otherwise widget's + // {@link View#getLocationInWindow(int[])} will set skewed location, causing resize + // frame not showing at skewed location in + // {@link AppWidgetResizeFrame#snapToWidget(boolean)}. + if (mStateManager.getState() == NORMAL && !mStateManager.isInTransition()) { AppWidgetResizeFrame.showForWidget(launcherHostView, cellLayout); } else { mStateManager.addStateListener(new StateManager.StateListener() { From ca79c7081671aa83eec25114361229042a049be5 Mon Sep 17 00:00:00 2001 From: Song Chun Fan Date: Mon, 8 Apr 2024 18:20:10 +0000 Subject: [PATCH 14/20] [Launcher/Archive] remove all checks for the archiving system property No longer needed Change-Id: I62c8843aa04a245d1dcc30f7787c71d17993f5d1 Merged-In: I62c8843aa04a245d1dcc30f7787c71d17993f5d1 BUG: 331165939 Test: builds --- src/com/android/launcher3/LauncherAppState.java | 2 +- src/com/android/launcher3/Utilities.java | 6 ------ src/com/android/launcher3/icons/IconCache.java | 3 ++- src/com/android/launcher3/model/AllAppsList.java | 3 ++- src/com/android/launcher3/model/ItemInstallQueue.java | 3 ++- src/com/android/launcher3/model/LoaderTask.java | 4 ++-- src/com/android/launcher3/model/PackageUpdatedTask.java | 2 +- src/com/android/launcher3/model/WorkspaceItemProcessor.kt | 7 ++++--- src/com/android/launcher3/model/data/AppInfo.java | 2 +- src/com/android/launcher3/model/data/ItemInfoWithIcon.java | 3 ++- src/com/android/launcher3/pm/InstallSessionHelper.java | 5 +++-- src/com/android/launcher3/pm/InstallSessionTracker.java | 3 ++- src/com/android/launcher3/touch/ItemClickHandler.java | 3 ++- src/com/android/launcher3/util/PackageManagerHelper.java | 5 +++-- 14 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index 60a6be6c9e..50a597d407 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -110,7 +110,7 @@ public class LauncherAppState implements SafeCloseable { mOnTerminateCallback.add(() -> mContext.getSystemService(LauncherApps.class).unregisterCallback(callbacks)); - if (Utilities.enableSupportForArchiving()) { + if (Flags.enableSupportForArchiving()) { ArchiveCompatibilityParams params = new ArchiveCompatibilityParams(); params.setEnableUnarchivalConfirmation(false); launcherApps.setArchiveCompatibility(params); diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index d44438f5bc..2b886e4570 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -830,10 +830,4 @@ public final class Utilities { // No-Op } } - - /** Encapsulates two flag checks into a single one. */ - public static boolean enableSupportForArchiving() { - return Flags.enableSupportForArchiving() - || getSystemProperty("pm.archiving.enabled", "false").equals("true"); - } } diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java index 1633eba5e1..af704a88f0 100644 --- a/src/com/android/launcher3/icons/IconCache.java +++ b/src/com/android/launcher3/icons/IconCache.java @@ -51,6 +51,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.core.util.Pair; +import com.android.launcher3.Flags; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Utilities; import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic; @@ -248,7 +249,7 @@ public class IconCache extends BaseIconCache { @SuppressWarnings("NewApi") public synchronized void getTitleAndIcon(ItemInfoWithIcon info, LauncherActivityInfo activityInfo, boolean useLowResIcon) { - boolean isAppArchived = Utilities.enableSupportForArchiving() && activityInfo != null + boolean isAppArchived = Flags.enableSupportForArchiving() && activityInfo != null && activityInfo.getActivityInfo().isArchived; // If we already have activity info, no need to use package icon getTitleAndIcon(info, () -> activityInfo, isAppArchived, useLowResIcon, diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java index 8659471d27..8c5ea79034 100644 --- a/src/com/android/launcher3/model/AllAppsList.java +++ b/src/com/android/launcher3/model/AllAppsList.java @@ -33,6 +33,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.AppFilter; +import com.android.launcher3.Flags; import com.android.launcher3.Utilities; import com.android.launcher3.compat.AlphabeticIndexCompat; import com.android.launcher3.icons.IconCache; @@ -330,7 +331,7 @@ public class AllAppsList { PackageManagerHelper.getLoadingProgress(info), PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING); applicationInfo.intent = launchIntent; - if (Utilities.enableSupportForArchiving()) { + if (Flags.enableSupportForArchiving()) { // In case an app is archived, the respective item flag corresponding to // archiving should also be applied during package updates if (info.getActivityInfo().isArchived) { diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java index d35087980a..90aba2a2de 100644 --- a/src/com/android/launcher3/model/ItemInstallQueue.java +++ b/src/com/android/launcher3/model/ItemInstallQueue.java @@ -40,6 +40,7 @@ import android.util.Pair; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import com.android.launcher3.Flags; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; @@ -300,7 +301,7 @@ public class ItemInstallQueue { } else { lai = laiList.get(0); si.intent = makeLaunchIntent(lai); - if (Utilities.enableSupportForArchiving() + if (Flags.enableSupportForArchiving() && lai.getActivityInfo().isArchived) { si.runtimeStatusFlags |= FLAG_ARCHIVED; } diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 17cef900ec..1e56e89ef5 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -420,7 +420,7 @@ public class LoaderTask implements Runnable { final HashMap installingPkgs = mSessionHelper.getActiveSessions(); - if (Utilities.enableSupportForArchiving()) { + if (Flags.enableSupportForArchiving()) { mInstallingPkgsCached = installingPkgs; } installingPkgs.forEach(mApp.getIconCache()::updateSessionCache); @@ -667,7 +667,7 @@ public class LoaderTask implements Runnable { for (int i = 0; i < apps.size(); i++) { LauncherActivityInfo app = apps.get(i); AppInfo appInfo = new AppInfo(app, mUserCache.getUserInfo(user), quietMode); - if (Utilities.enableSupportForArchiving() && app.getApplicationInfo().isArchived) { + if (Flags.enableSupportForArchiving() && app.getApplicationInfo().isArchived) { // For archived apps, include progress info in case there is a pending // install session post restart of device. String appPackageName = app.getApplicationInfo().packageName; diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index 0ba468d5f0..cc0140d636 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -276,7 +276,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING); // In case an app is archived, we need to make sure that archived state // in WorkspaceItemInfo is refreshed. - if (Utilities.enableSupportForArchiving() && !activities.isEmpty()) { + if (Flags.enableSupportForArchiving() && !activities.isEmpty()) { boolean newArchivalState = activities.get( 0).getActivityInfo().isArchived; if (newArchivalState != si.isArchived()) { diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt index 59f56dfaa8..9f2a49c669 100644 --- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt +++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt @@ -26,6 +26,7 @@ import android.graphics.Point import android.text.TextUtils import android.util.Log import android.util.LongSparseArray +import com.android.launcher3.Flags import com.android.launcher3.InvariantDeviceProfile import com.android.launcher3.LauncherAppState import com.android.launcher3.LauncherSettings.Favorites @@ -332,7 +333,7 @@ class WorkspaceItemProcessor( } if ( (c.restoreFlag != 0 || - Utilities.enableSupportForArchiving() && + Flags.enableSupportForArchiving() && activityInfo != null && activityInfo.applicationInfo.isArchived) && !TextUtils.isEmpty(targetPkg) ) { @@ -344,7 +345,7 @@ class WorkspaceItemProcessor( ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE.inv() } else if ( activityInfo == null || - (Utilities.enableSupportForArchiving() && + (Flags.enableSupportForArchiving() && activityInfo.applicationInfo.isArchived) ) { // For archived apps, include progress info in case there is @@ -443,7 +444,7 @@ class WorkspaceItemProcessor( !isSafeMode && (si == null) && (lapi == null) && - !(Utilities.enableSupportForArchiving() && + !(Flags.enableSupportForArchiving() && pmHelper.isAppArchived(component.packageName)) ) { // Restore never started diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java index 210d720bca..93ba619099 100644 --- a/src/com/android/launcher3/model/data/AppInfo.java +++ b/src/com/android/launcher3/model/data/AppInfo.java @@ -181,7 +181,7 @@ public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory { if (PackageManagerHelper.isAppSuspended(appInfo)) { info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED; } - if (Utilities.enableSupportForArchiving() && lai.getActivityInfo().isArchived) { + if (Flags.enableSupportForArchiving() && lai.getActivityInfo().isArchived) { info.runtimeStatusFlags |= FLAG_ARCHIVED; } info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java index 352c3633ac..f8878b61d8 100644 --- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java +++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java @@ -22,6 +22,7 @@ import android.os.Process; import androidx.annotation.Nullable; +import com.android.launcher3.Flags; import com.android.launcher3.Utilities; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.BitmapInfo.DrawableCreationFlags; @@ -171,7 +172,7 @@ public abstract class ItemInfoWithIcon extends ItemInfo { * Returns true if the app corresponding to the item is archived. */ public boolean isArchived() { - if (!Utilities.enableSupportForArchiving()) { + if (!Flags.enableSupportForArchiving()) { return false; } return (runtimeStatusFlags & FLAG_ARCHIVED) != 0; diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java index f3769d535f..4a3318e834 100644 --- a/src/com/android/launcher3/pm/InstallSessionHelper.java +++ b/src/com/android/launcher3/pm/InstallSessionHelper.java @@ -29,6 +29,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import com.android.launcher3.Flags; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.SessionCommitReceiver; import com.android.launcher3.Utilities; @@ -217,7 +218,7 @@ public class InstallSessionHelper { && !promiseIconAddedForId(sessionInfo.getSessionId())) { // In case of unarchival, we do not want to add a workspace promise icon if one is // not already present. For general app installations however, we do support it. - if (!Utilities.enableSupportForArchiving() || !sessionInfo.isUnarchival()) { + if (!Flags.enableSupportForArchiving() || !sessionInfo.isUnarchival()) { FileLog.d(LOG, "Adding package name to install queue: " + sessionInfo.getAppPackageName()); @@ -232,7 +233,7 @@ public class InstallSessionHelper { public boolean verifySessionInfo(@Nullable final PackageInstaller.SessionInfo sessionInfo) { // For archived apps we always want to show promise icons and the checks below don't apply. - if (Utilities.enableSupportForArchiving() && sessionInfo != null + if (Flags.enableSupportForArchiving() && sessionInfo != null && sessionInfo.isUnarchival()) { return true; } diff --git a/src/com/android/launcher3/pm/InstallSessionTracker.java b/src/com/android/launcher3/pm/InstallSessionTracker.java index eacbc11821..24d58f3e98 100644 --- a/src/com/android/launcher3/pm/InstallSessionTracker.java +++ b/src/com/android/launcher3/pm/InstallSessionTracker.java @@ -31,6 +31,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import com.android.launcher3.Flags; import com.android.launcher3.Utilities; import com.android.launcher3.util.PackageUserKey; @@ -80,7 +81,7 @@ public class InstallSessionTracker extends PackageInstaller.SessionCallback { helper.tryQueuePromiseAppIcon(sessionInfo); - if (Utilities.enableSupportForArchiving() && sessionInfo != null + if (Flags.enableSupportForArchiving() && sessionInfo != null && sessionInfo.isUnarchival()) { // For archived apps, icon could already be present on the workspace. To make sure // the icon state is updated, we send a change event. diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java index 111931eeeb..b743514758 100644 --- a/src/com/android/launcher3/touch/ItemClickHandler.java +++ b/src/com/android/launcher3/touch/ItemClickHandler.java @@ -41,6 +41,7 @@ import android.widget.Toast; import com.android.launcher3.BubbleTextView; import com.android.launcher3.BuildConfig; +import com.android.launcher3.Flags; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherSettings; @@ -340,7 +341,7 @@ public class ItemClickHandler { // Check for abandoned promise if ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi() - && (!Utilities.enableSupportForArchiving() || !shortcut.isArchived())) { + && (!Flags.enableSupportForArchiving() || !shortcut.isArchived())) { String packageName = shortcut.getIntent().getComponent() != null ? shortcut.getIntent().getComponent().getPackageName() : shortcut.getIntent().getPackage(); diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java index 606918e2ac..851c79578d 100644 --- a/src/com/android/launcher3/util/PackageManagerHelper.java +++ b/src/com/android/launcher3/util/PackageManagerHelper.java @@ -38,6 +38,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.launcher3.Flags; import com.android.launcher3.PendingAddItemInfo; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -109,7 +110,7 @@ public class PackageManagerHelper { */ public boolean isAppArchivedForUser(@NonNull final String packageName, @NonNull final UserHandle user) { - if (!Utilities.enableSupportForArchiving()) { + if (!Flags.enableSupportForArchiving()) { return false; } final ApplicationInfo info = getApplicationInfo( @@ -290,6 +291,6 @@ public class PackageManagerHelper { @SuppressWarnings("NewApi") private boolean isPackageInstalledOrArchived(ApplicationInfo info) { return (info.flags & ApplicationInfo.FLAG_INSTALLED) != 0 || ( - Utilities.enableSupportForArchiving() && info.isArchived); + Flags.enableSupportForArchiving() && info.isArchived); } } From 84fbec0b16cea289a375d5eda3808296fe6b2808 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Tue, 9 Apr 2024 10:55:58 -0700 Subject: [PATCH 15/20] Prevent meta shortcut from cancelling split select state. There are two things that need to be changed for this to work: 1. Make the isInOverview condition check for any Overview UI (including the split select state, modal, etc.) 2. Toggle Home All Apps directly, because firing the intent will cause Launcher to pause and resume before the intent is handled. We misinterpret the pause as a request to cancel split screen. Since TaskbarManager has a reference to Launcher, we might as well call the method directly. Test: Manual Fix: 319076403 Flag: N/A Change-Id: Ib8899188f593a168a054a16717df4a95be098557 --- .../launcher3/taskbar/LauncherTaskbarUIController.java | 6 +++--- .../launcher3/taskbar/TaskbarActivityContext.java | 2 +- .../android/launcher3/taskbar/TaskbarInsetsController.kt | 2 +- .../taskbar/TaskbarLauncherStateController.java | 4 ++-- .../com/android/launcher3/taskbar/TaskbarManager.java | 9 +++++---- .../android/launcher3/taskbar/TaskbarUIController.java | 2 +- .../com/android/quickstep/TouchInteractionService.java | 8 +++----- src/com/android/launcher3/Launcher.java | 9 +++++++-- 8 files changed, 23 insertions(+), 19 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 23380d67bd..896cc8424b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -425,14 +425,14 @@ public class LauncherTaskbarUIController extends TaskbarUIController { } @Override - protected boolean isInOverview() { - return mTaskbarLauncherStateController.isInOverview(); + protected boolean isInOverviewUi() { + return mTaskbarLauncherStateController.isInOverviewUi(); } @Override protected boolean canToggleHomeAllApps() { return mLauncher.isResumed() - && !mTaskbarLauncherStateController.isInOverview() + && !mTaskbarLauncherStateController.isInOverviewUi() && !mLauncher.areFreeformTasksVisible(); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 390dec9a66..e802e72e21 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -665,7 +665,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { LauncherAtom.TaskBarContainer.Builder taskbarBuilder = LauncherAtom.TaskBarContainer.newBuilder(); - if (mControllers.uiController.isInOverview()) { + if (mControllers.uiController.isInOverviewUi()) { taskbarBuilder.setTaskSwitcherContainer( LauncherAtom.TaskSwitcherContainer.newBuilder()); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index 8dc81cf461..6163dadca6 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -375,7 +375,7 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas ) { // Taskbar has some touchable elements, take over the full taskbar area if ( - controllers.uiController.isInOverview && + controllers.uiController.isInOverviewUi && DisplayController.isTransientTaskbar(context) ) { val region = diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index b0abbe9e57..17dcacea3c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -666,8 +666,8 @@ public class TaskbarLauncherStateController { && !mLauncher.getWorkspace().isOverlayShown(); } - boolean isInOverview() { - return mLauncherState == LauncherState.OVERVIEW; + boolean isInOverviewUi() { + return mLauncherState.overviewUi; } private void playStateTransitionAnim(AnimatorSet animatorSet, long duration, diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index e4f9ba5260..8f15d61e4e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -58,6 +58,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.statemanager.StatefulActivity; @@ -339,12 +340,12 @@ public class TaskbarManager { /** * Toggles All Apps for Taskbar or Launcher depending on the current state. - * - * @param homeAllAppsIntent Intent used if Taskbar is not enabled or Launcher is resumed. */ - public void toggleAllApps(Intent homeAllAppsIntent) { + public void toggleAllApps() { if (mTaskbarActivityContext == null || mTaskbarActivityContext.canToggleHomeAllApps()) { - mContext.startActivity(homeAllAppsIntent); + // Home All Apps should be toggled from this class, because the controllers are not + // initialized when Taskbar is disabled (i.e. TaskbarActivityContext is null). + if (mActivity instanceof Launcher l) l.toggleAllAppsSearch(); } else { mTaskbarActivityContext.toggleAllAppsSearch(); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index cb0fa406e8..2e78489692 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -193,7 +193,7 @@ public class TaskbarUIController { } /** Returns {@code true} if Taskbar is currently within overview. */ - protected boolean isInOverview() { + protected boolean isInOverviewUi() { return false; } diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 66d7144ae0..e66268a050 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -602,23 +602,21 @@ public class TouchInteractionService extends Service { } private PendingIntent createAllAppsPendingIntent() { - final Intent homeIntent = new Intent(mOverviewComponentObserver.getHomeIntent()) - .setAction(INTENT_ACTION_ALL_APPS_TOGGLE); - if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) { return new PendingIntent(new IIntentSender.Stub() { @Override public void send(int code, Intent intent, String resolvedType, IBinder allowlistToken, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { - MAIN_EXECUTOR.execute(() -> mTaskbarManager.toggleAllApps(homeIntent)); + MAIN_EXECUTOR.execute(() -> mTaskbarManager.toggleAllApps()); } }); } else { return PendingIntent.getActivity( this, GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS, - homeIntent, + new Intent(mOverviewComponentObserver.getHomeIntent()) + .setAction(INTENT_ACTION_ALL_APPS_TOGGLE), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 3273f27731..155bfa1bd5 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1647,7 +1647,7 @@ public class Launcher extends StatefulActivity } else if (Intent.ACTION_ALL_APPS.equals(intent.getAction())) { showAllAppsFromIntent(alreadyOnHome); } else if (INTENT_ACTION_ALL_APPS_TOGGLE.equals(intent.getAction())) { - toggleAllAppsFromIntent(alreadyOnHome); + toggleAllAppsSearch(alreadyOnHome); } else if (Intent.ACTION_SHOW_WORK_APPS.equals(intent.getAction())) { showAllAppsWithSelectedTabFromIntent(alreadyOnHome, ActivityAllAppsContainerView.AdapterHolder.WORK); @@ -1661,7 +1661,12 @@ public class Launcher extends StatefulActivity // Overridden } - protected void toggleAllAppsFromIntent(boolean alreadyOnHome) { + /** Toggles Launcher All Apps with keyboard ready for search. */ + public void toggleAllAppsSearch() { + toggleAllAppsSearch(/* alreadyOnHome= */ true); + } + + protected void toggleAllAppsSearch(boolean alreadyOnHome) { if (getStateManager().isInStableState(ALL_APPS)) { getStateManager().goToState(NORMAL, alreadyOnHome); } else { From deee0d06f624223b808593997cf22042c9aa5142 Mon Sep 17 00:00:00 2001 From: Holly Sun Date: Thu, 4 Apr 2024 16:49:41 -0700 Subject: [PATCH 16/20] [omni] Implement 2-stage for LPNH. Use existing override duration and touch slop multiplier values for the 1st stage. Times `TWO_STAGE_MULTIPLIER` for the 2nd stage. See http://shortn/_WqYj0buH7R Bug: 330446193 Test: manual Flag: legacy ENABLE_LPNH_TWO_STAGES disabled Change-Id: Ic200f431524578d17fd98ebfbc65e44e0971e31c --- .../android/quickstep/DeviceConfigWrapper.kt | 20 +++++-- .../NavHandleLongPressInputConsumer.java | 52 +++++++++++++++++-- src/com/android/launcher3/util/LogConfig.java | 5 ++ 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt b/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt index 678709c2e2..1cc54d825c 100644 --- a/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt +++ b/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt @@ -44,9 +44,26 @@ class DeviceConfigWrapper private constructor(propReader: PropReader) { "Enable AGSA override for LPNH and LPH timeout and touch slop" ) + val lpnhTimeoutMs = + propReader.get("LPNH_TIMEOUT_MS", 450, "Controls lpnh timeout in milliseconds") + val lpnhSlopPercentage = propReader.get("LPNH_SLOP_PERCENTAGE", 100, "Controls touch slop percentage for lpnh") + val enableLpnhTwoStages = + propReader.get( + "ENABLE_LPNH_TWO_STAGES", + false, + "Enable two stage for LPNH duration and touch slop" + ) + + val twoStageMultiplier = + propReader.get( + "TWO_STAGE_MULTIPLIER", + 2, + "Extends the duration and touch slop if the initial slop is passed" + ) + val animateLpnh = propReader.get("ANIMATE_LPNH", false, "Animates navbar when long pressing") val shrinkNavHandleOnPress = @@ -56,9 +73,6 @@ class DeviceConfigWrapper private constructor(propReader: PropReader) { "Shrinks navbar when long pressing if ANIMATE_LPNH is enabled" ) - val lpnhTimeoutMs = - propReader.get("LPNH_TIMEOUT_MS", 450, "Controls lpnh timeout in milliseconds") - val enableLongPressNavHandle = propReader.get( "ENABLE_LONG_PRESS_NAV_HANDLE", diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java index 5ab2fcc154..075e53988b 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java @@ -20,6 +20,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LONG_PRESS_NAVBAR; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LONG_PRESS_STASHED_TASKBAR; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; +import static com.android.launcher3.util.LogConfig.NAV_HANDLE_LONG_PRESS; import android.content.Context; import android.util.Log; @@ -43,14 +44,19 @@ import com.android.systemui.shared.system.InputMonitorCompat; public class NavHandleLongPressInputConsumer extends DelegateInputConsumer { private static final String TAG = "NavHandleLongPressIC"; + private static final boolean DEBUG_NAV_HANDLE = Utilities.isPropertyEnabled( + NAV_HANDLE_LONG_PRESS); private final NavHandleLongPressHandler mNavHandleLongPressHandler; private final float mNavHandleWidth; private final float mScreenWidth; private final Runnable mTriggerLongPress = this::triggerLongPress; - private final float mTouchSlopSquared; + private final float mTouchSlopSquaredOriginal; + private float mTouchSlopSquared; + private final float mOuterTouchSlopSquared; private final int mLongPressTimeout; + private final int mOuterLongPressTimeout; private final boolean mDeepPressEnabled; private final NavHandle mNavHandle; private final StatsLogManager mStatsLogManager; @@ -65,13 +71,23 @@ public class NavHandleLongPressInputConsumer extends DelegateInputConsumer { super(delegate, inputMonitor); mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x; mDeepPressEnabled = DeviceConfigWrapper.get().getEnableLpnhDeepPress(); + int twoStageMultiplier = DeviceConfigWrapper.get().getTwoStageMultiplier(); AssistStateManager assistStateManager = AssistStateManager.INSTANCE.get(context); if (assistStateManager.getLPNHDurationMillis().isPresent()) { mLongPressTimeout = assistStateManager.getLPNHDurationMillis().get().intValue(); } else { mLongPressTimeout = ViewConfiguration.getLongPressTimeout(); } - mTouchSlopSquared = deviceState.getSquaredTouchSlop(); + mOuterLongPressTimeout = mLongPressTimeout * twoStageMultiplier; + mTouchSlopSquaredOriginal = deviceState.getSquaredTouchSlop(); + mTouchSlopSquared = mTouchSlopSquaredOriginal; + mOuterTouchSlopSquared = mTouchSlopSquared * (twoStageMultiplier * twoStageMultiplier); + if (DEBUG_NAV_HANDLE) { + Log.d(TAG, "mLongPressTimeout=" + mLongPressTimeout); + Log.d(TAG, "mOuterLongPressTimeout=" + mOuterLongPressTimeout); + Log.d(TAG, "mTouchSlopSquared=" + mTouchSlopSquared); + Log.d(TAG, "mOuterTouchSlopSquared=" + mOuterTouchSlopSquared); + } mNavHandle = navHandle; mNavHandleWidth = navHandle.getNavHandleWidth(context); mNavHandleLongPressHandler = NavHandleLongPressHandler.newInstance(context); @@ -109,22 +125,44 @@ public class NavHandleLongPressInputConsumer extends DelegateInputConsumer { mCurrentDownEvent.recycle(); } mCurrentDownEvent = MotionEvent.obtain(ev); + mTouchSlopSquared = mTouchSlopSquaredOriginal; mDeepPressLogged = false; if (isInNavBarHorizontalArea(ev.getRawX())) { mNavHandleLongPressHandler.onTouchStarted(mNavHandle); MAIN_EXECUTOR.getHandler().postDelayed(mTriggerLongPress, mLongPressTimeout); } + if (DEBUG_NAV_HANDLE) { + Log.d(TAG, "ACTION_DOWN"); + } } case MotionEvent.ACTION_MOVE -> { if (!MAIN_EXECUTOR.getHandler().hasCallbacks(mTriggerLongPress)) { break; } - float touchSlopSquared = mTouchSlopSquared; float dx = ev.getX() - mCurrentDownEvent.getX(); float dy = ev.getY() - mCurrentDownEvent.getY(); double distanceSquared = (dx * dx) + (dy * dy); - if (distanceSquared > touchSlopSquared) { + if (DEBUG_NAV_HANDLE) { + Log.d(TAG, "ACTION_MOVE distanceSquared=" + distanceSquared); + } + if (DeviceConfigWrapper.get().getEnableLpnhTwoStages()) { + if (mTouchSlopSquared < distanceSquared + && distanceSquared <= mOuterTouchSlopSquared) { + MAIN_EXECUTOR.getHandler().removeCallbacks(mTriggerLongPress); + int delay = mOuterLongPressTimeout + - (int) (ev.getEventTime() - ev.getDownTime()); + MAIN_EXECUTOR.getHandler().postDelayed(mTriggerLongPress, delay); + mTouchSlopSquared = mOuterTouchSlopSquared; + if (DEBUG_NAV_HANDLE) { + Log.d(TAG, "Touch in middle region!"); + } + } + } + if (distanceSquared > mTouchSlopSquared) { + if (DEBUG_NAV_HANDLE) { + Log.d(TAG, "Touch slop out. mTouchSlopSquared=" + mTouchSlopSquared); + } cancelLongPress("touch slop passed"); } } @@ -153,6 +191,9 @@ public class NavHandleLongPressInputConsumer extends DelegateInputConsumer { } private void triggerLongPress() { + if (DEBUG_NAV_HANDLE) { + Log.d(TAG, "triggerLongPress"); + } String runningPackage = mTopTaskTracker.getCachedTopTask( /* filterOnlyVisibleRecents */ true).getPackageName(); mStatsLogManager.logger().withPackageName(runningPackage).log( @@ -175,6 +216,9 @@ public class NavHandleLongPressInputConsumer extends DelegateInputConsumer { } private void cancelLongPress(String reason) { + if (DEBUG_NAV_HANDLE) { + Log.d(TAG, "cancelLongPress"); + } MAIN_EXECUTOR.getHandler().removeCallbacks(mTriggerLongPress); mNavHandleLongPressHandler.onTouchFinished(mNavHandle, reason); } diff --git a/src/com/android/launcher3/util/LogConfig.java b/src/com/android/launcher3/util/LogConfig.java index e5bbcb1923..d59c3394c4 100644 --- a/src/com/android/launcher3/util/LogConfig.java +++ b/src/com/android/launcher3/util/LogConfig.java @@ -65,4 +65,9 @@ public class LogConfig { * When turned on, we enable AGA related session summary logging. */ public static final String AGA_SESSION_SUMMARY_LOG = "AGASessionSummaryLog"; + + /** + * When turned on, we enable long press nav handle related logging. + */ + public static final String NAV_HANDLE_LONG_PRESS = "NavHandleLongPress"; } From efc3c4641946804ceabff44f78bc38230d0e2a55 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 9 Apr 2024 17:03:43 -0700 Subject: [PATCH 17/20] Fixing null check causing test breakage Bug: 333609600 Test: Presubmit Flag: None Change-Id: Ic44df00ba945c79010c2cf99a034cca2b5d6c161 --- .../android/launcher3/allapps/PrivateProfileManagerTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java index 8f398a66ff..2dcbda4ab6 100644 --- a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java +++ b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java @@ -209,7 +209,8 @@ public class PrivateProfileManagerTest { Mockito.verify(mContext).startActivity(acIntent.capture()); assertEquals("Intent Action is different", - expectedIntent.toUri(0), acIntent.getValue().toUri(0)); + expectedIntent == null ? null : expectedIntent.toUri(0), + acIntent.getValue() == null ? null : acIntent.getValue().toUri(0)); } private static void awaitTasksCompleted() throws Exception { From 0580379e304dae5de7c0571cae8c1068478de685 Mon Sep 17 00:00:00 2001 From: Alina Zaidi Date: Tue, 9 Apr 2024 17:16:16 +0000 Subject: [PATCH 18/20] Rename freeform tasks to desktop tasks Bug: b/332878426 Test: refactoring CL. Existing unit tests still pass. Flag: NONE Change-Id: I24ad9699223dd383ff794ef3b028bf32beca96d7 --- .../DesktopVisibilityController.java | 56 +++++++++---------- .../KeyboardQuickSwitchController.java | 2 +- .../taskbar/LauncherTaskbarUIController.java | 4 +- .../taskbar/TaskbarStashController.java | 2 +- .../uioverrides/QuickstepLauncher.java | 6 +- .../states/BackgroundAppState.java | 4 +- .../uioverrides/states/QuickSwitchState.java | 4 +- .../quickstep/BaseActivityInterface.java | 4 +- .../android/quickstep/RemoteTargetGluer.java | 2 +- .../quickstep/views/LauncherRecentsView.java | 2 +- src/com/android/launcher3/Launcher.java | 4 +- 11 files changed, 45 insertions(+), 45 deletions(-) diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java index 176091a141..c0dacf1daa 100644 --- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java +++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java @@ -48,7 +48,7 @@ public class DesktopVisibilityController { "persist.wm.debug.desktop_stashing", false); private final Launcher mLauncher; - private int mVisibleFreeformTasksCount; + private int mVisibleDesktopTasksCount; private boolean mInOverviewState; private boolean mBackgroundStateEnabled; private boolean mGestureInProgress; @@ -73,7 +73,7 @@ public class DesktopVisibilityController { if (DEBUG) { Log.d(TAG, "desktop visible tasks count changed=" + visibleTasksCount); } - setVisibleFreeformTasksCount(visibleTasksCount); + setVisibleDesktopTasksCount(visibleTasksCount); } }); } @@ -108,51 +108,51 @@ public class DesktopVisibilityController { } /** - * Whether freeform windows are visible in desktop mode. + * Whether desktop tasks are visible in desktop mode. */ - public boolean areFreeformTasksVisible() { - boolean freeformTasksVisible = mVisibleFreeformTasksCount > 0; + public boolean areDesktopTasksVisible() { + boolean desktopTasksVisible = mVisibleDesktopTasksCount > 0; if (DEBUG) { - Log.d(TAG, "areFreeformTasksVisible: freeformVisible=" + freeformTasksVisible + Log.d(TAG, "areDesktopTasksVisible: desktopVisible=" + desktopTasksVisible + " overview=" + mInOverviewState); } - return freeformTasksVisible && !mInOverviewState; + return desktopTasksVisible && !mInOverviewState; } /** - * Number of visible freeform windows in desktop mode. + * Number of visible desktop windows in desktop mode. */ - public int getVisibleFreeformTasksCount() { - return mVisibleFreeformTasksCount; + public int getVisibleDesktopTasksCount() { + return mVisibleDesktopTasksCount; } /** - * Sets the number of freeform windows that are visible and updates launcher visibility based on + * Sets the number of desktop windows that are visible and updates launcher visibility based on * it. */ - public void setVisibleFreeformTasksCount(int visibleTasksCount) { + public void setVisibleDesktopTasksCount(int visibleTasksCount) { if (DEBUG) { - Log.d(TAG, "setVisibleFreeformTasksCount: visibleTasksCount=" + visibleTasksCount - + " currentValue=" + mVisibleFreeformTasksCount); + Log.d(TAG, "setVisibleDesktopTasksCount: visibleTasksCount=" + visibleTasksCount + + " currentValue=" + mVisibleDesktopTasksCount); } - if (visibleTasksCount != mVisibleFreeformTasksCount) { - final boolean wasVisible = mVisibleFreeformTasksCount > 0; + if (visibleTasksCount != mVisibleDesktopTasksCount) { + final boolean wasVisible = mVisibleDesktopTasksCount > 0; final boolean isVisible = visibleTasksCount > 0; - mVisibleFreeformTasksCount = visibleTasksCount; + mVisibleDesktopTasksCount = visibleTasksCount; if (wasVisible != isVisible) { - if (mVisibleFreeformTasksCount > 0) { + if (mVisibleDesktopTasksCount > 0) { setLauncherViewsVisibility(View.INVISIBLE); if (!mInOverviewState) { - // When freeform is visible & we're not in overview, we want launcher to - // appear paused, this ensures that taskbar displays. + // When desktop tasks are visible & we're not in overview, we want launcher + // to appear paused, this ensures that taskbar displays. markLauncherPaused(); } } else { setLauncherViewsVisibility(View.VISIBLE); - // If freeform isn't visible ensure that launcher appears resumed to behave - // normally. + // If desktop tasks aren't visible, ensure that launcher appears resumed to + // behave normally. markLauncherResumed(); } } @@ -181,9 +181,9 @@ public class DesktopVisibilityController { if (mInOverviewState) { setLauncherViewsVisibility(View.VISIBLE); markLauncherResumed(); - } else if (areFreeformTasksVisible() && !mGestureInProgress) { + } else if (areDesktopTasksVisible() && !mGestureInProgress) { // Switching out of overview state and gesture finished. - // If freeform tasks are still visible, hide launcher again. + // If desktop tasks are still visible, hide launcher again. setLauncherViewsVisibility(View.INVISIBLE); markLauncherPaused(); } @@ -200,8 +200,8 @@ public class DesktopVisibilityController { if (mBackgroundStateEnabled) { setLauncherViewsVisibility(View.VISIBLE); markLauncherResumed(); - } else if (areFreeformTasksVisible() && !mGestureInProgress) { - // Switching out of background state. If freeform tasks are visible, pause launcher. + } else if (areDesktopTasksVisible() && !mGestureInProgress) { + // Switching out of background state. If desktop tasks are visible, pause launcher. setLauncherViewsVisibility(View.INVISIBLE); markLauncherPaused(); } @@ -251,7 +251,7 @@ public class DesktopVisibilityController { * Handle launcher moving to home due to home gesture or home button press. */ public void onHomeActionTriggered() { - if (IS_STASHING_ENABLED && areFreeformTasksVisible()) { + if (IS_STASHING_ENABLED && areDesktopTasksVisible()) { SystemUiProxy.INSTANCE.get(mLauncher).stashDesktopApps(mLauncher.getDisplayId()); } } @@ -270,7 +270,7 @@ public class DesktopVisibilityController { dragLayer.setVisibility(visibility); } if (mLauncher instanceof QuickstepLauncher ql && ql.getTaskbarUIController() != null - && mVisibleFreeformTasksCount != 0) { + && mVisibleDesktopTasksCount != 0) { ql.getTaskbarUIController().onLauncherVisibilityChanged(visibility == VISIBLE); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java index d89f49b6aa..584106bc05 100644 --- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java +++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java @@ -115,7 +115,7 @@ public final class KeyboardQuickSwitchController implements DesktopVisibilityController desktopController = LauncherActivityInterface.INSTANCE.getDesktopVisibilityController(); final boolean onDesktop = - desktopController != null && desktopController.areFreeformTasksVisible(); + desktopController != null && desktopController.areDesktopTasksVisible(); if (mModel.isTaskListValid(mTaskListChangeId)) { // When we are opening the KQS with no focus override, check if the first task is diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 896cc8424b..03c28053c1 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -219,7 +219,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { DesktopVisibilityController desktopController = LauncherActivityInterface.INSTANCE.getDesktopVisibilityController(); final boolean onDesktop = - desktopController != null && desktopController.areFreeformTasksVisible(); + desktopController != null && desktopController.areDesktopTasksVisible(); if (onDesktop) { isVisible = false; } @@ -433,7 +433,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { protected boolean canToggleHomeAllApps() { return mLauncher.isResumed() && !mTaskbarLauncherStateController.isInOverviewUi() - && !mLauncher.areFreeformTasksVisible(); + && !mLauncher.areDesktopTasksVisible(); } @Override diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 7e74c27264..15be8e7415 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -985,7 +985,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba DesktopVisibilityController visibilityController = LauncherActivityInterface.INSTANCE.getDesktopVisibilityController(); if (visibilityController != null && mActivity.isHardwareKeyboard() - && mActivity.isThreeButtonNav() && visibilityController.areFreeformTasksVisible()) { + && mActivity.isThreeButtonNav() && visibilityController.areDesktopTasksVisible()) { return false; } diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index c5c009210f..6013797955 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -937,7 +937,7 @@ public class QuickstepLauncher extends Launcher { @Override public void setResumed() { if (mDesktopVisibilityController != null - && mDesktopVisibilityController.areFreeformTasksVisible() + && mDesktopVisibilityController.areDesktopTasksVisible() && !mDesktopVisibilityController.isRecentsGestureInProgress()) { // Return early to skip setting activity to appear as resumed // TODO(b/255649902): shouldn't be needed when we have a separate launcher state @@ -1284,9 +1284,9 @@ public class QuickstepLauncher extends Launcher { } @Override - public boolean areFreeformTasksVisible() { + public boolean areDesktopTasksVisible() { if (mDesktopVisibilityController != null) { - return mDesktopVisibilityController.areFreeformTasksVisible(); + return mDesktopVisibilityController.areDesktopTasksVisible(); } return false; } diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java index 547de77f64..3ffad70365 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java @@ -91,8 +91,8 @@ public class BackgroundAppState extends OverviewState { @Override protected float getDepthUnchecked(Context context) { - if (Launcher.getLauncher(context).areFreeformTasksVisible()) { - // Don't blur the background while freeform tasks are visible + if (Launcher.getLauncher(context).areDesktopTasksVisible()) { + // Don't blur the background while desktop tasks are visible return BaseDepthController.DEPTH_0_PERCENT; } else if (enableScalingRevealHomeAnimation()) { return BaseDepthController.DEPTH_70_PERCENT; diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java index 7fb811d4b7..dfad4096bc 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java @@ -45,8 +45,8 @@ public class QuickSwitchState extends BackgroundAppState { @Override public int getWorkspaceScrimColor(Launcher launcher) { - if (launcher.areFreeformTasksVisible()) { - // No scrim while freeform tasks are visible + if (launcher.areDesktopTasksVisible()) { + // No scrim while desktop tasks are visible return Color.TRANSPARENT; } DeviceProfile dp = launcher.getDeviceProfile(); diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index a3f6be032b..a3a5f82bdd 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -109,12 +109,12 @@ public abstract class BaseActivityInterface 0) { // Allocate +1 to account for a new task added to the desktop mode int numHandles = visibleTasksCount + 1; diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 0a3d2a0ac1..352ebfe7b0 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -271,7 +271,7 @@ public class LauncherRecentsView extends RecentsView * Returns {@code true} if there are visible tasks with windowing mode set to * {@link android.app.WindowConfiguration#WINDOWING_MODE_FREEFORM} */ - public boolean areFreeformTasksVisible() { - return false; // Base launcher does not track freeform tasks + public boolean areDesktopTasksVisible() { + return false; // Base launcher does not track desktop tasks } // Getters and Setters From 547d6fc472c130f12be195748c45e15a7cd7864d Mon Sep 17 00:00:00 2001 From: randypfohl Date: Thu, 1 Feb 2024 15:58:57 -0800 Subject: [PATCH 19/20] abtracting Activity from recentsView through recentsviewcontainer and basecontainerinterface interfaces This change will let us move from activity to other parent views for recent views. Summary: In prep for new recentsview containers outside of activity we needed to decouple recentsview from activity and state. This change will let us move from activity to other parent views for recent views. Test: Built and tested locally for 1p and 3p launchers on tablet, and portrait modes. Verified working functionality. Bug: 292269949 Flag: NONE Change-Id: I5c72745f438d466362ece988c35a97d829e9c1b4 --- .../launcher3/model/WellbeingModel.java | 15 +- .../uioverrides/QuickstepLauncher.java | 27 +- .../states/BackgroundAppState.java | 9 +- .../states/OverviewModalTaskState.java | 6 +- .../QuickstepAtomicAnimationFactory.java | 24 +- .../NavBarToHomeTouchController.java | 1 + .../NoButtonQuickSwitchTouchController.java | 3 +- .../QuickSwitchTouchController.java | 7 +- .../TaskViewTouchController.java | 29 +- .../TransposedQuickSwitchTouchController.java | 4 +- .../TwoButtonNavbarTouchController.java | 4 +- .../android/quickstep/AbsSwipeUpHandler.java | 146 +++---- .../quickstep/BaseActivityInterface.java | 310 +------------- .../quickstep/BaseContainerInterface.java | 377 ++++++++++++++++++ .../quickstep/DesktopSystemShortcut.kt | 12 +- .../quickstep/FallbackActivityInterface.java | 14 +- .../quickstep/FallbackSwipeHandler.java | 2 +- .../com/android/quickstep/GestureState.java | 16 +- .../quickstep/LauncherActivityInterface.java | 40 +- .../quickstep/LauncherSwipeHandlerV2.java | 24 +- .../quickstep/OverviewCommandHelper.java | 10 +- .../QuickstepTestInformationHandler.java | 2 +- .../android/quickstep/RecentsActivity.java | 14 +- .../android/quickstep/RemoteTargetGluer.java | 8 +- .../quickstep/RotationTouchHelper.java | 4 +- .../quickstep/SwipeUpAnimationLogic.java | 9 +- .../quickstep/TaskAnimationManager.java | 42 +- .../android/quickstep/TaskOverlayFactory.java | 25 +- .../quickstep/TaskShortcutFactory.java | 90 +++-- .../quickstep/TouchInteractionService.java | 38 +- .../FallbackNavBarTouchController.java | 17 +- .../FallbackRecentsStateController.java | 2 + .../fallback/FallbackRecentsView.java | 32 +- .../quickstep/fallback/RecentsState.java | 20 +- .../fallback/RecentsTaskController.java | 2 +- .../AssistantInputConsumer.java | 14 +- .../OtherActivityInputConsumer.java | 4 - .../inputconsumers/OverviewInputConsumer.java | 31 +- .../ScreenPinnedInputConsumer.java | 10 +- .../AnimatorControllerWithResistance.java | 21 +- .../quickstep/util/AppPairsController.java | 8 +- .../util/InputProxyHandlerFactory.java | 16 +- .../LauncherUnfoldAnimationController.java | 6 +- .../util/RecentsAtomicAnimationFactory.java | 19 +- .../quickstep/util/RecentsOrientedState.java | 14 +- .../util/ScalingWorkspaceRevealAnim.kt | 3 +- .../util/SplitAnimationController.kt | 43 +- .../util/SplitSelectStateController.java | 24 +- .../util/SplitToWorkspaceController.java | 7 +- .../util/StaggeredWorkspaceAnim.java | 25 +- .../util/TaskRemovedDuringLaunchListener.java | 22 +- .../quickstep/util/TaskViewSimulator.java | 5 +- .../UnfoldMoveFromCenterHotseatAnimator.java | 8 +- ...UnfoldMoveFromCenterWorkspaceAnimator.java | 8 +- .../LauncherUnfoldTransitionController.kt | 4 +- .../util/unfold/UnfoldAnimationBuilder.kt | 4 +- .../quickstep/views/ClearAllButton.java | 6 +- .../quickstep/views/DesktopAppSelectView.java | 9 +- .../quickstep/views/DesktopTaskView.java | 10 +- .../views/DigitalWellBeingToast.java | 36 +- .../views/FloatingAppPairBackground.kt | 97 +++-- .../quickstep/views/FloatingTaskView.java | 64 ++- .../quickstep/views/FloatingWidgetView.java | 8 +- .../quickstep/views/GroupedTaskView.java | 14 +- .../quickstep/views/LauncherRecentsView.java | 64 +-- .../android/quickstep/views/RecentsView.java | 178 +++++---- .../views/SplitInstructionsView.java | 25 +- .../android/quickstep/views/TaskMenuView.java | 43 +- .../quickstep/views/TaskMenuViewWithArrow.kt | 19 +- .../quickstep/views/TaskThumbnailView.java | 9 +- .../com/android/quickstep/views/TaskView.java | 39 +- .../util/SplitSelectStateControllerTest.kt | 3 +- .../launcher3/BaseDraggingActivity.java | 2 - .../launcher3/popup/RemoteActionShortcut.java | 12 +- .../SecondaryDisplayLauncher.java | 5 - .../quickstep/views/RecentsViewContainer.java | 168 ++++++++ 76 files changed, 1386 insertions(+), 1106 deletions(-) create mode 100644 quickstep/src/com/android/quickstep/BaseContainerInterface.java create mode 100644 src/com/android/quickstep/views/RecentsViewContainer.java diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java index 3d04cb6828..ee1c6004dd 100644 --- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java +++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java @@ -44,7 +44,6 @@ import androidx.annotation.MainThread; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.popup.RemoteActionShortcut; @@ -53,6 +52,7 @@ import com.android.launcher3.util.BgObjectWithLooper; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.Preconditions; import com.android.launcher3.util.SimpleBroadcastReceiver; +import com.android.launcher3.views.ActivityContext; import java.util.Arrays; import java.util.HashMap; @@ -147,7 +147,7 @@ public final class WellbeingModel extends BgObjectWithLooper { @MainThread private SystemShortcut getShortcutForApp(String packageName, int userId, - BaseDraggingActivity activity, ItemInfo info, View originalView) { + Context context, ItemInfo info, View originalView) { Preconditions.assertUIThread(); // Work profile apps are not recognized by digital wellbeing. if (userId != UserHandle.myUserId()) { @@ -171,7 +171,7 @@ public final class WellbeingModel extends BgObjectWithLooper { "getShortcutForApp [" + packageName + "]: action: '" + action.getTitle() + "'"); } - return new RemoteActionShortcut(action, activity, info, originalView); + return new RemoteActionShortcut(action, context, info, originalView); } } @@ -305,9 +305,10 @@ public final class WellbeingModel extends BgObjectWithLooper { /** * Shortcut factory for generating wellbeing action */ - public static final SystemShortcut.Factory SHORTCUT_FACTORY = - (activity, info, originalView) -> (info.getTargetComponent() == null) ? null - : INSTANCE.get(activity).getShortcutForApp( + public static final SystemShortcut.Factory SHORTCUT_FACTORY = + (context, info, originalView) -> + (info.getTargetComponent() == null) ? null + : INSTANCE.get(originalView.getContext()).getShortcutForApp( info.getTargetComponent().getPackageName(), info.user.getIdentifier(), - activity, info, originalView); + originalView.getContext(), info, originalView); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 6013797955..6c05bfe752 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -181,6 +181,7 @@ import com.android.quickstep.util.unfold.ProxyUnfoldTransitionProvider; import com.android.quickstep.views.FloatingTaskView; import com.android.quickstep.views.OverviewActionsView; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ActivityManagerWrapper; @@ -204,7 +205,7 @@ import java.util.function.BiConsumer; import java.util.function.Predicate; import java.util.stream.Stream; -public class QuickstepLauncher extends Launcher { +public class QuickstepLauncher extends Launcher implements RecentsViewContainer { private static final boolean TRACE_LAYOUTS = SystemProperties.getBoolean("persist.debug.trace_layouts", false); private static final String TRACE_RELAYOUT_CLASS = @@ -218,7 +219,8 @@ public class QuickstepLauncher extends Launcher { private DepthController mDepthController; private @Nullable DesktopVisibilityController mDesktopVisibilityController; private QuickstepTransitionManager mAppTransitionManager; - private OverviewActionsView mActionsView; + + private OverviewActionsView mActionsView; private TISBindHelper mTISBindHelper; private @Nullable LauncherTaskbarUIController mTaskbarUIController; // Will be updated when dragging from taskbar. @@ -244,12 +246,16 @@ public class QuickstepLauncher extends Launcher { private boolean mIsPredictiveBackToHomeInProgress; + public static QuickstepLauncher getLauncher(Context context) { + return fromContext(context); + } + @Override protected void setupViews() { super.setupViews(); mActionsView = findViewById(R.id.overview_actions_view); - RecentsView overviewPanel = getOverviewPanel(); + RecentsView overviewPanel = getOverviewPanel(); SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.get(this); mSplitSelectStateController = new SplitSelectStateController(this, mHandler, getStateManager(), @@ -1055,8 +1061,9 @@ public class QuickstepLauncher extends Launcher { .playPlaceholderDismissAnim(this, splitDismissEvent); } - public T getActionsView() { - return (T) mActionsView; + @Override + public OverviewActionsView getActionsView() { + return mActionsView; } @Override @@ -1369,25 +1376,25 @@ public class QuickstepLauncher extends Launcher { } private static final class LauncherTaskViewController extends - TaskViewTouchController { + TaskViewTouchController { - LauncherTaskViewController(Launcher activity) { + LauncherTaskViewController(QuickstepLauncher activity) { super(activity); } @Override protected boolean isRecentsInteractive() { - return mActivity.isInState(OVERVIEW) || mActivity.isInState(OVERVIEW_MODAL_TASK); + return mContainer.isInState(OVERVIEW) || mContainer.isInState(OVERVIEW_MODAL_TASK); } @Override protected boolean isRecentsModal() { - return mActivity.isInState(OVERVIEW_MODAL_TASK); + return mContainer.isInState(OVERVIEW_MODAL_TASK); } @Override protected void onUserControlledAnimationCreated(AnimatorPlaybackController animController) { - mActivity.getStateManager().setCurrentUserControlledAnimation(animController); + mContainer.getStateManager().setCurrentUserControlledAnimation(animController); } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java index 3ffad70365..7fa121dadb 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java @@ -22,7 +22,6 @@ import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITION import android.content.Context; import android.graphics.Color; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.allapps.AllAppsTransitionController; @@ -63,7 +62,7 @@ public class BackgroundAppState extends OverviewState { @Override public float[] getOverviewScaleAndOffset(Launcher launcher) { - return getOverviewScaleAndOffsetForBackgroundState(launcher); + return getOverviewScaleAndOffsetForBackgroundState(launcher.getOverviewPanel()); } @Override @@ -125,9 +124,7 @@ public class BackgroundAppState extends OverviewState { } public static float[] getOverviewScaleAndOffsetForBackgroundState( - BaseDraggingActivity activity) { - return new float[] { - ((RecentsView) activity.getOverviewPanel()).getMaxScaleForFullScreen(), - NO_OFFSET}; + RecentsView recentsView) { + return new float[] {recentsView.getMaxScaleForFullScreen(), NO_OFFSET}; } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java index c63eaebc89..3c291e6095 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java @@ -20,7 +20,6 @@ import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERV import android.content.Context; import android.graphics.Rect; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Flags; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; @@ -51,7 +50,7 @@ public class OverviewModalTaskState extends OverviewState { @Override public float[] getOverviewScaleAndOffset(Launcher launcher) { - return getOverviewScaleAndOffsetForModalState(launcher); + return getOverviewScaleAndOffsetForModalState(launcher.getOverviewPanel()); } @Override @@ -72,8 +71,7 @@ public class OverviewModalTaskState extends OverviewState { return super.isTaskbarStashed(launcher); } - public static float[] getOverviewScaleAndOffsetForModalState(BaseDraggingActivity activity) { - RecentsView recentsView = activity.getOverviewPanel(); + public static float[] getOverviewScaleAndOffsetForModalState(RecentsView recentsView) { Rect taskSize = recentsView.getSelectedTaskBounds(); Rect modalTaskSize = new Rect(); recentsView.getModalTaskSize(modalTaskSize); diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java index b40186819f..0368f3a86d 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java @@ -94,7 +94,7 @@ public class QuickstepAtomicAnimationFactory extends @Override public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState, StateAnimationConfig config) { - RecentsView overview = mActivity.getOverviewPanel(); + RecentsView overview = mContainer.getOverviewPanel(); if ((fromState == OVERVIEW || fromState == OVERVIEW_SPLIT_SELECT) && toState == NORMAL) { overview.switchToScreenshot(() -> overview.finishRecentsAnimation(true /* toRecents */, null)); @@ -118,7 +118,7 @@ public class QuickstepAtomicAnimationFactory extends config.setInterpolator(ANIM_WORKSPACE_SCALE, DECELERATE); config.setInterpolator(ANIM_WORKSPACE_FADE, ACCELERATE); - if (DisplayController.getNavigationMode(mActivity).hasGestures + if (DisplayController.getNavigationMode(mContainer).hasGestures && overview.getTaskViewCount() > 0) { // Overview is going offscreen, so keep it at its current scale and opacity. config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME); @@ -136,7 +136,7 @@ public class QuickstepAtomicAnimationFactory extends config.duration = Math.max(config.duration, scrollDuration); // Sync scroll so that it ends before or at the same time as the taskbar animation. - if (mActivity.getDeviceProfile().isTaskbarPresent) { + if (mContainer.getDeviceProfile().isTaskbarPresent) { config.duration = Math.min( config.duration, QuickstepTransitionManager.getTaskbarToHomeDuration()); } @@ -147,7 +147,7 @@ public class QuickstepAtomicAnimationFactory extends config.setInterpolator(ANIM_OVERVIEW_FADE, DECELERATE_1_7); } - Workspace workspace = mActivity.getWorkspace(); + Workspace workspace = mContainer.getWorkspace(); // Start from a higher workspace scale, but only if we're invisible so we don't jump. boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE; if (isWorkspaceVisible) { @@ -160,7 +160,7 @@ public class QuickstepAtomicAnimationFactory extends workspace.setScaleX(WORKSPACE_PREPARE_SCALE); workspace.setScaleY(WORKSPACE_PREPARE_SCALE); } - Hotseat hotseat = mActivity.getHotseat(); + Hotseat hotseat = mContainer.getHotseat(); boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0; if (!isHotseatVisible) { hotseat.setScaleX(WORKSPACE_PREPARE_SCALE); @@ -168,7 +168,7 @@ public class QuickstepAtomicAnimationFactory extends } } else if ((fromState == NORMAL || fromState == HINT_STATE || fromState == HINT_STATE_TWO_BUTTON) && toState == OVERVIEW) { - if (DisplayController.getNavigationMode(mActivity).hasGestures) { + if (DisplayController.getNavigationMode(mContainer).hasGestures) { config.setInterpolator(ANIM_WORKSPACE_SCALE, fromState == NORMAL ? ACCELERATE : OVERSHOOT_1_2); config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCELERATE); @@ -201,18 +201,18 @@ public class QuickstepAtomicAnimationFactory extends } else if (fromState == HINT_STATE && toState == NORMAL) { config.setInterpolator(ANIM_DEPTH, DECELERATE_3); if (mHintToNormalDuration == -1) { - ValueAnimator va = getWorkspaceSpringScaleAnimator(mActivity, - mActivity.getWorkspace(), - toState.getWorkspaceScaleAndTranslation(mActivity).scale); + ValueAnimator va = getWorkspaceSpringScaleAnimator(mContainer, + mContainer.getWorkspace(), + toState.getWorkspaceScaleAndTranslation(mContainer).scale); mHintToNormalDuration = (int) va.getDuration(); } config.duration = Math.max(config.duration, mHintToNormalDuration); } else if (fromState == ALL_APPS && toState == NORMAL) { - AllAppsSwipeController.applyAllAppsToNormalConfig(mActivity, config); + AllAppsSwipeController.applyAllAppsToNormalConfig(mContainer, config); } else if (fromState == NORMAL && toState == ALL_APPS) { - AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mActivity, config); + AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mContainer, config); } else if (fromState == OVERVIEW && toState == OVERVIEW_SPLIT_SELECT) { - SplitAnimationTimings timings = mActivity.getDeviceProfile().isTablet + SplitAnimationTimings timings = mContainer.getDeviceProfile().isTablet ? SplitAnimationTimings.TABLET_OVERVIEW_TO_SPLIT : SplitAnimationTimings.PHONE_OVERVIEW_TO_SPLIT; config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR, diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java index e8b508168d..615e3e326e 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java @@ -47,6 +47,7 @@ import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.touch.SingleAxisSwipeDetector; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.TouchController; import com.android.quickstep.TaskUtils; diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java index 8ef35c06eb..5a19ed42db 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java @@ -84,7 +84,6 @@ import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.util.MotionPauseDetector; import com.android.quickstep.util.WorkspaceRevealAnim; -import com.android.quickstep.views.LauncherRecentsView; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; @@ -108,7 +107,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, private final float mMaxYProgress; private final MotionPauseDetector mMotionPauseDetector; private final float mMotionPauseMinDisplacement; - private final LauncherRecentsView mRecentsView; + private final RecentsView mRecentsView; protected final AnimatorListener mClearStateOnCancelListener = newCancelListener(this::clearState); diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java index de73630666..05a55d0856 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java @@ -38,12 +38,12 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_O import android.view.MotionEvent; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.Utilities; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.AbstractStateChangeTouchController; import com.android.launcher3.touch.SingleAxisSwipeDetector; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.NavigationMode; import com.android.quickstep.SystemUiProxy; @@ -58,11 +58,12 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll protected final RecentsView mOverviewPanel; - public QuickSwitchTouchController(Launcher launcher) { + public QuickSwitchTouchController(QuickstepLauncher launcher) { this(launcher, SingleAxisSwipeDetector.HORIZONTAL); } - protected QuickSwitchTouchController(Launcher l, SingleAxisSwipeDetector.Direction dir) { + protected QuickSwitchTouchController(QuickstepLauncher l, + SingleAxisSwipeDetector.Direction dir) { super(l, dir); mOverviewPanel = l.getOverviewPanel(); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java index e9f2d4f019..300d697fff 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java @@ -21,6 +21,7 @@ import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_BOTH import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.content.Context; import android.os.VibrationEffect; import android.view.MotionEvent; import android.view.View; @@ -28,7 +29,6 @@ import android.view.animation.Interpolator; import com.android.app.animation.Interpolators; import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.LauncherAnimUtils; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -44,12 +44,13 @@ import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.orientation.RecentsPagedOrientationHandler; import com.android.quickstep.util.VibrationConstants; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; import com.android.quickstep.views.TaskView; /** * Touch controller for handling task view card swipes */ -public abstract class TaskViewTouchController +public abstract class TaskViewTouchController extends AnimatorListenerAdapter implements TouchController, SingleAxisSwipeDetector.Listener { @@ -63,7 +64,7 @@ public abstract class TaskViewTouchController public static final VibrationEffect TASK_DISMISS_VIBRATION_FALLBACK = VibrationConstants.EFFECT_TEXTURE_TICK; - protected final T mActivity; + protected final CONTAINER mContainer; private final SingleAxisSwipeDetector mDetector; private final RecentsView mRecentsView; private final int[] mTempCords = new int[2]; @@ -87,13 +88,13 @@ public abstract class TaskViewTouchController private boolean mIsDismissHapticRunning = false; - public TaskViewTouchController(T activity) { - mActivity = activity; - mRecentsView = activity.getOverviewPanel(); - mIsRtl = Utilities.isRtl(activity.getResources()); + public TaskViewTouchController(CONTAINER container) { + mContainer = container; + mRecentsView = container.getOverviewPanel(); + mIsRtl = Utilities.isRtl(container.getResources()); SingleAxisSwipeDetector.Direction dir = mRecentsView.getPagedOrientationHandler().getUpDownSwipeDirection(); - mDetector = new SingleAxisSwipeDetector(activity, this, dir); + mDetector = new SingleAxisSwipeDetector(container, this, dir); } private boolean canInterceptTouch(MotionEvent ev) { @@ -113,7 +114,7 @@ public abstract class TaskViewTouchController return true; } if (AbstractFloatingView.getTopOpenViewWithType( - mActivity, TYPE_TOUCH_CONTROLLER_NO_INTERCEPT) != null) { + mContainer, TYPE_TOUCH_CONTROLLER_NO_INTERCEPT) != null) { return false; } return isRecentsInteractive(); @@ -159,7 +160,7 @@ public abstract class TaskViewTouchController for (int i = 0; i < mRecentsView.getTaskViewCount(); i++) { TaskView view = mRecentsView.getTaskViewAt(i); - if (mRecentsView.isTaskViewVisible(view) && mActivity.getDragLayer() + if (mRecentsView.isTaskViewVisible(view) && mContainer.getDragLayer() .isEventOverView(view, ev)) { // Disable swiping up and down if the task overlay is modal. if (isRecentsModal()) { @@ -179,7 +180,7 @@ public abstract class TaskViewTouchController // - It's the focused task if in grid view // - The task is snapped mAllowGoingDown = i == mRecentsView.getCurrentPage() - && DisplayController.getNavigationMode(mActivity).hasGestures + && DisplayController.getNavigationMode(mContainer).hasGestures && (!mRecentsView.showAsGrid() || mTaskBeingDragged.isFocusedTask()) && mRecentsView.isTaskInExpectedScrollPosition(i); @@ -228,7 +229,7 @@ public abstract class TaskViewTouchController RecentsPagedOrientationHandler orientationHandler = mRecentsView.getPagedOrientationHandler(); mCurrentAnimationIsGoingUp = goingUp; - BaseDragLayer dl = mActivity.getDragLayer(); + BaseDragLayer dl = mContainer.getDragLayer(); final int secondaryLayerDimension = orientationHandler.getSecondaryDimension(dl); long maxDuration = 2 * secondaryLayerDimension; int verticalFactor = orientationHandler.getTaskDragDisplacementFactor(mIsRtl); @@ -372,10 +373,10 @@ public abstract class TaskViewTouchController MIN_TASK_DISMISS_ANIMATION_DURATION, MAX_TASK_DISMISS_ANIMATION_DURATION); mCurrentAnimation.setEndAction(this::clearState); - mCurrentAnimation.startWithVelocity(mActivity, goingToEnd, Math.abs(velocity), + mCurrentAnimation.startWithVelocity(mContainer, goingToEnd, Math.abs(velocity), mEndDisplacement, animationDuration); if (goingUp && goingToEnd && !mIsDismissHapticRunning) { - VibratorWrapper.INSTANCE.get(mActivity).vibrate(TASK_DISMISS_VIBRATION_PRIMITIVE, + VibratorWrapper.INSTANCE.get(mContainer).vibrate(TASK_DISMISS_VIBRATION_PRIMITIVE, TASK_DISMISS_VIBRATION_PRIMITIVE_SCALE, TASK_DISMISS_VIBRATION_FALLBACK); mIsDismissHapticRunning = true; } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java index 8f9c01441e..b70cabe76d 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java @@ -15,13 +15,13 @@ */ package com.android.launcher3.uioverrides.touchcontrollers; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.touch.SingleAxisSwipeDetector; +import com.android.launcher3.uioverrides.QuickstepLauncher; public class TransposedQuickSwitchTouchController extends QuickSwitchTouchController { - public TransposedQuickSwitchTouchController(Launcher launcher) { + public TransposedQuickSwitchTouchController(QuickstepLauncher launcher) { super(launcher, SingleAxisSwipeDetector.VERTICAL); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java index 9f2c1d479f..31c9b3e7c0 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java @@ -27,10 +27,10 @@ import android.os.SystemClock; import android.view.MotionEvent; import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.touch.AbstractStateChangeTouchController; import com.android.launcher3.touch.SingleAxisSwipeDetector; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.views.AllAppsEduView; @@ -51,7 +51,7 @@ public class TwoButtonNavbarTouchController extends AbstractStateChangeTouchCont private int mContinuousTouchCount = 0; - public TwoButtonNavbarTouchController(Launcher l) { + public TwoButtonNavbarTouchController(QuickstepLauncher l) { super(l, l.getDeviceProfile().isVerticalBarLayout() ? SingleAxisSwipeDetector.HORIZONTAL : SingleAxisSwipeDetector.VERTICAL); mIsTransposed = l.getDeviceProfile().isVerticalBarLayout(); diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 7ee7751362..cceaf278b4 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -108,7 +108,6 @@ import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager.StatsLogger; import com.android.launcher3.statehandlers.DesktopVisibilityController; import com.android.launcher3.statemanager.BaseState; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.taskbar.TaskbarThresholdUtils; import com.android.launcher3.taskbar.TaskbarUIController; import com.android.launcher3.uioverrides.QuickstepLauncher; @@ -136,6 +135,7 @@ import com.android.quickstep.util.SwipePipToHomeAnimator; import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.util.TransformParams; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView.TaskIdAttributeContainer; import com.android.systemui.shared.recents.model.Task; @@ -160,7 +160,7 @@ import java.util.function.Consumer; /** * Handles the navigation gestures when Launcher is the default home activity. */ -public abstract class AbsSwipeUpHandler, +public abstract class AbsSwipeUpHandler> extends SwipeUpAnimationLogic implements OnApplyWindowInsetsListener, RecentsAnimationCallbacks.RecentsAnimationListener { @@ -171,7 +171,7 @@ public abstract class AbsSwipeUpHandler, // Fraction of the scroll and transform animation in which the current task fades out private static final float KQS_TASK_FADE_ANIMATION_FRACTION = 0.4f; - protected final BaseActivityInterface mActivityInterface; + protected final BaseContainerInterface mContainerInterface; protected final InputConsumerProxy mInputConsumerProxy; protected final ActivityInitListener mActivityInitListener; // Callbacks to be made once the recents animation starts @@ -182,7 +182,7 @@ public abstract class AbsSwipeUpHandler, protected @Nullable RecentsAnimationController mRecentsAnimationController; protected @Nullable RecentsAnimationController mDeferredCleanupRecentsAnimationController; protected RecentsAnimationTargets mRecentsAnimationTargets; - protected @Nullable T mActivity; + protected @Nullable T mContainer; protected @Nullable Q mRecentsView; protected Runnable mGestureEndCallback; protected MultiStateCallback mStateCallback; @@ -192,7 +192,7 @@ public abstract class AbsSwipeUpHandler, private final Runnable mLauncherOnDestroyCallback = () -> { ActiveGestureLog.INSTANCE.addLog("Launcher destroyed", LAUNCHER_DESTROYED); mRecentsView = null; - mActivity = null; + mContainer = null; mStateCallback.clearState(STATE_LAUNCHER_PRESENT); }; @@ -347,8 +347,9 @@ public abstract class AbsSwipeUpHandler, long touchTimeMs, boolean continuingLastGesture, InputConsumerController inputConsumer) { super(context, deviceState, gestureState); - mActivityInterface = gestureState.getActivityInterface(); - mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit); + mContainerInterface = gestureState.getContainerInterface(); + mActivityInitListener = + mContainerInterface.createActivityInitListener(this::onActivityInit); mInputConsumerProxy = new InputConsumerProxy(context, /* rotationSupplier = */ () -> { if (mRecentsView == null) { @@ -358,7 +359,7 @@ public abstract class AbsSwipeUpHandler, }, inputConsumer, /* onTouchDownCallback = */ () -> { endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */); endLauncherTransitionController(); - }, new InputProxyHandlerFactory(mActivityInterface, mGestureState)); + }, new InputProxyHandlerFactory(mContainerInterface, mGestureState)); mTaskAnimationManager = taskAnimationManager; mTouchTimeMs = touchTimeMs; mContinuingLastGesture = continuingLastGesture; @@ -375,8 +376,8 @@ public abstract class AbsSwipeUpHandler, initStateCallbacks(); mIsTransientTaskbar = mDp.isTaskbarPresent - && DisplayController.isTransientTaskbar(mActivity); - TaskbarUIController controller = mActivityInterface.getTaskbarController(); + && DisplayController.isTransientTaskbar(context); + TaskbarUIController controller = mContainerInterface.getTaskbarController(); mTaskbarAlreadyOpen = controller != null && !controller.isTaskbarStashed(); mIsTaskbarAllAppsOpen = controller != null && controller.isTaskbarAllAppsOpen(); mTaskbarAppWindowThreshold = @@ -473,16 +474,16 @@ public abstract class AbsSwipeUpHandler, return false; } - T createdActivity = mActivityInterface.getCreatedActivity(); - if (createdActivity != null) { - initTransitionEndpoints(createdActivity.getDeviceProfile()); + T createdContainer = (T) mContainerInterface.getCreatedContainer(); + if (createdContainer != null) { + initTransitionEndpoints(createdContainer.getDeviceProfile()); } - final T activity = mActivityInterface.getCreatedActivity(); - if (mActivity == activity) { + final T container = (T) mContainerInterface.getCreatedContainer(); + if (mContainer == container) { return true; } - if (mActivity != null) { + if (mContainer != null) { if (mStateCallback.hasStates(STATE_GESTURE_COMPLETED)) { // If the activity has restarted between setting the page scroll settling callback // and actually receiving the callback, just mark the gesture completed @@ -497,23 +498,23 @@ public abstract class AbsSwipeUpHandler, mStateCallback.setState(oldState); } mWasLauncherAlreadyVisible = alreadyOnHome; - mActivity = activity; + mContainer = container; // Override the visibility of the activity until the gesture actually starts and we swipe // up, or until we transition home and the home animation is composed if (alreadyOnHome) { - mActivity.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS); + mContainer.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS); } else { - mActivity.addForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS); + mContainer.addForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS); } - mRecentsView = activity.getOverviewPanel(); + mRecentsView = container.getOverviewPanel(); mRecentsView.setOnPageTransitionEndCallback(null); mStateCallback.setState(STATE_LAUNCHER_PRESENT); if (alreadyOnHome) { onLauncherStart(); } else { - activity.addEventCallback(EVENT_STARTED, mLauncherOnStartCallback); + container.addEventCallback(EVENT_STARTED, mLauncherOnStartCallback); } // Set up a entire animation lifecycle callback to notify the current recents view when @@ -538,8 +539,8 @@ public abstract class AbsSwipeUpHandler, setupRecentsViewUi(); mRecentsView.runOnPageScrollsInitialized(this::linkRecentsViewScroll); - mActivity.runOnBindToTouchInteractionService(this::onLauncherBindToService); - mActivity.addEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback); + mContainer.runOnBindToTouchInteractionService(this::onLauncherBindToService); + mContainer.addEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback); return true; } @@ -551,8 +552,8 @@ public abstract class AbsSwipeUpHandler, } private void onLauncherStart() { - final T activity = mActivityInterface.getCreatedActivity(); - if (activity == null || mActivity != activity) { + final T container = (T) mContainerInterface.getCreatedContainer(); + if (container == null || mContainer != container) { return; } if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) { @@ -568,7 +569,7 @@ public abstract class AbsSwipeUpHandler, // as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL. if (mGestureState.getEndTarget() != HOME) { Runnable initAnimFactory = () -> { - mAnimationFactory = mActivityInterface.prepareRecentsUI(mDeviceState, + mAnimationFactory = mContainerInterface.prepareRecentsUI(mDeviceState, mWasLauncherAlreadyVisible, this::onAnimatorPlaybackControllerCreated); maybeUpdateRecentsAttachedState(false /* animate */); if (mGestureState.getEndTarget() != null) { @@ -585,14 +586,14 @@ public abstract class AbsSwipeUpHandler, initAnimFactory.run(); } } - AbstractFloatingView.closeAllOpenViewsExcept(activity, mWasLauncherAlreadyVisible, + AbstractFloatingView.closeAllOpenViewsExcept(container, mWasLauncherAlreadyVisible, AbstractFloatingView.TYPE_LISTENER); if (mWasLauncherAlreadyVisible) { mStateCallback.setState(STATE_LAUNCHER_DRAWN); } else { SafeCloseable traceToken = TraceHelper.INSTANCE.beginAsyncSection("WTS-init"); - View dragLayer = activity.getDragLayer(); + View dragLayer = container.getDragLayer(); dragLayer.getViewTreeObserver().addOnDrawListener(new OnDrawListener() { boolean mHandled = false; @@ -606,7 +607,7 @@ public abstract class AbsSwipeUpHandler, traceToken.close(); dragLayer.post(() -> dragLayer.getViewTreeObserver().removeOnDrawListener(this)); - if (activity != mActivity) { + if (container != mContainer) { return; } @@ -615,7 +616,7 @@ public abstract class AbsSwipeUpHandler, }); } - activity.getRootView().setOnApplyWindowInsetsListener(this); + container.getRootView().setOnApplyWindowInsetsListener(this); mStateCallback.setState(STATE_LAUNCHER_STARTED); } @@ -631,21 +632,21 @@ public abstract class AbsSwipeUpHandler, // For the duration of the gesture, in cases where an activity is launched while the // activity is not yet resumed, finish the animation to ensure we get resumed - mGestureState.getActivityInterface().setOnDeferredActivityLaunchCallback( + mGestureState.getContainerInterface().setOnDeferredActivityLaunchCallback( mOnDeferredActivityLaunch); mGestureState.runOnceAtState(STATE_END_TARGET_SET, () -> { mDeviceState.getRotationTouchHelper() .onEndTargetCalculated(mGestureState.getEndTarget(), - mActivityInterface); + mContainerInterface); }); notifyGestureStarted(); } private void onDeferredActivityLaunch() { - mActivityInterface.switchRunningTaskViewToScreenshot( + mContainerInterface.switchRunningTaskViewToScreenshot( null, () -> { mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */); }); @@ -706,7 +707,7 @@ public abstract class AbsSwipeUpHandler, public void onMotionPauseDetected() { mHasMotionEverBeenPaused = true; maybeUpdateRecentsAttachedState(true/* animate */, true/* moveRunningTask */); - Optional.ofNullable(mActivityInterface.getTaskbarController()) + Optional.ofNullable(mContainerInterface.getTaskbarController()) .ifPresent(TaskbarUIController::startTranslationSpring); if (!mIsInAllAppsRegion) { performHapticFeedback(); @@ -812,7 +813,7 @@ public abstract class AbsSwipeUpHandler, */ private void setIsInAllAppsRegion(boolean isInAllAppsRegion) { if (mIsInAllAppsRegion == isInAllAppsRegion - || !mActivityInterface.allowAllAppsFromOverview()) { + || !mContainerInterface.allowAllAppsFromOverview()) { return; } mIsInAllAppsRegion = isInAllAppsRegion; @@ -821,8 +822,9 @@ public abstract class AbsSwipeUpHandler, VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC); maybeUpdateRecentsAttachedState(true); - if (mActivity != null) { - mActivity.getAppsView().getSearchUiManager().prepareToFocusEditText(mIsInAllAppsRegion); + if (mContainer != null) { + mContainer.getAppsView().getSearchUiManager() + .prepareToFocusEditText(mIsInAllAppsRegion); } // Draw active task below Launcher so that All Apps can appear over it. @@ -835,7 +837,7 @@ public abstract class AbsSwipeUpHandler, if (!canCreateNewOrUpdateExistingLauncherTransitionController()) { return; } - initTransitionEndpoints(mActivity.getDeviceProfile()); + initTransitionEndpoints(mContainer.getDeviceProfile()); mAnimationFactory.createActivityInterface(mTransitionDragLength); } @@ -846,7 +848,7 @@ public abstract class AbsSwipeUpHandler, */ private boolean canCreateNewOrUpdateExistingLauncherTransitionController() { return mGestureState.getEndTarget() != HOME - && !mHasEndedLauncherTransition && mActivity != null; + && !mHasEndedLauncherTransition && mContainer != null; } @Override @@ -930,11 +932,11 @@ public abstract class AbsSwipeUpHandler, // needs to be canceled mRecentsAnimationController.setWillFinishToHome(swipeUpThresholdPassed); - if (mActivity == null) return; + if (mContainer == null) return; if (swipeUpThresholdPassed) { - mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0); + mContainer.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0); } else { - mActivity.getSystemUiController().updateUiState( + mContainer.getSystemUiController().updateUiState( UI_STATE_FULLSCREEN_TASK, centermostTaskFlags); } } @@ -962,7 +964,7 @@ public abstract class AbsSwipeUpHandler, // Only initialize the device profile, if it has not been initialized before, as in some // configurations targets.homeContentInsets may not be correct. - if (mActivity == null) { + if (mContainer == null) { RemoteAnimationTarget primaryTaskTarget = targets.apps[0]; // orientation state is independent of which remote target handle we use since both // should be pointing to the same one. Just choose index 0 for now since that works for @@ -971,7 +973,7 @@ public abstract class AbsSwipeUpHandler, .getOrientationState(); DeviceProfile dp = orientationState.getLauncherDeviceProfile(); if (targets.minimizedHomeBounds != null && primaryTaskTarget != null) { - Rect overviewStackBounds = mActivityInterface + Rect overviewStackBounds = mContainerInterface .getOverviewWindowBounds(targets.minimizedHomeBounds, primaryTaskTarget); dp = dp.getMultiWindowProfile(mContext, new WindowBounds(overviewStackBounds, targets.homeContentInsets)); @@ -1014,7 +1016,7 @@ public abstract class AbsSwipeUpHandler, @UiThread public void onGestureStarted(boolean isLikelyToStartNewTask) { - mActivityInterface.closeOverlay(); + mContainerInterface.closeOverlay(); TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); if (mRecentsView != null) { @@ -1074,11 +1076,11 @@ public abstract class AbsSwipeUpHandler, */ @UiThread private void notifyGestureStarted() { - final T curActivity = mActivity; + final T curActivity = mContainer; if (curActivity != null) { // Once the gesture starts, we can no longer transition home through the button, so // reset the force override of the activity visibility - mActivity.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS); + mContainer.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS); } } @@ -1147,7 +1149,7 @@ public abstract class AbsSwipeUpHandler, maybeUpdateRecentsAttachedState(false); final GestureEndTarget endTarget = mGestureState.getEndTarget(); // Wait until the given View (if supplied) draws before resuming the last task. - View postResumeLastTask = mActivityInterface.onSettledOnEndTarget(endTarget); + View postResumeLastTask = mContainerInterface.onSettledOnEndTarget(endTarget); if (endTarget != NEW_TASK) { InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_QUICK_SWITCH); @@ -1168,7 +1170,7 @@ public abstract class AbsSwipeUpHandler, // Notify the SysUI to use fade-in animation when entering PiP SystemUiProxy.INSTANCE.get(mContext).setPipAnimationTypeToAlpha(); DesktopVisibilityController desktopVisibilityController = - mActivityInterface.getDesktopVisibilityController(); + mContainerInterface.getDesktopVisibilityController(); if (desktopVisibilityController != null) { // Notify the SysUI to stash desktop apps if they are visible desktopVisibilityController.onHomeActionTriggered(); @@ -1357,7 +1359,7 @@ public abstract class AbsSwipeUpHandler, } } Interpolator interpolator; - S state = mActivityInterface.stateFromGestureEndTarget(endTarget); + S state = mContainerInterface.stateFromGestureEndTarget(endTarget); if (isKeyboardTaskFocusPending()) { interpolator = EMPHASIZED; } else if (state.displayOverviewTasksAsGrid(mDp)) { @@ -1372,7 +1374,7 @@ public abstract class AbsSwipeUpHandler, mInputConsumerProxy.enable(); } if (endTarget == HOME) { - duration = mActivity != null && mActivity.getDeviceProfile().isTaskbarPresent + duration = mContainer != null && mContainer.getDeviceProfile().isTaskbarPresent ? StaggeredWorkspaceAnim.DURATION_TASKBAR_MS : StaggeredWorkspaceAnim.DURATION_MS; // Early detach the nav bar once the endTarget is determined as HOME @@ -1509,14 +1511,14 @@ public abstract class AbsSwipeUpHandler, if (mGestureState.getEndTarget().isLauncher) { // This is also called when the launcher is resumed, in order to clear the pending // widgets that have yet to be configured. - if (mActivity != null) { - DragView.removeAllViews(mActivity); + if (mContainer != null) { + DragView.removeAllViews(mContainer); } TaskStackChangeListeners.getInstance().registerTaskStackListener( mActivityRestartListener); - mParallelRunningAnim = mActivityInterface.getParallelAnimationToLauncher( + mParallelRunningAnim = mContainerInterface.getParallelAnimationToLauncher( mGestureState.getEndTarget(), duration, mTaskAnimationManager.getCurrentCallbacks()); if (mParallelRunningAnim != null) { @@ -1614,7 +1616,7 @@ public abstract class AbsSwipeUpHandler, if (windowAnimation == null) { continue; } - DeviceProfile dp = mActivity == null ? null : mActivity.getDeviceProfile(); + DeviceProfile dp = mContainer == null ? null : mContainer.getDeviceProfile(); windowAnimation.start(mContext, dp, velocityPxPerMs); mRunningWindowAnim[i] = RunningWindowAnim.wrap(windowAnimation); } @@ -1867,7 +1869,7 @@ public abstract class AbsSwipeUpHandler, } // Make sure recents is in its final state maybeUpdateRecentsAttachedState(false); - mActivityInterface.onSwipeUpToHomeComplete(mDeviceState); + mContainerInterface.onSwipeUpToHomeComplete(mDeviceState); } }); if (mRecentsAnimationTargets != null) { @@ -1941,8 +1943,8 @@ public abstract class AbsSwipeUpHandler, private void reset() { mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED); - if (mActivity != null) { - mActivity.removeEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback); + if (mContainer != null) { + mContainer.removeEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback); } } @@ -1966,7 +1968,7 @@ public abstract class AbsSwipeUpHandler, } private void invalidateHandler() { - if (!mActivityInterface.isInLiveTileMode() || mGestureState.getEndTarget() != RECENTS) { + if (!mContainerInterface.isInLiveTileMode() || mGestureState.getEndTarget() != RECENTS) { mInputConsumerProxy.destroy(); mTaskAnimationManager.setLiveTileCleanUpHandler(null); } @@ -2013,11 +2015,11 @@ public abstract class AbsSwipeUpHandler, * continued quick switch gesture, which cancels the previous handler but doesn't invalidate it. */ private void resetLauncherListeners() { - if (mActivity != null) { - mActivity.removeEventCallback(EVENT_STARTED, mLauncherOnStartCallback); - mActivity.removeEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback); + if (mContainer != null) { + mContainer.removeEventCallback(EVENT_STARTED, mLauncherOnStartCallback); + mContainer.removeEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback); - mActivity.getRootView().setOnApplyWindowInsetsListener(null); + mContainer.getRootView().setOnApplyWindowInsetsListener(null); } if (mRecentsView != null) { mRecentsView.removeOnScrollChangedListener(mOnRecentsScrollListener); @@ -2026,11 +2028,11 @@ public abstract class AbsSwipeUpHandler, private void resetStateForAnimationCancel() { boolean wasVisible = mWasLauncherAlreadyVisible || mGestureStarted; - mActivityInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget()); + mContainerInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget()); // Leave the pending invisible flag, as it may be used by wallpaper open animation. - if (mActivity != null) { - mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER); + if (mContainer != null) { + mContainer.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER); } } @@ -2296,14 +2298,14 @@ public abstract class AbsSwipeUpHandler, onRestartPreviouslyAppearedTask(); } } else { - mActivityInterface.onLaunchTaskFailed(); + mContainerInterface.onLaunchTaskFailed(); if (mRecentsAnimationController != null) { mRecentsAnimationController.finish(true /* toRecents */, null); } } }, true /* freezeTaskList */); } else { - mActivityInterface.onLaunchTaskFailed(); + mContainerInterface.onLaunchTaskFailed(); Toast.makeText(mContext, R.string.activity_not_available, LENGTH_SHORT).show(); if (mRecentsAnimationController != null) { mRecentsAnimationController.finish(true /* toRecents */, null); @@ -2395,12 +2397,12 @@ public abstract class AbsSwipeUpHandler, finishRecentsAnimationOnTasksAppeared(null /* onFinishComplete */); return; } - if (mActivity == null) { + if (mContainer == null) { ActiveGestureLog.INSTANCE.addLog("Activity destroyed"); finishRecentsAnimationOnTasksAppeared(null /* onFinishComplete */); return; } - animateSplashScreenExit(mActivity, appearedTaskTargets, taskTarget.leash); + animateSplashScreenExit(mContainer, appearedTaskTargets, taskTarget.leash); } private void animateSplashScreenExit( @@ -2515,7 +2517,7 @@ public abstract class AbsSwipeUpHandler, transaction.setAlpha(app.leash, 1f - fadeProgress); transaction.setPosition(app.leash, /* x= */ app.startBounds.left - + (mActivity.getDeviceProfile().overviewPageSpacing + + (mContainer.getDeviceProfile().overviewPageSpacing * (mRecentsView.isRtl() ? fadeProgress : -fadeProgress)), /* y= */ 0f); transaction.setScale(app.leash, 1f, 1f); @@ -2566,7 +2568,7 @@ public abstract class AbsSwipeUpHandler, // Scaling of RecentsView during quick switch based on amount of recents scroll private float getScaleProgressDueToScroll() { - if (mActivity == null || !mActivity.getDeviceProfile().isTablet || mRecentsView == null + if (mContainer == null || !mContainer.getDeviceProfile().isTablet || mRecentsView == null || !shouldLinkRecentsViewScroll()) { return 0; } diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index a3a5f82bdd..00cd60b1d6 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -18,11 +18,9 @@ package com.android.quickstep; import static com.android.app.animation.Interpolators.ACCELERATE_2; import static com.android.app.animation.Interpolators.INSTANT; import static com.android.app.animation.Interpolators.LINEAR; -import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR; import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe; import static com.android.quickstep.AbsSwipeUpHandler.RECENTS_ATTACH_DURATION; import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK; -import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS; import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM; import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET; @@ -33,23 +31,12 @@ import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; -import android.content.Context; -import android.content.res.Resources; import android.graphics.Color; -import android.graphics.PointF; -import android.graphics.Rect; -import android.view.Gravity; import android.view.MotionEvent; -import android.view.RemoteAnimationTarget; -import android.view.View; import androidx.annotation.Nullable; import androidx.annotation.UiThread; -import com.android.launcher3.DeviceProfile; -import com.android.launcher3.Flags; -import com.android.launcher3.R; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.statehandlers.DepthController; @@ -57,29 +44,23 @@ import com.android.launcher3.statehandlers.DesktopVisibilityController; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.taskbar.TaskbarUIController; -import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.NavigationMode; -import com.android.launcher3.views.ScrimView; -import com.android.quickstep.orientation.RecentsPagedOrientationHandler; -import com.android.quickstep.util.ActivityInitListener; import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; import com.android.systemui.shared.recents.model.ThumbnailData; import java.util.HashMap; import java.util.Optional; import java.util.function.Consumer; -import java.util.function.Predicate; /** * Utility class which abstracts out the logical differences between Launcher and RecentsActivity. */ public abstract class BaseActivityInterface, - ACTIVITY_TYPE extends StatefulActivity> { - - public final boolean rotationSupportedByActivity; - + ACTIVITY_TYPE extends StatefulActivity & RecentsViewContainer> extends + BaseContainerInterface { private final STATE_TYPE mBackgroundState; private STATE_TYPE mTargetState; @@ -100,7 +81,7 @@ public abstract class BaseActivityInterface callback); - - public abstract ActivityInitListener createActivityInitListener( - Predicate onInitListener); - - /** - * Sets a callback to be run when an activity launch happens while launcher is not yet resumed. - */ - public void setOnDeferredActivityLaunchCallback(Runnable r) {} - @Nullable - public abstract ACTIVITY_TYPE getCreatedActivity(); + public abstract ACTIVITY_TYPE getCreatedContainer(); @Nullable public DepthController getDepthController() { return null; } - @Nullable - public DesktopVisibilityController getDesktopVisibilityController() { - return null; - } - - @Nullable - public abstract TaskbarUIController getTaskbarController(); - public final boolean isResumed() { - ACTIVITY_TYPE activity = getCreatedActivity(); + ACTIVITY_TYPE activity = getCreatedContainer(); return activity != null && activity.hasBeenResumed(); } public final boolean isStarted() { - ACTIVITY_TYPE activity = getCreatedActivity(); + ACTIVITY_TYPE activity = getCreatedContainer(); return activity != null && activity.isStarted(); } @@ -177,14 +130,6 @@ public abstract class BaseActivityInterface thumbnailDatas, Runnable runnable) { - ACTIVITY_TYPE activity = getCreatedActivity(); + ACTIVITY_TYPE activity = getCreatedContainer(); if (activity == null) { return; } @@ -231,230 +162,9 @@ public abstract class BaseActivityInterface callback) { mCallback = callback; - mActivity = getCreatedActivity(); + mActivity = getCreatedContainer(); mStartState = mActivity.getStateManager().getState(); } diff --git a/quickstep/src/com/android/quickstep/BaseContainerInterface.java b/quickstep/src/com/android/quickstep/BaseContainerInterface.java new file mode 100644 index 0000000000..99551834f1 --- /dev/null +++ b/quickstep/src/com/android/quickstep/BaseContainerInterface.java @@ -0,0 +1,377 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep; + +import static com.android.app.animation.Interpolators.INSTANT; +import static com.android.app.animation.Interpolators.LINEAR; +import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR; +import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK; +import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Color; +import android.graphics.PointF; +import android.graphics.Rect; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.RemoteAnimationTarget; +import android.view.View; + +import androidx.annotation.Nullable; + +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Flags; +import com.android.launcher3.R; +import com.android.launcher3.statehandlers.DesktopVisibilityController; +import com.android.launcher3.statemanager.BaseState; +import com.android.launcher3.taskbar.TaskbarUIController; +import com.android.launcher3.touch.PagedOrientationHandler; +import com.android.launcher3.util.DisplayController; +import com.android.launcher3.views.ScrimView; +import com.android.quickstep.orientation.RecentsPagedOrientationHandler; +import com.android.quickstep.util.ActivityInitListener; +import com.android.quickstep.util.AnimatorControllerWithResistance; +import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; +import com.android.systemui.shared.recents.model.ThumbnailData; + +import java.util.HashMap; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public abstract class BaseContainerInterface, + CONTAINER_TYPE extends RecentsViewContainer> { + + public boolean rotationSupportedByActivity = false; + + @Nullable + public abstract CONTAINER_TYPE getCreatedContainer(); + + public abstract boolean isInLiveTileMode(); + + public abstract void onAssistantVisibilityChanged(float assistantVisibility); + + public abstract boolean allowMinimizeSplitScreen(); + + public abstract boolean isResumed(); + + public abstract boolean isStarted(); + public abstract boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, + MotionEvent ev); + + /** @return whether to allow going to All Apps from Overview. */ + public abstract boolean allowAllAppsFromOverview(); + + /** + * Returns the color of the scrim behind overview when at rest in this state. + * Return {@link Color#TRANSPARENT} for no scrim. + */ + protected abstract int getOverviewScrimColorForState(CONTAINER_TYPE container, + STATE_TYPE state); + + public abstract int getSwipeUpDestinationAndLength( + DeviceProfile dp, Context context, Rect outRect, + RecentsPagedOrientationHandler orientationHandler); + + @Nullable + public abstract TaskbarUIController getTaskbarController(); + + public abstract BaseActivityInterface.AnimationFactory prepareRecentsUI( + RecentsAnimationDeviceState deviceState, boolean activityVisible, + Consumer callback); + + public abstract ActivityInitListener createActivityInitListener( + Predicate onInitListener); + /** + * Returns the expected STATE_TYPE from the provided GestureEndTarget. + */ + public abstract STATE_TYPE stateFromGestureEndTarget(GestureState.GestureEndTarget endTarget); + + public abstract void switchRunningTaskViewToScreenshot(HashMap thumbnailDatas, Runnable runnable); + + public abstract void closeOverlay(); + + public abstract Rect getOverviewWindowBounds( + Rect homeBounds, RemoteAnimationTarget target); + + public abstract void onLaunchTaskFailed(); + + public abstract void onExitOverview(RotationTouchHelper deviceState, + Runnable exitRunnable); + + /** Called when the animation to home has fully settled. */ + public void onSwipeUpToHomeComplete(RecentsAnimationDeviceState deviceState) {} + + /** + * Sets a callback to be run when an activity launch happens while launcher is not yet resumed. + */ + public void setOnDeferredActivityLaunchCallback(Runnable r) {} + /** + * @return Whether the gesture in progress should be cancelled. + */ + public boolean shouldCancelCurrentGesture() { + return false; + } + + @Nullable + public DesktopVisibilityController getDesktopVisibilityController() { + return null; + } + + /** + * Called when the gesture ends and the animation starts towards the given target. Used to add + * an optional additional animation with the same duration. + */ + public @Nullable Animator getParallelAnimationToLauncher( + GestureState.GestureEndTarget endTarget, long duration, + RecentsAnimationCallbacks callbacks) { + if (endTarget == RECENTS) { + CONTAINER_TYPE container = getCreatedContainer(); + if (container == null) { + return null; + } + RecentsView recentsView = container.getOverviewPanel(); + STATE_TYPE state = stateFromGestureEndTarget(endTarget); + ScrimView scrimView = container.getScrimView(); + ObjectAnimator anim = ObjectAnimator.ofArgb(scrimView, VIEW_BACKGROUND_COLOR, + getOverviewScrimColorForState(container, state)); + anim.setDuration(duration); + anim.setInterpolator(recentsView == null || !recentsView.isKeyboardTaskFocusPending() + ? LINEAR : INSTANT); + return anim; + } + return null; + } + + /** + * Called when the animation to the target has finished, but right before updating the state. + * @return A View that needs to draw before ending the recents animation to LAST_TASK. + * (This is a hack to ensure Taskbar draws its background first to avoid flickering.) + */ + public @Nullable View onSettledOnEndTarget(GestureState.GestureEndTarget endTarget) { + TaskbarUIController taskbarUIController = getTaskbarController(); + if (taskbarUIController != null) { + taskbarUIController.setSystemGestureInProgress(false); + return taskbarUIController.getRootView(); + } + return null; + } + + /** + * Called when the current gesture transition is cancelled. + * @param activityVisible Whether the user can see the changes we make here, so try to animate. + * @param endTarget If the gesture ended before we got cancelled, where we were headed. + */ + public void onTransitionCancelled(boolean activityVisible, + @Nullable GestureState.GestureEndTarget endTarget) { + RecentsViewContainer container = getCreatedContainer(); + if (container == null) { + return; + } + RecentsView recentsView = container.getOverviewPanel(); + BaseState startState = recentsView.getStateManager().getRestState(); + if (endTarget != null) { + // We were on our way to this state when we got canceled, end there instead. + startState = stateFromGestureEndTarget(endTarget); + DesktopVisibilityController controller = getDesktopVisibilityController(); + if (controller != null && controller.areDesktopTasksVisible() + && endTarget == LAST_TASK) { + // When we are cancelling the transition and going back to last task, move to + // rest state instead when desktop tasks are visible. + // If a fullscreen task is visible, launcher goes to normal state when the + // activity is stopped. This does not happen when desktop tasks are visible + // on top of launcher. Force the launcher state to rest state here. + startState = recentsView.getStateManager().getRestState(); + // Do not animate the transition + activityVisible = false; + } + } + recentsView.getStateManager().goToState(startState, activityVisible); + } + + public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect, + PagedOrientationHandler orientedState) { + if (dp.isTablet) { + if (Flags.enableGridOnlyOverview()) { + calculateGridTaskSize(context, dp, outRect, orientedState); + } else { + calculateFocusTaskSize(context, dp, outRect); + } + } else { + Resources res = context.getResources(); + float maxScale = res.getFloat(R.dimen.overview_max_scale); + int taskMargin = dp.overviewTaskMarginPx; + calculateTaskSizeInternal( + context, + dp, + dp.overviewTaskThumbnailTopMarginPx, + dp.getOverviewActionsClaimedSpace(), + res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin, + maxScale, + Gravity.CENTER, + outRect); + } + } + + /** + * Calculates the taskView size for carousel during app to overview animation on tablets. + */ + public final void calculateCarouselTaskSize(Context context, DeviceProfile dp, Rect outRect, + PagedOrientationHandler orientedState) { + if (dp.isTablet && dp.isGestureMode) { + Resources res = context.getResources(); + float minScale = res.getFloat(R.dimen.overview_carousel_min_scale); + Rect gridRect = new Rect(); + calculateGridSize(dp, context, gridRect); + calculateTaskSizeInternal(context, dp, gridRect, minScale, Gravity.CENTER | Gravity.TOP, + outRect); + } else { + calculateTaskSize(context, dp, outRect, orientedState); + } + } + + private void calculateFocusTaskSize(Context context, DeviceProfile dp, Rect outRect) { + Resources res = context.getResources(); + float maxScale = res.getFloat(R.dimen.overview_max_scale); + Rect gridRect = new Rect(); + calculateGridSize(dp, context, gridRect); + calculateTaskSizeInternal(context, dp, gridRect, maxScale, Gravity.CENTER, outRect); + } + + private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove, + int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity, + Rect outRect) { + Rect insets = dp.getInsets(); + + Rect potentialTaskRect = new Rect(0, 0, dp.widthPx, dp.heightPx); + potentialTaskRect.inset(insets.left, insets.top, insets.right, insets.bottom); + potentialTaskRect.inset( + minimumHorizontalPadding, + claimedSpaceAbove, + minimumHorizontalPadding, + claimedSpaceBelow); + + calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect); + } + + private void calculateTaskSizeInternal(Context context, DeviceProfile dp, + Rect potentialTaskRect, float targetScale, int gravity, Rect outRect) { + PointF taskDimension = getTaskDimension(context, dp); + + float scale = Math.min( + potentialTaskRect.width() / taskDimension.x, + potentialTaskRect.height() / taskDimension.y); + scale = Math.min(scale, targetScale); + int outWidth = Math.round(scale * taskDimension.x); + int outHeight = Math.round(scale * taskDimension.y); + + Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect); + } + + private static PointF getTaskDimension(Context context, DeviceProfile dp) { + PointF dimension = new PointF(); + getTaskDimension(context, dp, dimension); + return dimension; + } + + /** + * Gets the dimension of the task in the current system state. + */ + public static void getTaskDimension(Context context, DeviceProfile dp, PointF out) { + out.x = dp.widthPx; + out.y = dp.heightPx; + if (dp.isTablet && !DisplayController.isTransientTaskbar(context)) { + out.y -= dp.taskbarHeight; + } + } + + /** + * Calculates the overview grid size for the provided device configuration. + */ + public final void calculateGridSize(DeviceProfile dp, Context context, Rect outRect) { + Rect insets = dp.getInsets(); + int topMargin = dp.overviewTaskThumbnailTopMarginPx; + int bottomMargin = dp.getOverviewActionsClaimedSpace(); + if (dp.isTaskbarPresent && Flags.enableGridOnlyOverview()) { + topMargin += context.getResources().getDimensionPixelSize( + R.dimen.overview_top_margin_grid_only); + bottomMargin += context.getResources().getDimensionPixelSize( + R.dimen.overview_bottom_margin_grid_only); + } + int sideMargin = dp.overviewGridSideMargin; + + outRect.set(0, 0, dp.widthPx, dp.heightPx); + outRect.inset(Math.max(insets.left, sideMargin), insets.top + topMargin, + Math.max(insets.right, sideMargin), Math.max(insets.bottom, bottomMargin)); + } + + /** + * Calculates the overview grid non-focused task size for the provided device configuration. + */ + public final void calculateGridTaskSize(Context context, DeviceProfile dp, Rect outRect, + PagedOrientationHandler orientedState) { + Resources res = context.getResources(); + Rect potentialTaskRect = new Rect(); + if (Flags.enableGridOnlyOverview()) { + calculateGridSize(dp, context, potentialTaskRect); + } else { + calculateFocusTaskSize(context, dp, potentialTaskRect); + } + + float rowHeight = (potentialTaskRect.height() + dp.overviewTaskThumbnailTopMarginPx + - dp.overviewRowSpacing) / 2f; + + PointF taskDimension = getTaskDimension(context, dp); + float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / taskDimension.y; + int outWidth = Math.round(scale * taskDimension.x); + int outHeight = Math.round(scale * taskDimension.y); + + int gravity = Gravity.TOP; + gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT; + Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect); + } + + /** + * Calculates the modal taskView size for the provided device configuration + */ + public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect, + PagedOrientationHandler orientedState) { + calculateTaskSize(context, dp, outRect, orientedState); + boolean isGridOnlyOverview = dp.isTablet && Flags.enableGridOnlyOverview(); + int claimedSpaceBelow = isGridOnlyOverview + ? dp.overviewActionsTopMarginPx + dp.overviewActionsHeight + dp.stashedTaskbarHeight + : (dp.heightPx - outRect.bottom - dp.getInsets().bottom); + int minimumHorizontalPadding = 0; + if (!isGridOnlyOverview) { + float maxScale = context.getResources().getFloat(R.dimen.overview_modal_max_scale); + minimumHorizontalPadding = + Math.round((dp.availableWidthPx - outRect.width() * maxScale) / 2); + } + calculateTaskSizeInternal( + context, + dp, + dp.overviewTaskMarginPx, + claimedSpaceBelow, + minimumHorizontalPadding, + 1f /*maxScale*/, + Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, + outRect); + } +} diff --git a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt index 8c71d925e4..aa0f728b8b 100644 --- a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt +++ b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt @@ -18,24 +18,24 @@ package com.android.quickstep import android.view.View import com.android.launcher3.AbstractFloatingViewHelper -import com.android.launcher3.BaseDraggingActivity import com.android.launcher3.R import com.android.launcher3.logging.StatsLogManager.LauncherEvent import com.android.launcher3.popup.SystemShortcut import com.android.quickstep.views.RecentsView +import com.android.quickstep.views.RecentsViewContainer import com.android.quickstep.views.TaskView.TaskIdAttributeContainer import com.android.window.flags.Flags /** A menu item, "Desktop", that allows the user to bring the current app into Desktop Windowing. */ class DesktopSystemShortcut( - activity: BaseDraggingActivity, + container: RecentsViewContainer, private val mTaskContainer: TaskIdAttributeContainer, abstractFloatingViewHelper: AbstractFloatingViewHelper ) : - SystemShortcut( + SystemShortcut( R.drawable.ic_caption_desktop_button_foreground, R.string.recent_task_option_desktop, - activity, + container, mTaskContainer.itemInfo, mTaskContainer.taskView, abstractFloatingViewHelper @@ -59,7 +59,7 @@ class DesktopSystemShortcut( ): TaskShortcutFactory { return object : TaskShortcutFactory { override fun getShortcuts( - activity: BaseDraggingActivity, + container: RecentsViewContainer, taskContainer: TaskIdAttributeContainer ): List? { return if (!Flags.enableDesktopWindowingMode()) null @@ -67,7 +67,7 @@ class DesktopSystemShortcut( else listOf( DesktopSystemShortcut( - activity, + container, taskContainer, abstractFloatingViewHelper ) diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java index 27e8726975..9e896fddc5 100644 --- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java +++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java @@ -96,13 +96,13 @@ public final class FallbackActivityInterface extends @Nullable @Override - public RecentsActivity getCreatedActivity() { + public RecentsActivity getCreatedContainer() { return RecentsActivity.ACTIVITY_TRACKER.getCreatedActivity(); } @Override public FallbackTaskbarUIController getTaskbarController() { - RecentsActivity activity = getCreatedActivity(); + RecentsActivity activity = getCreatedContainer(); if (activity == null) { return null; } @@ -112,7 +112,7 @@ public final class FallbackActivityInterface extends @Nullable @Override public RecentsView getVisibleRecentsView() { - RecentsActivity activity = getCreatedActivity(); + RecentsActivity activity = getCreatedContainer(); if (activity != null) { if (activity.hasBeenResumed() || isInLiveTileMode()) { return activity.getOverviewPanel(); @@ -154,7 +154,7 @@ public final class FallbackActivityInterface extends @Override public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) { - final StateManager stateManager = getCreatedActivity().getStateManager(); + final StateManager stateManager = getCreatedContainer().getStateManager(); if (stateManager.getState() == HOME) { exitRunnable.run(); notifyRecentsOfOrientation(deviceState); @@ -177,7 +177,7 @@ public final class FallbackActivityInterface extends @Override public boolean isInLiveTileMode() { - RecentsActivity activity = getCreatedActivity(); + RecentsActivity activity = getCreatedContainer(); return activity != null && activity.getStateManager().getState() == DEFAULT && activity.isStarted(); } @@ -185,7 +185,7 @@ public final class FallbackActivityInterface extends @Override public void onLaunchTaskFailed() { // TODO: probably go back to overview instead. - RecentsActivity activity = getCreatedActivity(); + RecentsActivity activity = getCreatedContainer(); if (activity == null) { return; } @@ -209,7 +209,7 @@ public final class FallbackActivityInterface extends private void notifyRecentsOfOrientation(RotationTouchHelper rotationTouchHelper) { // reset layout on swipe to home - RecentsView recentsView = getCreatedActivity().getOverviewPanel(); + RecentsView recentsView = getCreatedContainer().getOverviewPanel(); recentsView.setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(), rotationTouchHelper.getDisplayRotation()); } diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java index b42eb067e4..92cdf72c73 100644 --- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java @@ -223,7 +223,7 @@ public class FallbackSwipeHandler extends public AnimatorPlaybackController createActivityAnimationToHome() { // copied from {@link LauncherSwipeHandlerV2.LauncherHomeAnimationFactory} long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx); - return mActivity.getStateManager().createAnimationToNewWorkspace( + return mContainer.getStateManager().createAnimationToNewWorkspace( RecentsState.HOME, accuracy, StateAnimationConfig.SKIP_ALL_ANIMATIONS); } } diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java index d02909c527..6b33c0aacb 100644 --- a/quickstep/src/com/android/quickstep/GestureState.java +++ b/quickstep/src/com/android/quickstep/GestureState.java @@ -37,10 +37,10 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.statemanager.BaseState; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.quickstep.TopTaskTracker.CachedTaskInfo; import com.android.quickstep.util.ActiveGestureErrorDetector; import com.android.quickstep.util.ActiveGestureLog; +import com.android.quickstep.views.RecentsViewContainer; import com.android.systemui.shared.recents.model.ThumbnailData; import java.io.PrintWriter; @@ -151,7 +151,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL // Needed to interact with the current activity private final Intent mHomeIntent; private final Intent mOverviewIntent; - private final BaseActivityInterface mActivityInterface; + private final BaseContainerInterface mContainerInterface; private final MultiStateCallback mStateCallback; private final int mGestureId; @@ -189,7 +189,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL public GestureState(OverviewComponentObserver componentObserver, int gestureId) { mHomeIntent = componentObserver.getHomeIntent(); mOverviewIntent = componentObserver.getOverviewIntent(); - mActivityInterface = componentObserver.getActivityInterface(); + mContainerInterface = componentObserver.getActivityInterface(); mStateCallback = new MultiStateCallback( STATE_NAMES.toArray(new String[0]), GestureState::getTrackedEventForState); mGestureId = gestureId; @@ -198,7 +198,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL public GestureState(GestureState other) { mHomeIntent = other.mHomeIntent; mOverviewIntent = other.mOverviewIntent; - mActivityInterface = other.mActivityInterface; + mContainerInterface = other.mContainerInterface; mStateCallback = other.mStateCallback; mGestureId = other.mGestureId; mRunningTask = other.mRunningTask; @@ -212,7 +212,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL // Do nothing, only used for initializing the gesture state prior to user unlock mHomeIntent = new Intent(); mOverviewIntent = new Intent(); - mActivityInterface = null; + mContainerInterface = null; mStateCallback = new MultiStateCallback( STATE_NAMES.toArray(new String[0]), GestureState::getTrackedEventForState); mGestureId = -1; @@ -268,9 +268,9 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL /** * @return the interface to the activity handing the UI updates for this gesture. */ - public , - T extends StatefulActivity> BaseActivityInterface getActivityInterface() { - return mActivityInterface; + public , T extends RecentsViewContainer> + BaseContainerInterface getContainerInterface() { + return mContainerInterface; } /** diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java index 7c17e4ee7a..7655c5913e 100644 --- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java @@ -36,7 +36,6 @@ import androidx.annotation.UiThread; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Flags; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAnimUtils; import com.android.launcher3.LauncherInitListener; import com.android.launcher3.LauncherState; @@ -86,7 +85,7 @@ public final class LauncherActivityInterface extends @Override public void onSwipeUpToHomeComplete(RecentsAnimationDeviceState deviceState) { - Launcher launcher = getCreatedActivity(); + QuickstepLauncher launcher = getCreatedContainer(); if (launcher == null) { return; } @@ -103,7 +102,7 @@ public final class LauncherActivityInterface extends @Override public void onAssistantVisibilityChanged(float visibility) { - Launcher launcher = getCreatedActivity(); + QuickstepLauncher launcher = getCreatedContainer(); if (launcher == null) { return; } @@ -145,7 +144,7 @@ public final class LauncherActivityInterface extends @Override public void setOnDeferredActivityLaunchCallback(Runnable r) { - Launcher launcher = getCreatedActivity(); + QuickstepLauncher launcher = getCreatedContainer(); if (launcher == null) { return; } @@ -154,14 +153,14 @@ public final class LauncherActivityInterface extends @Nullable @Override - public QuickstepLauncher getCreatedActivity() { + public QuickstepLauncher getCreatedContainer() { return QuickstepLauncher.ACTIVITY_TRACKER.getCreatedActivity(); } @Nullable @Override public DepthController getDepthController() { - QuickstepLauncher launcher = getCreatedActivity(); + QuickstepLauncher launcher = getCreatedContainer(); if (launcher == null) { return null; } @@ -171,7 +170,7 @@ public final class LauncherActivityInterface extends @Nullable @Override public DesktopVisibilityController getDesktopVisibilityController() { - QuickstepLauncher launcher = getCreatedActivity(); + QuickstepLauncher launcher = getCreatedContainer(); if (launcher == null) { return null; } @@ -181,7 +180,7 @@ public final class LauncherActivityInterface extends @Nullable @Override public LauncherTaskbarUIController getTaskbarController() { - QuickstepLauncher launcher = getCreatedActivity(); + QuickstepLauncher launcher = getCreatedContainer(); if (launcher == null) { return null; } @@ -191,7 +190,7 @@ public final class LauncherActivityInterface extends @Nullable @Override public RecentsView getVisibleRecentsView() { - Launcher launcher = getVisibleLauncher(); + QuickstepLauncher launcher = getVisibleLauncher(); RecentsView recentsView = launcher != null && launcher.getStateManager().getState().overviewUi ? launcher.getOverviewPanel() : null; @@ -205,8 +204,8 @@ public final class LauncherActivityInterface extends @Nullable @UiThread - private Launcher getVisibleLauncher() { - Launcher launcher = getCreatedActivity(); + private QuickstepLauncher getVisibleLauncher() { + QuickstepLauncher launcher = getCreatedContainer(); if (launcher == null) { return null; } @@ -222,7 +221,7 @@ public final class LauncherActivityInterface extends @Override public boolean switchToRecentsIfVisible(Animator.AnimatorListener animatorListener) { - Launcher launcher = getVisibleLauncher(); + QuickstepLauncher launcher = getVisibleLauncher(); if (launcher == null) { return false; } @@ -243,7 +242,7 @@ public final class LauncherActivityInterface extends @Override public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) { - final StateManager stateManager = getCreatedActivity().getStateManager(); + final StateManager stateManager = getCreatedContainer().getStateManager(); stateManager.addStateListener( new StateManager.StateListener() { @Override @@ -260,7 +259,7 @@ public final class LauncherActivityInterface extends private void notifyRecentsOfOrientation(RotationTouchHelper rotationTouchHelper) { // reset layout on swipe to home - RecentsView recentsView = getCreatedActivity().getOverviewPanel(); + RecentsView recentsView = getCreatedContainer().getOverviewPanel(); recentsView.setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(), rotationTouchHelper.getDisplayRotation()); } @@ -279,12 +278,12 @@ public final class LauncherActivityInterface extends public boolean allowAllAppsFromOverview() { return FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get() // If floating search bar would not show in overview, don't allow all apps gesture. - && OVERVIEW.areElementsVisible(getCreatedActivity(), FLOATING_SEARCH_BAR); + && OVERVIEW.areElementsVisible(getCreatedContainer(), FLOATING_SEARCH_BAR); } @Override public boolean isInLiveTileMode() { - Launcher launcher = getCreatedActivity(); + QuickstepLauncher launcher = getCreatedContainer(); return launcher != null && launcher.getStateManager().getState() == OVERVIEW @@ -294,7 +293,7 @@ public final class LauncherActivityInterface extends @Override public void onLaunchTaskFailed() { - Launcher launcher = getCreatedActivity(); + QuickstepLauncher launcher = getCreatedContainer(); if (launcher == null) { return; } @@ -304,7 +303,7 @@ public final class LauncherActivityInterface extends @Override public void closeOverlay() { super.closeOverlay(); - Launcher launcher = getCreatedActivity(); + QuickstepLauncher launcher = getCreatedContainer(); if (launcher == null) { return; } @@ -337,9 +336,8 @@ public final class LauncherActivityInterface extends } @Override - protected int getOverviewScrimColorForState(QuickstepLauncher launcher, - LauncherState state) { - return state.getWorkspaceScrimColor(launcher); + protected int getOverviewScrimColorForState(QuickstepLauncher activity, LauncherState state) { + return state.getWorkspaceScrimColor(activity); } @Override diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java index f678bea778..6647057776 100644 --- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java +++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java @@ -75,7 +75,7 @@ public class LauncherSwipeHandlerV2 extends protected HomeAnimationFactory createHomeAnimationFactory(ArrayList launchCookies, long duration, boolean isTargetTranslucent, boolean appCanEnterPip, RemoteAnimationTarget runningTaskTarget) { - if (mActivity == null) { + if (mContainer == null) { mStateCallback.addChangeListener(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED, isPresent -> mRecentsView.startHome()); return new HomeAnimationFactory() { @@ -91,9 +91,9 @@ public class LauncherSwipeHandlerV2 extends boolean canUseWorkspaceView = workspaceView != null && workspaceView.isAttachedToWindow() && workspaceView.getHeight() > 0; - mActivity.getRootView().setForceHideBackArrow(true); + mContainer.getRootView().setForceHideBackArrow(true); if (!TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) { - mActivity.setHintUserWillBeActive(); + mContainer.setHintUserWillBeActive(); } if (!canUseWorkspaceView || appCanEnterPip || mIsSwipeForSplit) { @@ -108,10 +108,10 @@ public class LauncherSwipeHandlerV2 extends private HomeAnimationFactory createIconHomeAnimationFactory(View workspaceView) { RectF iconLocation = new RectF(); - FloatingIconView floatingIconView = getFloatingIconView(mActivity, workspaceView, null, - mActivity.getTaskbarUIController() == null + FloatingIconView floatingIconView = getFloatingIconView(mContainer, workspaceView, null, + mContainer.getTaskbarUIController() == null ? null - : mActivity.getTaskbarUIController().findMatchingView(workspaceView), + : mContainer.getTaskbarUIController().findMatchingView(workspaceView), true /* hideOriginal */, iconLocation, false /* isOpening */); // We want the window alpha to be 0 once this threshold is met, so that the @@ -171,7 +171,7 @@ public class LauncherSwipeHandlerV2 extends Size windowSize = new Size(crop.width(), crop.height()); int fallbackBackgroundColor = FloatingWidgetView.getDefaultBackgroundColor(mContext, runningTaskTarget); - FloatingWidgetView floatingWidgetView = FloatingWidgetView.getFloatingWidgetView(mActivity, + FloatingWidgetView floatingWidgetView = FloatingWidgetView.getFloatingWidgetView(mContainer, hostView, backgroundLocation, windowSize, tvs.getCurrentCornerRadius(), isTargetTranslucent, fallbackBackgroundColor); @@ -248,7 +248,7 @@ public class LauncherSwipeHandlerV2 extends } } - return mActivity.getFirstMatchForAppClose(launchCookieItemId, + return mContainer.getFirstMatchForAppClose(launchCookieItemId, runningTaskView.getTask().key.getComponent().getPackageName(), UserHandle.of(runningTaskView.getTask().key.userId), false /* supportsAllAppsState */); @@ -292,18 +292,18 @@ public class LauncherSwipeHandlerV2 extends // Return an empty APC here since we have an non-user controlled animation // to home. long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx); - return mActivity.getStateManager().createAnimationToNewWorkspace( + return mContainer.getStateManager().createAnimationToNewWorkspace( NORMAL, accuracy, StateAnimationConfig.SKIP_ALL_ANIMATIONS); } @Override public void playAtomicAnimation(float velocity) { if (enableScalingRevealHomeAnimation()) { - if (mActivity != null) { - new ScalingWorkspaceRevealAnim(mActivity).start(); + if (mContainer != null) { + new ScalingWorkspaceRevealAnim(mContainer).start(); } } else { - new StaggeredWorkspaceAnim(mActivity, velocity, true /* animateOverviewScrim */, + new StaggeredWorkspaceAnim(mContainer, velocity, true /* animateOverviewScrim */, getViewIgnoredInWorkspaceRevealAnimation()) .start(); } diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java index 0db50bfe2d..68923eeccb 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java @@ -40,6 +40,7 @@ import com.android.launcher3.util.RunnableList; import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener; import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; @@ -191,7 +192,8 @@ public class OverviewCommandHelper { * Executes the task and returns true if next task can be executed. If false, then the next * task is deferred until {@link #scheduleNextTask} is called */ - private > boolean executeCommand(CommandInfo cmd) { + private & RecentsViewContainer> boolean executeCommand( + CommandInfo cmd) { if (mWaitForToggleCommandComplete && cmd.type == TYPE_TOGGLE) { return true; } @@ -200,7 +202,7 @@ public class OverviewCommandHelper { RecentsView visibleRecentsView = activityInterface.getVisibleRecentsView(); RecentsView createdRecentsView; if (visibleRecentsView == null) { - T activity = activityInterface.getCreatedActivity(); + T activity = activityInterface.getCreatedContainer(); createdRecentsView = activity == null ? null : activity.getOverviewPanel(); DeviceProfile dp = activity == null ? null : activity.getDeviceProfile(); TaskbarUIController uiController = activityInterface.getTaskbarController(); @@ -296,7 +298,7 @@ public class OverviewCommandHelper { return false; } - final T activity = activityInterface.getCreatedActivity(); + final T activity = activityInterface.getCreatedContainer(); if (activity != null) { InteractionJankMonitorWrapper.begin( activity.getRootView(), @@ -327,7 +329,7 @@ public class OverviewCommandHelper { interactionHandler.onGestureCancelled(); cmd.removeListener(this); - T createdActivity = activityInterface.getCreatedActivity(); + T createdActivity = activityInterface.getCreatedContainer(); if (createdActivity == null) { return; } diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java index c3a4351d7b..dfbae657dd 100644 --- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java +++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java @@ -208,7 +208,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { RecentsAnimationDeviceState rads = new RecentsAnimationDeviceState(mContext); OverviewComponentObserver observer = new OverviewComponentObserver(mContext, rads); try { - return observer.getActivityInterface().getCreatedActivity(); + return observer.getActivityInterface().getCreatedContainer(); } finally { observer.onDestroy(); rads.destroy(); diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index 81ab6bedcc..f57f4c8440 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -33,6 +33,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.app.ActivityOptions; +import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; @@ -85,6 +86,7 @@ import com.android.quickstep.util.SplitSelectStateController; import com.android.quickstep.util.TISBindHelper; import com.android.quickstep.views.OverviewActionsView; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; import com.android.quickstep.views.TaskView; import java.io.FileDescriptor; @@ -95,7 +97,8 @@ import java.util.List; * A recents activity that shows the recently launched tasks as swipable task cards. * See {@link com.android.quickstep.views.RecentsView}. */ -public final class RecentsActivity extends StatefulActivity { +public final class RecentsActivity extends StatefulActivity implements + RecentsViewContainer { private static final String TAG = "RecentsActivity"; public static final ActivityTracker ACTIVITY_TRACKER = @@ -109,7 +112,7 @@ public final class RecentsActivity extends StatefulActivity { private RecentsDragLayer mDragLayer; private ScrimView mScrimView; private FallbackRecentsView mFallbackRecentsView; - private OverviewActionsView mActionsView; + private OverviewActionsView mActionsView; private TISBindHelper mTISBindHelper; private @Nullable FallbackTaskbarUIController mTaskbarUIController; @@ -224,11 +227,12 @@ public final class RecentsActivity extends StatefulActivity { } @Override - public T getOverviewPanel() { - return (T) mFallbackRecentsView; + public FallbackRecentsView getOverviewPanel() { + return mFallbackRecentsView; } - public OverviewActionsView getActionsView() { + @Override + public OverviewActionsView getActionsView() { return mActionsView; } diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java index 856e8af27e..7f2adedbca 100644 --- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java +++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java @@ -57,7 +57,7 @@ public class RemoteTargetGluer { /** * Use this constructor if remote targets are split-screen independent */ - public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy, + public RemoteTargetGluer(Context context, BaseContainerInterface sizingStrategy, RemoteAnimationTargets targets, boolean forDesktop) { init(context, sizingStrategy, targets.apps.length, forDesktop); } @@ -66,7 +66,7 @@ public class RemoteTargetGluer { * Use this constructor if you want the number of handles created to match the number of active * running tasks */ - public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy) { + public RemoteTargetGluer(Context context, BaseContainerInterface sizingStrategy) { DesktopVisibilityController desktopVisibilityController = LauncherActivityInterface.INSTANCE.getDesktopVisibilityController(); if (desktopVisibilityController != null) { @@ -84,13 +84,13 @@ public class RemoteTargetGluer { init(context, sizingStrategy, DEFAULT_NUM_HANDLES, false /* forDesktop */); } - private void init(Context context, BaseActivityInterface sizingStrategy, int numHandles, + private void init(Context context, BaseContainerInterface sizingStrategy, int numHandles, boolean forDesktop) { mRemoteTargetHandles = createHandles(context, sizingStrategy, numHandles, forDesktop); } private RemoteTargetHandle[] createHandles(Context context, - BaseActivityInterface sizingStrategy, int numHandles, boolean forDesktop) { + BaseContainerInterface sizingStrategy, int numHandles, boolean forDesktop) { RemoteTargetHandle[] handles = new RemoteTargetHandle[numHandles]; for (int i = 0; i < numHandles; i++) { TaskViewSimulator tvs = new TaskViewSimulator(context, sizingStrategy); diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java index 2d47097671..bf50d7022d 100644 --- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java +++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java @@ -345,14 +345,14 @@ public class RotationTouchHelper implements DisplayInfoChangeListener { } void onEndTargetCalculated(GestureState.GestureEndTarget endTarget, - BaseActivityInterface activityInterface) { + BaseContainerInterface containerInterface) { if (endTarget == GestureState.GestureEndTarget.RECENTS) { mInOverview = true; if (!mTaskListFrozen) { // If we're in landscape w/o ever quickswitching, show the navbar in landscape enableMultipleRegions(true); } - activityInterface.onExitOverview(this, mExitOverviewRunnable); + containerInterface.onExitOverview(this, mExitOverviewRunnable); } else if (endTarget == GestureState.GestureEndTarget.HOME || endTarget == GestureState.GestureEndTarget.ALL_APPS) { enableMultipleRegions(false); diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java index b920c10d05..5ff978746c 100644 --- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java +++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java @@ -86,7 +86,7 @@ public abstract class SwipeUpAnimationLogic implements updateIsGestureForSplit(TopTaskTracker.INSTANCE.get(context) .getRunningSplitTaskIds().length); - mTargetGluer = new RemoteTargetGluer(mContext, mGestureState.getActivityInterface()); + mTargetGluer = new RemoteTargetGluer(mContext, mGestureState.getContainerInterface()); mRemoteTargetHandles = mTargetGluer.getRemoteTargetHandles(); runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().getOrientationState().update( @@ -97,9 +97,10 @@ public abstract class SwipeUpAnimationLogic implements protected void initTransitionEndpoints(DeviceProfile dp) { mDp = dp; - mTransitionDragLength = mGestureState.getActivityInterface().getSwipeUpDestinationAndLength( - dp, mContext, TEMP_RECT, mRemoteTargetHandles[0].getTaskViewSimulator() - .getOrientationState().getOrientationHandler()); + mTransitionDragLength = mGestureState.getContainerInterface() + .getSwipeUpDestinationAndLength(dp, mContext, TEMP_RECT, + mRemoteTargetHandles[0].getTaskViewSimulator().getOrientationState() + .getOrientationHandler()); mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength; for (RemoteTargetHandle remoteHandle : mRemoteTargetHandles) { diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index 4e62d60d2c..3b1ed4662a 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -77,10 +77,11 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mLiveTileRestartListener); return; } - BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface(); - if (activityInterface.isInLiveTileMode() - && activityInterface.getCreatedActivity() != null) { - RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel(); + BaseContainerInterface containerInterface = mLastGestureState.getContainerInterface(); + if (containerInterface.isInLiveTileMode() + && containerInterface.getCreatedContainer() != null) { + RecentsView recentsView = containerInterface.getCreatedContainer() + .getOverviewPanel(); if (recentsView != null) { recentsView.launchSideTaskInLiveTileModeForRestartedApp(task.taskId); TaskStackChangeListeners.getInstance().unregisterTaskStackListener( @@ -135,10 +136,10 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn cleanUpRecentsAnimation(mCallbacks); } - final BaseActivityInterface activityInterface = gestureState.getActivityInterface(); + final BaseContainerInterface containerInterface = gestureState.getContainerInterface(); mLastGestureState = gestureState; RecentsAnimationCallbacks newCallbacks = new RecentsAnimationCallbacks( - SystemUiProxy.INSTANCE.get(mCtx), activityInterface.allowMinimizeSplitScreen()); + SystemUiProxy.INSTANCE.get(mCtx), containerInterface.allowMinimizeSplitScreen()); mCallbacks = newCallbacks; mCallbacks.addListener(new RecentsAnimationCallbacks.RecentsAnimationListener() { @Override @@ -208,17 +209,18 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn @Override public void onTasksAppeared(RemoteAnimationTarget[] appearedTaskTargets) { RemoteAnimationTarget appearedTaskTarget = appearedTaskTargets[0]; - BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface(); + BaseContainerInterface containerInterface = + mLastGestureState.getContainerInterface(); for (RemoteAnimationTarget compat : appearedTaskTargets) { if (compat.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME - && activityInterface.getCreatedActivity() instanceof RecentsActivity + && containerInterface.getCreatedContainer() instanceof RecentsActivity && DisplayController.getNavigationMode(mCtx) != NO_BUTTON) { // The only time we get onTasksAppeared() in button navigation with a // 3p launcher is if the user goes to overview first, and in this case we // can immediately finish the transition RecentsView recentsView = - activityInterface.getCreatedActivity().getOverviewPanel(); + containerInterface.getCreatedContainer().getOverviewPanel(); if (recentsView != null) { recentsView.finishRecentsAnimation(true, null); } @@ -232,12 +234,12 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn if (nonAppTargets == null) { nonAppTargets = new RemoteAnimationTarget[0]; } - if ((activityInterface.isInLiveTileMode() + if ((containerInterface.isInLiveTileMode() || mLastGestureState.getEndTarget() == RECENTS || isNonRecentsStartedTasksAppeared(appearedTaskTargets)) - && activityInterface.getCreatedActivity() != null) { + && containerInterface.getCreatedContainer() != null) { RecentsView recentsView = - activityInterface.getCreatedActivity().getOverviewPanel(); + containerInterface.getCreatedContainer().getOverviewPanel(); if (recentsView != null) { ActiveGestureLog.INSTANCE.addLog( new ActiveGestureLog.CompoundString("Launching side task id=") @@ -272,13 +274,13 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn @Override public boolean onSwitchToScreenshot(Runnable onFinished) { - if (!activityInterface.isInLiveTileMode() - || activityInterface.getCreatedActivity() == null) { + if (!containerInterface.isInLiveTileMode() + || containerInterface.getCreatedContainer() == null) { // No need to switch since tile is already a screenshot. onFinished.run(); } else { final RecentsView recentsView = - activityInterface.getCreatedActivity().getOverviewPanel(); + containerInterface.getCreatedContainer().getOverviewPanel(); if (recentsView != null) { recentsView.switchToScreenshot(onFinished); } else { @@ -295,7 +297,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn if (ENABLE_SHELL_TRANSITIONS) { final ActivityOptions options = ActivityOptions.makeBasic(); // Use regular (non-transient) launch for all apps page to control IME. - if (!activityInterface.allowAllAppsFromOverview()) { + if (!containerInterface.allowAllAppsFromOverview()) { options.setTransientLaunch(); } options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_RECENTS_ANIMATION, eventTime); @@ -332,10 +334,10 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn if (mLastGestureState == null) { return; } - BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface(); - if (activityInterface.isInLiveTileMode() - && activityInterface.getCreatedActivity() != null) { - RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel(); + BaseContainerInterface containerInterface = mLastGestureState.getContainerInterface(); + if (containerInterface.isInLiveTileMode() + && containerInterface.getCreatedContainer() != null) { + RecentsView recentsView = containerInterface.getCreatedContainer().getOverviewPanel(); if (recentsView != null) { recentsView.switchToScreenshot(null, () -> recentsView.finishRecentsAnimation(true /* toRecents */, diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java index 64c4ff45ad..18b8e3e0f5 100644 --- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java @@ -33,7 +33,6 @@ import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import com.android.launcher3.BaseActivity; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Flags; import com.android.launcher3.R; import com.android.launcher3.model.data.ItemInfo; @@ -46,6 +45,7 @@ import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.views.GroupedTaskView; import com.android.quickstep.views.OverviewActionsView; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; import com.android.quickstep.views.TaskThumbnailView; import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView.TaskIdAttributeContainer; @@ -63,14 +63,15 @@ public class TaskOverlayFactory implements ResourceBasedOverride { public static List getEnabledShortcuts(TaskView taskView, TaskIdAttributeContainer taskContainer) { final ArrayList shortcuts = new ArrayList<>(); - final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext()); + final RecentsViewContainer container = + RecentsViewContainer.containerFromContext(taskView.getContext()); boolean hasMultipleTasks = taskView.getTaskIds()[1] != -1; for (TaskShortcutFactory menuOption : MENU_OPTIONS) { if (hasMultipleTasks && !menuOption.showForSplitscreen()) { continue; } - List menuShortcuts = menuOption.getShortcuts(activity, taskContainer); + List menuShortcuts = menuOption.getShortcuts(container, taskContainer); if (menuShortcuts == null) { continue; } @@ -79,7 +80,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride { RecentsOrientedState orientedState = taskView.getRecentsView().getPagedViewOrientedState(); boolean canLauncherRotate = orientedState.isRecentsActivityRotationAllowed(); boolean isInLandscape = orientedState.getTouchRotation() != ROTATION_0; - boolean isTablet = activity.getDeviceProfile().isTablet; + boolean isTablet = container.getDeviceProfile().isTablet; boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview(); // Add overview actions to the menu when: @@ -88,7 +89,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride { if (!hasMultipleTasks && ((!canLauncherRotate && isInLandscape) || isGridOnlyOverview)) { // Add screenshot action to task menu. List screenshotShortcuts = TaskShortcutFactory.SCREENSHOT - .getShortcuts(activity, taskContainer); + .getShortcuts(container, taskContainer); if (screenshotShortcuts != null) { shortcuts.addAll(screenshotShortcuts); } @@ -97,7 +98,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride { // or in grid-only overview. if (orientedState.getDisplayRotation() == ROTATION_0 || isGridOnlyOverview) { List modalShortcuts = TaskShortcutFactory.MODAL - .getShortcuts(activity, taskContainer); + .getShortcuts(container, taskContainer); if (modalShortcuts != null) { shortcuts.addAll(modalShortcuts); } @@ -255,9 +256,9 @@ public class TaskOverlayFactory implements ResourceBasedOverride { /** * Gets the system shortcut for the screenshot that will be added to the task menu. */ - public SystemShortcut getScreenshotShortcut(BaseDraggingActivity activity, + public SystemShortcut getScreenshotShortcut(RecentsViewContainer container, ItemInfo iteminfo, View originalView) { - return new ScreenshotSystemShortcut(activity, iteminfo, originalView); + return new ScreenshotSystemShortcut(container, iteminfo, originalView); } /** @@ -305,13 +306,13 @@ public class TaskOverlayFactory implements ResourceBasedOverride { private class ScreenshotSystemShortcut extends SystemShortcut { - private final BaseDraggingActivity mActivity; + private final RecentsViewContainer mContainer; - ScreenshotSystemShortcut(BaseDraggingActivity activity, ItemInfo itemInfo, + ScreenshotSystemShortcut(RecentsViewContainer container, ItemInfo itemInfo, View originalView) { - super(R.drawable.ic_screenshot, R.string.action_screenshot, activity, itemInfo, + super(R.drawable.ic_screenshot, R.string.action_screenshot, container, itemInfo, originalView); - mActivity = activity; + mContainer = container; } @Override diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java index 5e970f1bd7..9d10ac146c 100644 --- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java +++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java @@ -22,7 +22,6 @@ import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP; import static com.android.window.flags.Flags.enableDesktopWindowingMode; -import android.app.Activity; import android.app.ActivityOptions; import android.graphics.Bitmap; import android.graphics.Color; @@ -39,7 +38,6 @@ import android.window.SplashScreen; import androidx.annotation.Nullable; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; @@ -50,9 +48,11 @@ import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.popup.SystemShortcut.AppInfo; import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption; +import com.android.launcher3.views.ActivityContext; import com.android.quickstep.orientation.RecentsPagedOrientationHandler; import com.android.quickstep.views.GroupedTaskView; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; import com.android.quickstep.views.TaskThumbnailView; import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView.TaskIdAttributeContainer; @@ -74,7 +74,7 @@ import java.util.stream.Collectors; */ public interface TaskShortcutFactory { @Nullable - default List getShortcuts(BaseDraggingActivity activity, + default List getShortcuts(RecentsViewContainer container, TaskIdAttributeContainer taskContainer) { return null; } @@ -94,7 +94,7 @@ public interface TaskShortcutFactory { TaskShortcutFactory APP_INFO = new TaskShortcutFactory() { @Override - public List getShortcuts(BaseDraggingActivity activity, + public List getShortcuts(RecentsViewContainer container, TaskIdAttributeContainer taskContainer) { TaskView taskView = taskContainer.getTaskView(); AppInfo.SplitAccessibilityInfo accessibilityInfo = @@ -102,7 +102,7 @@ public interface TaskShortcutFactory { TaskUtils.getTitle(taskView.getContext(), taskContainer.getTask()), taskContainer.getA11yNodeId() ); - return Collections.singletonList(new AppInfo(activity, taskContainer.getItemInfo(), + return Collections.singletonList(new AppInfo(container, taskContainer.getItemInfo(), taskView, accessibilityInfo)); } @@ -116,9 +116,9 @@ public interface TaskShortcutFactory { private final TaskView mTaskView; private final SplitPositionOption mSplitPositionOption; - public SplitSelectSystemShortcut(BaseDraggingActivity target, TaskView taskView, + public SplitSelectSystemShortcut(RecentsViewContainer container, TaskView taskView, SplitPositionOption option) { - super(option.iconResId, option.textResId, target, taskView.getItemInfo(), taskView); + super(option.iconResId, option.textResId, container, taskView.getItemInfo(), taskView); mTaskView = taskView; mSplitPositionOption = option; } @@ -133,12 +133,13 @@ public interface TaskShortcutFactory { * A menu item, "Save app pair", that allows the user to preserve the current app combination as * one persistent icon on the Home screen, allowing for quick split screen launching. */ - class SaveAppPairSystemShortcut extends SystemShortcut { + class SaveAppPairSystemShortcut extends SystemShortcut { private final GroupedTaskView mTaskView; - public SaveAppPairSystemShortcut(BaseDraggingActivity activity, GroupedTaskView taskView, - int iconResId) { - super(iconResId, R.string.save_app_pair, activity, + + public SaveAppPairSystemShortcut(RecentsViewContainer container, GroupedTaskView taskView, + int iconResId) { + super(iconResId, R.string.save_app_pair, container, taskView.getItemInfo(), taskView); mTaskView = taskView; } @@ -151,7 +152,7 @@ public interface TaskShortcutFactory { } } - class FreeformSystemShortcut extends SystemShortcut { + class FreeformSystemShortcut extends SystemShortcut { private static final String TAG = "FreeformSystemShortcut"; private Handler mHandler; @@ -161,14 +162,14 @@ public interface TaskShortcutFactory { private final TaskView mTaskView; private final LauncherEvent mLauncherEvent; - public FreeformSystemShortcut(int iconRes, int textRes, BaseDraggingActivity activity, + public FreeformSystemShortcut(int iconRes, int textRes, RecentsViewContainer container, TaskIdAttributeContainer taskContainer, LauncherEvent launcherEvent) { - super(iconRes, textRes, activity, taskContainer.getItemInfo(), + super(iconRes, textRes, container, taskContainer.getItemInfo(), taskContainer.getTaskView()); mLauncherEvent = launcherEvent; mHandler = new Handler(Looper.getMainLooper()); mTaskView = taskContainer.getTaskView(); - mRecentsView = activity.getOverviewPanel(); + mRecentsView = container.getOverviewPanel(); mThumbnailView = taskContainer.getThumbnailView(); } @@ -252,11 +253,11 @@ public interface TaskShortcutFactory { } } - private ActivityOptions makeLaunchOptions(Activity activity) { + private ActivityOptions makeLaunchOptions(RecentsViewContainer container) { ActivityOptions activityOptions = ActivityOptions.makeBasic(); activityOptions.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM); // Arbitrary bounds only because freeform is in dev mode right now - final View decorView = activity.getWindow().getDecorView(); + final View decorView = container.getWindow().getDecorView(); final WindowInsets insets = decorView.getRootWindowInsets(); final Rect r = new Rect(0, 0, decorView.getWidth() / 2, decorView.getHeight() / 2); r.offsetTo(insets.getSystemWindowInsetLeft() + 50, @@ -277,9 +278,9 @@ public interface TaskShortcutFactory { */ TaskShortcutFactory SPLIT_SELECT = new TaskShortcutFactory() { @Override - public List getShortcuts(BaseDraggingActivity activity, + public List getShortcuts(RecentsViewContainer container, TaskIdAttributeContainer taskContainer) { - DeviceProfile deviceProfile = activity.getDeviceProfile(); + DeviceProfile deviceProfile = container.getDeviceProfile(); final Task task = taskContainer.getTask(); final int intentFlags = task.key.baseIntent.getFlags(); final TaskView taskView = taskContainer.getTaskView(); @@ -291,7 +292,7 @@ public interface TaskShortcutFactory { !deviceProfile.isTaskbarPresent && recentsView.getTaskViewCount() < 2; boolean isTaskSplitNotSupported = !task.isDockable || (intentFlags & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0; - boolean hideForExistingMultiWindow = activity.getDeviceProfile().isMultiWindowMode; + boolean hideForExistingMultiWindow = container.getDeviceProfile().isMultiWindowMode; boolean isFocusedTask = deviceProfile.isTablet && taskView.isFocusedTask(); boolean isTaskInExpectedScrollPosition = recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView)); @@ -304,7 +305,7 @@ public interface TaskShortcutFactory { return orientationHandler.getSplitPositionOptions(deviceProfile) .stream() .map((Function) option -> - new SplitSelectSystemShortcut(activity, taskView, option)) + new SplitSelectSystemShortcut(container, taskView, option)) .collect(Collectors.toList()); } }; @@ -312,9 +313,9 @@ public interface TaskShortcutFactory { TaskShortcutFactory SAVE_APP_PAIR = new TaskShortcutFactory() { @Nullable @Override - public List getShortcuts(BaseDraggingActivity activity, + public List getShortcuts(RecentsViewContainer container, TaskIdAttributeContainer taskContainer) { - DeviceProfile deviceProfile = activity.getDeviceProfile(); + DeviceProfile deviceProfile = container.getDeviceProfile(); final TaskView taskView = taskContainer.getTaskView(); final RecentsView recentsView = taskView.getRecentsView(); boolean isLargeTileFocusedTask = deviceProfile.isTablet && taskView.isFocusedTask(); @@ -348,7 +349,8 @@ public interface TaskShortcutFactory { : R.drawable.ic_save_app_pair_up_down; return Collections.singletonList( - new SaveAppPairSystemShortcut(activity, (GroupedTaskView) taskView, iconResId)); + new SaveAppPairSystemShortcut(container, + (GroupedTaskView) taskView, iconResId)); } @Override @@ -359,25 +361,25 @@ public interface TaskShortcutFactory { TaskShortcutFactory FREE_FORM = new TaskShortcutFactory() { @Override - public List getShortcuts(BaseDraggingActivity activity, + public List getShortcuts(RecentsViewContainer container, TaskIdAttributeContainer taskContainer) { final Task task = taskContainer.getTask(); if (!task.isDockable) { return null; } - if (!isAvailable(activity, task.key.displayId)) { + if (!isAvailable(container)) { return null; } return Collections.singletonList(new FreeformSystemShortcut( R.drawable.ic_caption_desktop_button_foreground, - R.string.recent_task_option_freeform, activity, taskContainer, + R.string.recent_task_option_freeform, container, taskContainer, LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP)); } - private boolean isAvailable(BaseDraggingActivity activity, int displayId) { + private boolean isAvailable(RecentsViewContainer container) { return Settings.Global.getInt( - activity.getContentResolver(), + container.asContext().getContentResolver(), Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0 && !enableDesktopWindowingMode(); } @@ -385,9 +387,9 @@ public interface TaskShortcutFactory { TaskShortcutFactory PIN = new TaskShortcutFactory() { @Override - public List getShortcuts(BaseDraggingActivity activity, + public List getShortcuts(RecentsViewContainer container, TaskIdAttributeContainer taskContainer) { - if (!SystemUiProxy.INSTANCE.get(activity).isActive()) { + if (!SystemUiProxy.INSTANCE.get(container.asContext()).isActive()) { return null; } if (!ActivityManagerWrapper.getInstance().isScreenPinningEnabled()) { @@ -397,17 +399,17 @@ public interface TaskShortcutFactory { // We shouldn't be able to pin while an app is locked. return null; } - return Collections.singletonList(new PinSystemShortcut(activity, taskContainer)); + return Collections.singletonList(new PinSystemShortcut(container, taskContainer)); } }; - class PinSystemShortcut extends SystemShortcut { + class PinSystemShortcut extends SystemShortcut { private static final String TAG = "PinSystemShortcut"; private final TaskView mTaskView; - public PinSystemShortcut(BaseDraggingActivity target, + public PinSystemShortcut(RecentsViewContainer target, TaskIdAttributeContainer taskContainer) { super(R.drawable.ic_pin, R.string.recent_task_option_pin, target, taskContainer.getItemInfo(), taskContainer.getTaskView()); @@ -417,7 +419,7 @@ public interface TaskShortcutFactory { @Override public void onClick(View view) { if (mTaskView.launchTaskAnimated() != null) { - SystemUiProxy.INSTANCE.get(mTarget).startScreenPinning( + SystemUiProxy.INSTANCE.get(mTarget.asContext()).startScreenPinning( mTaskView.getTask().key.id); } dismissTaskMenuView(); @@ -428,12 +430,12 @@ public interface TaskShortcutFactory { TaskShortcutFactory INSTALL = new TaskShortcutFactory() { @Override - public List getShortcuts(BaseDraggingActivity activity, + public List getShortcuts(RecentsViewContainer container, TaskIdAttributeContainer taskContainer) { Task t = taskContainer.getTask(); - return InstantAppResolver.newInstance(activity).isInstantApp( + return InstantAppResolver.newInstance(container.asContext()).isInstantApp( t.getTopComponent().getPackageName(), t.getKey().userId) - ? Collections.singletonList(new SystemShortcut.Install(activity, + ? Collections.singletonList(new SystemShortcut.Install(container, taskContainer.getItemInfo(), taskContainer.getTaskView())) : null; } @@ -441,10 +443,10 @@ public interface TaskShortcutFactory { TaskShortcutFactory WELLBEING = new TaskShortcutFactory() { @Override - public List getShortcuts(BaseDraggingActivity activity, + public List getShortcuts(RecentsViewContainer container, TaskIdAttributeContainer taskContainer) { - SystemShortcut wellbeingShortcut = - WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, + SystemShortcut wellbeingShortcut = + WellbeingModel.SHORTCUT_FACTORY.getShortcut(container, taskContainer.getItemInfo(), taskContainer.getTaskView()); return createSingletonShortcutList(wellbeingShortcut); } @@ -452,11 +454,11 @@ public interface TaskShortcutFactory { TaskShortcutFactory SCREENSHOT = new TaskShortcutFactory() { @Override - public List getShortcuts(BaseDraggingActivity activity, + public List getShortcuts(RecentsViewContainer container, TaskIdAttributeContainer taskContainer) { SystemShortcut screenshotShortcut = taskContainer.getThumbnailView().getTaskOverlay() - .getScreenshotShortcut(activity, taskContainer.getItemInfo(), + .getScreenshotShortcut(container, taskContainer.getItemInfo(), taskContainer.getTaskView()); return createSingletonShortcutList(screenshotShortcut); } @@ -464,7 +466,7 @@ public interface TaskShortcutFactory { TaskShortcutFactory MODAL = new TaskShortcutFactory() { @Override - public List getShortcuts(BaseDraggingActivity activity, + public List getShortcuts(RecentsViewContainer container, TaskIdAttributeContainer taskContainer) { SystemShortcut modalStateSystemShortcut = taskContainer.getThumbnailView().getTaskOverlay() diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 8f1bf3478f..5564b1873d 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -120,6 +120,7 @@ import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.ActiveGestureLog.CompoundString; import com.android.quickstep.util.AssistStateManager; import com.android.quickstep.util.AssistUtils; +import com.android.quickstep.views.RecentsViewContainer; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.system.ActivityManagerWrapper; @@ -317,7 +318,7 @@ public class TouchInteractionService extends Service { public void enterStageSplitFromRunningApp(boolean leftOrTop) { executeForTouchInteractionService(tis -> { StatefulActivity activity = - tis.mOverviewComponentObserver.getActivityInterface().getCreatedActivity(); + tis.mOverviewComponentObserver.getActivityInterface().getCreatedContainer(); if (activity != null) { activity.enterStageSplitFromRunningApp(leftOrTop); } @@ -594,7 +595,7 @@ public class TouchInteractionService extends Service { mAllAppsActionManager.setHomeAndOverviewSame(isHomeAndOverviewSame); StatefulActivity newOverviewActivity = mOverviewComponentObserver.getActivityInterface() - .getCreatedActivity(); + .getCreatedContainer(); if (newOverviewActivity != null) { mTaskbarManager.setActivity(newOverviewActivity); } @@ -828,8 +829,8 @@ public class TouchInteractionService extends Service { } } - boolean cancelGesture = mGestureState.getActivityInterface() != null - && mGestureState.getActivityInterface().shouldCancelCurrentGesture(); + boolean cancelGesture = mGestureState.getContainerInterface() != null + && mGestureState.getContainerInterface().shouldCancelCurrentGesture(); boolean cleanUpConsumer = (action == ACTION_UP || action == ACTION_CANCEL || cancelGesture) && mConsumer != null && !mConsumer.getActiveConsumerInHierarchy().isConsumerDetachedFromGesture(); @@ -1146,7 +1147,7 @@ public class TouchInteractionService extends Service { TopTaskTracker.CachedTaskInfo runningTask = gestureState.getRunningTask(); // Use overview input consumer for sharesheets on top of home. - boolean forceOverviewInputConsumer = gestureState.getActivityInterface().isStarted() + boolean forceOverviewInputConsumer = gestureState.getContainerInterface().isStarted() && runningTask != null && runningTask.isRootChooseActivity(); @@ -1170,7 +1171,7 @@ public class TouchInteractionService extends Service { // with shell-transitions, home is resumed during recents animation, so // explicitly check against recents animation too. boolean launcherResumedThroughShellTransition = - gestureState.getActivityInterface().isResumed() + gestureState.getContainerInterface().isResumed() && !previousGestureState.isRecentsAnimationRunning(); // If a task fragment within Launcher is resumed boolean launcherChildActivityResumed = useActivityOverlay() @@ -1180,7 +1181,7 @@ public class TouchInteractionService extends Service { && !launcherResumedThroughShellTransition && !previousGestureState.isRecentsAnimationRunning(); - if (gestureState.getActivityInterface().isInLiveTileMode()) { + if (gestureState.getContainerInterface().isInLiveTileMode()) { return createOverviewInputConsumer( previousGestureState, gestureState, @@ -1228,7 +1229,7 @@ public class TouchInteractionService extends Service { final AbsSwipeUpHandler.Factory factory = getSwipeUpHandlerFactory(); final boolean shouldDefer = !mOverviewComponentObserver.isHomeAndOverviewSame() - || gestureState.getActivityInterface().deferStartingActivity(mDeviceState, event); + || gestureState.getContainerInterface().deferStartingActivity(mDeviceState, event); final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event); return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager, gestureState, shouldDefer, this::onConsumerInactive, @@ -1262,18 +1263,19 @@ public class TouchInteractionService extends Service { MotionEvent event, boolean forceOverviewInputConsumer, CompoundString reasonString) { - StatefulActivity activity = gestureState.getActivityInterface().getCreatedActivity(); - if (activity == null) { + RecentsViewContainer container = gestureState.getContainerInterface().getCreatedContainer(); + if (container == null) { return getDefaultInputConsumer( reasonString.append(SUBSTRING_PREFIX) .append("activity == null, trying to use default input consumer")); } - boolean hasWindowFocus = activity.getRootView().hasWindowFocus(); + boolean hasWindowFocus = container.getRootView().hasWindowFocus(); boolean isPreviousGestureAnimatingToLauncher = previousGestureState.isRunningAnimationToLauncher() || mDeviceState.isPredictiveBackToHomeInProgress(); - boolean isInLiveTileMode = gestureState.getActivityInterface().isInLiveTileMode(); + boolean isInLiveTileMode = gestureState.getContainerInterface().isInLiveTileMode(); + reasonString.append(SUBSTRING_PREFIX) .append(hasWindowFocus ? "activity has window focus" @@ -1287,14 +1289,14 @@ public class TouchInteractionService extends Service { || isInLiveTileMode) { reasonString.append(SUBSTRING_PREFIX) .append("overview should have focus, using OverviewInputConsumer"); - return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat, + return new OverviewInputConsumer(gestureState, container, mInputMonitorCompat, false /* startingInActivityBounds */); } else { reasonString.append(SUBSTRING_PREFIX).append( "overview shouldn't have focus, using OverviewWithoutFocusInputConsumer"); final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event); - return new OverviewWithoutFocusInputConsumer(activity, mDeviceState, gestureState, - mInputMonitorCompat, disableHorizontalSwipe); + return new OverviewWithoutFocusInputConsumer(container.asContext(), mDeviceState, + gestureState, mInputMonitorCompat, disableHorizontalSwipe); } } @@ -1367,7 +1369,7 @@ public class TouchInteractionService extends Service { mOverviewComponentObserver.getActivityInterface(); final Intent overviewIntent = new Intent( mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState()); - if (activityInterface.getCreatedActivity() != null && fromInit) { + if (activityInterface.getCreatedContainer() != null && fromInit) { // The activity has been created before the initialization of overview service. It is // usually happens when booting or launcher is the top activity, so we should already // have the latest state. @@ -1389,7 +1391,7 @@ public class TouchInteractionService extends Service { } final BaseActivityInterface activityInterface = mOverviewComponentObserver.getActivityInterface(); - final BaseDraggingActivity activity = activityInterface.getCreatedActivity(); + final BaseDraggingActivity activity = activityInterface.getCreatedContainer(); if (activity == null || activity.isStarted()) { // We only care about the existing background activity. return; @@ -1439,7 +1441,7 @@ public class TouchInteractionService extends Service { DisplayController.INSTANCE.get(this).dump(pw); pw.println("TouchState:"); BaseDraggingActivity createdOverviewActivity = mOverviewComponentObserver == null ? null - : mOverviewComponentObserver.getActivityInterface().getCreatedActivity(); + : mOverviewComponentObserver.getActivityInterface().getCreatedContainer(); boolean resumed = mOverviewComponentObserver != null && mOverviewComponentObserver.getActivityInterface().isResumed(); pw.println(" createdOverviewActivity=" + createdOverviewActivity); diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java index 69de3b0f98..ec531d8028 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java @@ -24,9 +24,9 @@ import com.android.launcher3.Utilities; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.NavigationMode; import com.android.launcher3.util.TouchController; -import com.android.quickstep.RecentsActivity; import com.android.quickstep.util.NavBarPosition; import com.android.quickstep.util.TriggerSwipeUpTouchTracker; +import com.android.quickstep.views.RecentsViewContainer; /** * In 0-button mode, intercepts swipe up from the nav bar on FallbackRecentsView to go home. @@ -34,17 +34,18 @@ import com.android.quickstep.util.TriggerSwipeUpTouchTracker; public class FallbackNavBarTouchController implements TouchController, TriggerSwipeUpTouchTracker.OnSwipeUpListener { - private final RecentsActivity mActivity; + private final RecentsViewContainer mContainer; @Nullable private final TriggerSwipeUpTouchTracker mTriggerSwipeUpTracker; - public FallbackNavBarTouchController(RecentsActivity activity) { - mActivity = activity; - NavigationMode sysUINavigationMode = DisplayController.getNavigationMode(mActivity); + public FallbackNavBarTouchController(RecentsViewContainer container) { + mContainer = container; + NavigationMode sysUINavigationMode = + DisplayController.getNavigationMode(mContainer.asContext()); if (sysUINavigationMode == NavigationMode.NO_BUTTON) { NavBarPosition navBarPosition = new NavBarPosition(sysUINavigationMode, - DisplayController.INSTANCE.get(mActivity).getInfo()); - mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(mActivity, + DisplayController.INSTANCE.get(mContainer.asContext()).getInfo()); + mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(mContainer.asContext(), true /* disableHorizontalSwipe */, navBarPosition, this); } else { mTriggerSwipeUpTracker = null; @@ -75,6 +76,6 @@ public class FallbackNavBarTouchController implements TouchController, @Override public void onSwipeUp(boolean wasFling, PointF finalVelocity) { - mActivity.getOverviewPanel().startHome(); + mContainer.getOverviewPanel().startHome(); } } diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 69eaf6afd8..2e76356b5d 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -49,7 +49,9 @@ import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.util.MultiPropertyFactory; import com.android.quickstep.RecentsActivity; import com.android.quickstep.views.ClearAllButton; +import com.android.quickstep.views.OverviewActionsView; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; /** * State controller for fallback recents activity diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java index 32d8be988c..d881a1f735 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -36,6 +36,7 @@ import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.desktop.DesktopRecentsTransitionController; import com.android.launcher3.logging.StatsLogManager; +import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.statemanager.StateManager.StateListener; import com.android.launcher3.util.SplitConfigurationOptions; import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource; @@ -67,7 +68,7 @@ public class FallbackRecentsView extends RecentsView getStateManager() { + return mContainer.getStateManager(); } /** @@ -210,10 +216,10 @@ public class FallbackRecentsView extends RecentsView { /** * For this state, what color scrim should be drawn behind overview. */ - public int getScrimColor(RecentsActivity activity) { - return hasFlag(FLAG_SCRIM) ? Themes.getAttrColor(activity, R.attr.overviewScrimColor) + public int getScrimColor(Context context) { + return hasFlag(FLAG_SCRIM) + ? Themes.getAttrColor(context, R.attr.overviewScrimColor) : Color.TRANSPARENT; } - public float[] getOverviewScaleAndOffset(RecentsActivity activity) { + public float[] getOverviewScaleAndOffset(RecentsViewContainer container) { return new float[] { NO_SCALE, NO_OFFSET }; } @@ -161,8 +163,8 @@ public class RecentsState implements BaseState { } @Override - public float[] getOverviewScaleAndOffset(RecentsActivity activity) { - return getOverviewScaleAndOffsetForModalState(activity); + public float[] getOverviewScaleAndOffset(RecentsViewContainer container) { + return getOverviewScaleAndOffsetForModalState(container.getOverviewPanel()); } } @@ -172,8 +174,8 @@ public class RecentsState implements BaseState { } @Override - public float[] getOverviewScaleAndOffset(RecentsActivity activity) { - return getOverviewScaleAndOffsetForBackgroundState(activity); + public float[] getOverviewScaleAndOffset(RecentsViewContainer container) { + return getOverviewScaleAndOffsetForBackgroundState(container.getOverviewPanel()); } } @@ -183,7 +185,7 @@ public class RecentsState implements BaseState { } @Override - public float[] getOverviewScaleAndOffset(RecentsActivity activity) { + public float[] getOverviewScaleAndOffset(RecentsViewContainer container) { return new float[] { NO_SCALE, 1 }; } } diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java index db4927a0d1..2cb398cfff 100644 --- a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java +++ b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java @@ -26,7 +26,7 @@ public class RecentsTaskController extends TaskViewTouchController mOnCompleteCallback; @@ -135,7 +132,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mTaskAnimationManager = taskAnimationManager; mGestureState = gestureState; mHandlerFactory = handlerFactory; - mActivityInterface = mGestureState.getActivityInterface(); mMotionPauseDetector = new MotionPauseDetector(base, false, mNavBarPosition.isLeftEdge() || mNavBarPosition.isRightEdge() diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java index 7d3a860b23..bb8d1d7d33 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java @@ -28,24 +28,24 @@ import androidx.annotation.Nullable; import com.android.launcher3.Utilities; import com.android.launcher3.statemanager.BaseState; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.views.BaseDragLayer; -import com.android.quickstep.BaseActivityInterface; +import com.android.quickstep.BaseContainerInterface; import com.android.quickstep.GestureState; import com.android.quickstep.InputConsumer; import com.android.quickstep.TaskUtils; +import com.android.quickstep.views.RecentsViewContainer; import com.android.systemui.shared.system.InputMonitorCompat; /** * Input consumer for handling touch on the recents/Launcher activity. */ -public class OverviewInputConsumer, T extends StatefulActivity> +public class OverviewInputConsumer, T extends RecentsViewContainer> implements InputConsumer { - private final T mActivity; - private final BaseActivityInterface mActivityInterface; + private final T mContainer; + private final BaseContainerInterface mContainerInterface; private final BaseDragLayer mTarget; private final InputMonitorCompat mInputMonitor; @@ -56,14 +56,14 @@ public class OverviewInputConsumer, T extends StatefulAct private boolean mHasSetTouchModeForFirstDPadEvent; private boolean mIsWaitingForAttachToWindow; - public OverviewInputConsumer(GestureState gestureState, T activity, + public OverviewInputConsumer(GestureState gestureState, T container, @Nullable InputMonitorCompat inputMonitor, boolean startingInActivityBounds) { - mActivity = activity; + mContainer = container; mInputMonitor = inputMonitor; mStartingInActivityBounds = startingInActivityBounds; - mActivityInterface = gestureState.getActivityInterface(); + mContainerInterface = gestureState.getContainerInterface(); - mTarget = activity.getDragLayer(); + mTarget = container.getDragLayer(); mTarget.getLocationOnScreen(mLocationOnScreen); } @@ -91,7 +91,7 @@ public class OverviewInputConsumer, T extends StatefulAct if (!mTargetHandledTouch && handled) { mTargetHandledTouch = true; if (!mStartingInActivityBounds) { - mActivityInterface.closeOverlay(); + mContainerInterface.closeOverlay(); TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); } if (mInputMonitor != null) { @@ -100,13 +100,13 @@ public class OverviewInputConsumer, T extends StatefulAct } } if (mHasSetTouchModeForFirstDPadEvent) { - mActivity.getRootView().clearFocus(); + mContainer.getRootView().clearFocus(); } } @Override public void onHoverEvent(MotionEvent ev) { - mActivity.dispatchGenericMotionEvent(ev); + mContainer.dispatchGenericMotionEvent(ev); } @Override @@ -115,7 +115,8 @@ public class OverviewInputConsumer, T extends StatefulAct case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_MUTE: - MediaSessionManager mgr = mActivity.getSystemService(MediaSessionManager.class); + MediaSessionManager mgr = mContainer.asContext() + .getSystemService(MediaSessionManager.class); mgr.dispatchVolumeKeyEventAsSystemService(ev, AudioManager.USE_DEFAULT_STREAM_TYPE); break; @@ -124,7 +125,7 @@ public class OverviewInputConsumer, T extends StatefulAct if (mHasSetTouchModeForFirstDPadEvent) { break; } - View viewRoot = mActivity.getRootView(); + View viewRoot = mContainer.getRootView(); if (viewRoot.isAttachedToWindow()) { setTouchModeChanged(viewRoot); break; @@ -150,7 +151,7 @@ public class OverviewInputConsumer, T extends StatefulAct default: break; } - mActivity.dispatchKeyEvent(ev); + mContainer.dispatchKeyEvent(ev); } private void setTouchModeChanged(@NonNull View viewRoot) { diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java index a8bf333567..d73c23ff51 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java @@ -19,12 +19,12 @@ import android.content.Context; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; import com.android.quickstep.GestureState; import com.android.quickstep.InputConsumer; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.util.MotionPauseDetector; +import com.android.quickstep.views.RecentsViewContainer; /** * An input consumer that detects swipe up and hold to exit screen pinning mode. @@ -44,10 +44,10 @@ public class ScreenPinnedInputConsumer implements InputConsumer { mMotionPauseDetector = new MotionPauseDetector(context, true /* makePauseHarderToTrigger*/); mMotionPauseDetector.setOnMotionPauseListener(() -> { SystemUiProxy.INSTANCE.get(context).stopScreenPinning(); - BaseDraggingActivity launcherActivity = gestureState.getActivityInterface() - .getCreatedActivity(); - if (launcherActivity != null) { - launcherActivity.getRootView().performHapticFeedback( + RecentsViewContainer container = gestureState.getContainerInterface() + .getCreatedContainer(); + if (container != null) { + container.getRootView().performHapticFeedback( HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java index 561e951362..c9647f596e 100644 --- a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java +++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java @@ -39,12 +39,12 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.statemanager.StateManager; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.AllAppsSwipeController; import com.android.quickstep.DeviceConfigWrapper; import com.android.quickstep.orientation.RecentsPagedOrientationHandler; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; /** * Controls an animation that can go beyond progress = 1, at which point resistance should be @@ -158,11 +158,12 @@ public class AnimatorControllerWithResistance { PendingAnimation resistAnim = createRecentsResistanceAnim(params); // Apply All Apps animation during the resistance animation. - if (recentsOrientedState.getActivityInterface().allowAllAppsFromOverview()) { - StatefulActivity activity = - recentsOrientedState.getActivityInterface().getCreatedActivity(); - if (activity != null) { - StateManager stateManager = activity.getStateManager(); + if (recentsOrientedState.getContainerInterface().allowAllAppsFromOverview()) { + RecentsViewContainer container = + recentsOrientedState.getContainerInterface().getCreatedContainer(); + if (container != null) { + RecentsView recentsView = container.getOverviewPanel(); + StateManager stateManager = recentsView.getStateManager(); if (stateManager.isInStableState(LauncherState.BACKGROUND_APP) && stateManager.isInTransition()) { @@ -185,7 +186,7 @@ public class AnimatorControllerWithResistance { private static float getAllAppsThreshold(Context context, RecentsOrientedState recentsOrientedState, DeviceProfile dp) { int transitionDragLength = - recentsOrientedState.getActivityInterface().getSwipeUpDestinationAndLength( + recentsOrientedState.getContainerInterface().getSwipeUpDestinationAndLength( dp, context, TEMP_RECT, recentsOrientedState.getOrientationHandler()); float dragLengthFactor = (float) dp.heightPx / transitionDragLength; @@ -203,7 +204,7 @@ public class AnimatorControllerWithResistance { Rect startRect = new Rect(); RecentsPagedOrientationHandler orientationHandler = params.recentsOrientedState .getOrientationHandler(); - params.recentsOrientedState.getActivityInterface() + params.recentsOrientedState.getContainerInterface() .calculateTaskSize(params.context, params.dp, startRect, orientationHandler); long distanceToCover = startRect.bottom; PendingAnimation resistAnim = params.resistAnim != null @@ -303,14 +304,14 @@ public class AnimatorControllerWithResistance { this.translationProperty = translationProperty; if (dp.isTablet) { resistanceParams = - recentsOrientedState.getActivityInterface().allowAllAppsFromOverview() + recentsOrientedState.getContainerInterface().allowAllAppsFromOverview() ? RecentsResistanceParams.FROM_APP_TO_ALL_APPS_TABLET : enableGridOnlyOverview() ? RecentsResistanceParams.FROM_APP_TABLET_GRID_ONLY : RecentsResistanceParams.FROM_APP_TABLET; } else { resistanceParams = - recentsOrientedState.getActivityInterface().allowAllAppsFromOverview() + recentsOrientedState.getContainerInterface().allowAllAppsFromOverview() ? RecentsResistanceParams.FROM_APP_TO_ALL_APPS : RecentsResistanceParams.FROM_APP; } diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java index 3ed3e40ca7..3f0657123f 100644 --- a/quickstep/src/com/android/quickstep/util/AppPairsController.java +++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java @@ -42,7 +42,6 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.internal.jank.Cuj; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; @@ -56,8 +55,10 @@ import com.android.launcher3.model.data.AppPairInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.taskbar.TaskbarActivityContext; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.SplitConfigurationOptions.StagePosition; +import com.android.launcher3.views.ActivityContext; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TopTaskTracker; import com.android.quickstep.views.GroupedTaskView; @@ -159,7 +160,7 @@ public class AppPairsController { }); MAIN_EXECUTOR.execute(() -> { LauncherAccessibilityDelegate delegate = - Launcher.getLauncher(mContext).getAccessibilityDelegate(); + QuickstepLauncher.getLauncher(mContext).getAccessibilityDelegate(); if (delegate != null) { delegate.addToWorkspace(newAppPair, true, (success) -> { if (success) { @@ -238,7 +239,8 @@ public class AppPairsController { return null; } - AllAppsStore appsStore = Launcher.getLauncher(mContext).getAppsView().getAppsStore(); + AllAppsStore appsStore = ActivityContext.lookupContext(mContext) + .getAppsView().getAppsStore(); // Lookup by ComponentKey AppInfo appInfo = appsStore.getApp(key); diff --git a/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java b/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java index 8209c09304..843619de78 100644 --- a/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java +++ b/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java @@ -17,11 +17,11 @@ package com.android.quickstep.util; import androidx.annotation.UiThread; -import com.android.launcher3.statemanager.StatefulActivity; -import com.android.quickstep.BaseActivityInterface; +import com.android.quickstep.BaseContainerInterface; import com.android.quickstep.GestureState; import com.android.quickstep.InputConsumer; import com.android.quickstep.inputconsumers.OverviewInputConsumer; +import com.android.quickstep.views.RecentsViewContainer; import java.util.function.Supplier; @@ -31,13 +31,13 @@ import java.util.function.Supplier; */ public class InputProxyHandlerFactory implements Supplier { - private final BaseActivityInterface mActivityInterface; + private final BaseContainerInterface mContainerInterface; private final GestureState mGestureState; @UiThread - public InputProxyHandlerFactory(BaseActivityInterface activityInterface, + public InputProxyHandlerFactory(BaseContainerInterface activityInterface, GestureState gestureState) { - mActivityInterface = activityInterface; + mContainerInterface = activityInterface; mGestureState = gestureState; } @@ -46,8 +46,8 @@ public class InputProxyHandlerFactory implements Supplier { */ @Override public InputConsumer get() { - StatefulActivity activity = mActivityInterface.getCreatedActivity(); - return activity == null ? InputConsumer.NO_OP - : new OverviewInputConsumer(mGestureState, activity, null, true); + RecentsViewContainer container = mContainerInterface.getCreatedContainer(); + return container == null ? InputConsumer.NO_OP + : new OverviewInputConsumer(mGestureState, container, null, true); } } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 61ba5ace65..4474f3355c 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -30,9 +30,9 @@ import androidx.core.view.OneShotPreDrawListener; import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.Hotseat; -import com.android.launcher3.Launcher; import com.android.launcher3.Workspace; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.HorizontalInsettableView; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.util.unfold.LauncherJankMonitorTransitionProgressListener; @@ -56,7 +56,7 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private static final FloatProperty HOTSEAT_SCALE_PROPERTY = HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION); - private final Launcher mLauncher; + private final QuickstepLauncher mLauncher; private final ScopedUnfoldTransitionProgressProvider mProgressProvider; private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; @@ -73,7 +73,7 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private HorizontalInsettableView mQsbInsettable; public LauncherUnfoldAnimationController( - Launcher launcher, + QuickstepLauncher launcher, WindowManager windowManager, UnfoldTransitionProgressProvider unfoldTransitionProgressProvider, RotationChangeProvider rotationChangeProvider) { diff --git a/quickstep/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java b/quickstep/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java index 1d008da5b3..0b05c2e7c1 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java +++ b/quickstep/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java @@ -19,39 +19,40 @@ import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_O import android.animation.Animator; import android.animation.ObjectAnimator; +import android.content.Context; import androidx.dynamicanimation.animation.DynamicAnimation; import com.android.launcher3.anim.SpringAnimationBuilder; import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; -public class RecentsAtomicAnimationFactory - extends AtomicAnimationFactory { +public class RecentsAtomicAnimationFactory extends AtomicAnimationFactory { public static final int INDEX_RECENTS_FADE_ANIM = AtomicAnimationFactory.NEXT_INDEX + 0; public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = AtomicAnimationFactory.NEXT_INDEX + 1; private static final int MY_ANIM_COUNT = 2; - protected final ACTIVITY_TYPE mActivity; + protected final CONTAINER mContainer; - public RecentsAtomicAnimationFactory(ACTIVITY_TYPE activity) { + public RecentsAtomicAnimationFactory(CONTAINER container) { super(MY_ANIM_COUNT); - mActivity = activity; + mContainer = container; } @Override public Animator createStateElementAnimation(int index, float... values) { switch (index) { case INDEX_RECENTS_FADE_ANIM: - ObjectAnimator alpha = ObjectAnimator.ofFloat(mActivity.getOverviewPanel(), + ObjectAnimator alpha = ObjectAnimator.ofFloat(mContainer.getOverviewPanel(), RecentsView.CONTENT_ALPHA, values); return alpha; case INDEX_RECENTS_TRANSLATE_X_ANIM: { - RecentsView rv = mActivity.getOverviewPanel(); - return new SpringAnimationBuilder(mActivity) + RecentsView rv = mContainer.getOverviewPanel(); + return new SpringAnimationBuilder(mContainer) .setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE) .setDampingRatio(0.8f) .setStiffness(250) diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java index cba628b817..9335e7e475 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java +++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java @@ -50,7 +50,7 @@ import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.SettingsCache; -import com.android.quickstep.BaseActivityInterface; +import com.android.quickstep.BaseContainerInterface; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TaskAnimationManager; import com.android.quickstep.orientation.RecentsPagedOrientationHandler; @@ -118,7 +118,7 @@ public class RecentsOrientedState implements | FLAG_SWIPE_UP_NOT_RUNNING; private final Context mContext; - private final BaseActivityInterface mActivityInterface; + private final BaseContainerInterface mContainerInterface; private final OrientationEventListener mOrientationListener; private final SettingsCache mSettingsCache; private final SettingsCache.OnChangeListener mRotationChangeListener = @@ -138,10 +138,10 @@ public class RecentsOrientedState implements * is enabled * @see #setRotationWatcherEnabled(boolean) */ - public RecentsOrientedState(Context context, BaseActivityInterface activityInterface, + public RecentsOrientedState(Context context, BaseContainerInterface containerInterface, IntConsumer rotationChangeListener) { mContext = context; - mActivityInterface = activityInterface; + mContainerInterface = containerInterface; mOrientationListener = new OrientationEventListener(context) { @Override public void onOrientationChanged(int degrees) { @@ -153,7 +153,7 @@ public class RecentsOrientedState implements } }; - mFlags = mActivityInterface.rotationSupportedByActivity + mFlags = mContainerInterface.rotationSupportedByActivity ? FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY : 0; mFlags |= FLAG_SWIPE_UP_NOT_RUNNING; @@ -161,8 +161,8 @@ public class RecentsOrientedState implements initFlags(); } - public BaseActivityInterface getActivityInterface() { - return mActivityInterface; + public BaseContainerInterface getContainerInterface() { + return mContainerInterface; } /** diff --git a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt index 33736adc82..48c2407e33 100644 --- a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt +++ b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt @@ -20,7 +20,6 @@ import android.view.View import com.android.app.animation.Interpolators import com.android.app.animation.Interpolators.EMPHASIZED import com.android.app.animation.Interpolators.LINEAR -import com.android.launcher3.Launcher import com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY import com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WORKSPACE_STATE import com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY @@ -39,7 +38,7 @@ import com.android.quickstep.views.RecentsView * Creates an animation where the workspace and hotseat fade in while revealing from the center of * the screen outwards radially. This is used in conjunction with the swipe up to home animation. */ -class ScalingWorkspaceRevealAnim(launcher: Launcher) { +class ScalingWorkspaceRevealAnim(launcher: QuickstepLauncher) { companion object { private const val FADE_DURATION_MS = 200L private const val SCALE_DURATION_MS = 1000L diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt index a2d3859135..9e45380d10 100644 --- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt +++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt @@ -41,7 +41,6 @@ import androidx.annotation.VisibleForTesting import com.android.app.animation.Interpolators import com.android.launcher3.DeviceProfile import com.android.launcher3.Flags.enableOverviewIconMenu -import com.android.launcher3.Launcher import com.android.launcher3.QuickstepTransitionManager import com.android.launcher3.Utilities import com.android.launcher3.anim.PendingAnimation @@ -50,8 +49,8 @@ import com.android.launcher3.config.FeatureFlags import com.android.launcher3.logging.StatsLogManager.EventEnum import com.android.launcher3.statehandlers.DepthController import com.android.launcher3.statemanager.StateManager -import com.android.launcher3.statemanager.StatefulActivity import com.android.launcher3.taskbar.TaskbarActivityContext +import com.android.launcher3.uioverrides.QuickstepLauncher import com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource import com.android.launcher3.views.BaseDragLayer @@ -61,6 +60,7 @@ import com.android.quickstep.views.FloatingTaskView import com.android.quickstep.views.GroupedTaskView import com.android.quickstep.views.IconAppChipView import com.android.quickstep.views.RecentsView +import com.android.quickstep.views.RecentsViewContainer import com.android.quickstep.views.SplitInstructionsView import com.android.quickstep.views.TaskThumbnailView import com.android.quickstep.views.TaskView @@ -269,12 +269,12 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC } /** Does not play any animation if user is not currently in split selection state. */ - fun playPlaceholderDismissAnim(launcher: StatefulActivity<*>, splitDismissEvent: EventEnum) { + fun playPlaceholderDismissAnim(container: RecentsViewContainer, splitDismissEvent: EventEnum) { if (!splitSelectStateController.isSplitSelectActive) { return } - val anim = createPlaceholderDismissAnim(launcher, splitDismissEvent, null /*duration*/) + val anim = createPlaceholderDismissAnim(container, splitDismissEvent, null /*duration*/) anim.start() } @@ -283,18 +283,18 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC * for why split is being dismissed */ fun createPlaceholderDismissAnim( - launcher: StatefulActivity<*>, + container: RecentsViewContainer, splitDismissEvent: EventEnum, duration: Long? ): AnimatorSet { val animatorSet = AnimatorSet() duration?.let { animatorSet.duration = it } - val recentsView: RecentsView<*, *> = launcher.getOverviewPanel() + val recentsView: RecentsView<*, *> = container.getOverviewPanel() val floatingTask: FloatingTaskView = splitSelectStateController.firstFloatingTaskView ?: return animatorSet // We are in split selection state currently, transitioning to another state - val dragLayer: BaseDragLayer<*> = launcher.dragLayer + val dragLayer: BaseDragLayer<*> = container.dragLayer val onScreenRectF = RectF() Utilities.getBoundsForViewInDragLayer( dragLayer, @@ -320,7 +320,7 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC floatingTask, onScreenRectF, floatingTask.stagePosition, - launcher.deviceProfile + container.deviceProfile ) ) ) @@ -329,7 +329,7 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC override fun onAnimationEnd(animation: Animator) { splitSelectStateController.resetState() safeRemoveViewFromDragLayer( - launcher, + container, splitSelectStateController.splitInstructionsView ) } @@ -343,11 +343,11 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC * Returns a [PendingAnimation] to animate in the chip to instruct a user to select a second app * for splitscreen */ - fun getShowSplitInstructionsAnim(launcher: StatefulActivity<*>): PendingAnimation { - safeRemoveViewFromDragLayer(launcher, splitSelectStateController.splitInstructionsView) - val splitInstructionsView = SplitInstructionsView.getSplitInstructionsView(launcher) + fun getShowSplitInstructionsAnim(container: RecentsViewContainer): PendingAnimation { + safeRemoveViewFromDragLayer(container, splitSelectStateController.splitInstructionsView) + val splitInstructionsView = SplitInstructionsView.getSplitInstructionsView(container) splitSelectStateController.splitInstructionsView = splitInstructionsView - val timings = AnimUtils.getDeviceOverviewToSplitTimings(launcher.deviceProfile.isTablet) + val timings = AnimUtils.getDeviceOverviewToSplitTimings(container.deviceProfile.isTablet) val anim = PendingAnimation(100 /*duration */) splitInstructionsView.alpha = 0f anim.setViewAlpha( @@ -374,8 +374,8 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC } /** Removes the split instructions view from [launcher] drag layer. */ - fun removeSplitInstructionsView(launcher: StatefulActivity<*>) { - safeRemoveViewFromDragLayer(launcher, splitSelectStateController.splitInstructionsView) + fun removeSplitInstructionsView(container: RecentsViewContainer) { + safeRemoveViewFromDragLayer(container, splitSelectStateController.splitInstructionsView) } /** @@ -384,22 +384,23 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC * TODO(b/276361926): Remove the [resetCallback] option once contextual launches */ fun playAnimPlaceholderToFullscreen( - launcher: StatefulActivity<*>, + container: RecentsViewContainer, view: View, resetCallback: Optional ) { val stagedTaskView = view as FloatingTaskView - val isTablet: Boolean = launcher.deviceProfile.isTablet + val isTablet: Boolean = container.deviceProfile.isTablet val duration = if (isTablet) SplitAnimationTimings.TABLET_CONFIRM_DURATION else SplitAnimationTimings.PHONE_CONFIRM_DURATION + val pendingAnimation = PendingAnimation(duration.toLong()) val firstTaskStartingBounds = Rect() val firstTaskEndingBounds = Rect() stagedTaskView.getBoundsOnScreen(firstTaskStartingBounds) - launcher.dragLayer.getBoundsOnScreen(firstTaskEndingBounds) + container.dragLayer.getBoundsOnScreen(firstTaskEndingBounds) splitSelectStateController.setLaunchingFirstAppFullscreen() stagedTaskView.addConfirmAnimation( @@ -589,7 +590,7 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC } // Else we are in Launcher and can launch with the full icon stretch-and-split animation. - val launcher = Launcher.getLauncher(launchingIconView.context) + val launcher = QuickstepLauncher.getLauncher(launchingIconView.context) val dp = launcher.deviceProfile // Create an AnimatorSet that will run both shell and launcher transitions together @@ -923,9 +924,9 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC animator.start() } - private fun safeRemoveViewFromDragLayer(launcher: StatefulActivity<*>, view: View?) { + private fun safeRemoveViewFromDragLayer(container: RecentsViewContainer, view: View?) { if (view != null) { - launcher.dragLayer.removeView(view) + container.dragLayer.removeView(view) } } } diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java index bff5a259c7..c9aa30d80f 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java @@ -72,7 +72,6 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.internal.logging.InstanceId; -import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.apppairs.AppPairIcon; @@ -82,9 +81,9 @@ import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.StateManager; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.BackPressHandler; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.SplitConfigurationOptions.StagePosition; @@ -100,6 +99,7 @@ import com.android.quickstep.TaskAnimationManager; import com.android.quickstep.views.FloatingTaskView; import com.android.quickstep.views.GroupedTaskView; import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.RecentsViewContainer; import com.android.quickstep.views.SplitInstructionsView; import com.android.systemui.animation.RemoteAnimationRunnerCompat; import com.android.systemui.shared.recents.model.Task; @@ -121,7 +121,7 @@ import java.util.function.Consumer; public class SplitSelectStateController { private static final String TAG = "SplitSelectStateCtor"; - private StatefulActivity mContext; + private RecentsViewContainer mContainer; private final Handler mHandler; private final RecentsModel mRecentTasksModel; @Nullable @@ -179,7 +179,7 @@ public class SplitSelectStateController { public void onBackInvoked() { // When exiting from split selection, leave current context to go to // homescreen as well - getSplitAnimationController().playPlaceholderDismissAnim(mContext, + getSplitAnimationController().playPlaceholderDismissAnim(mContainer, LAUNCHER_SPLIT_SELECTION_EXIT_HOME); if (mActivityBackCallback != null) { mActivityBackCallback.run(); @@ -187,11 +187,11 @@ public class SplitSelectStateController { } }; - public SplitSelectStateController(StatefulActivity context, Handler handler, + public SplitSelectStateController(RecentsViewContainer container, Handler handler, StateManager stateManager, DepthController depthController, StatsLogManager statsLogManager, SystemUiProxy systemUiProxy, RecentsModel recentsModel, Runnable activityBackCallback) { - mContext = context; + mContainer = container; mHandler = handler; mStatsLogManager = statsLogManager; mSystemUiProxy = systemUiProxy; @@ -200,12 +200,12 @@ public class SplitSelectStateController { mRecentTasksModel = recentsModel; mActivityBackCallback = activityBackCallback; mSplitAnimationController = new SplitAnimationController(this); - mAppPairsController = new AppPairsController(context, this, statsLogManager); - mSplitSelectDataHolder = new SplitSelectDataHolder(mContext); + mAppPairsController = new AppPairsController(mContainer.asContext(), this, statsLogManager); + mSplitSelectDataHolder = new SplitSelectDataHolder(mContainer.asContext()); } public void onDestroy() { - mContext = null; + mContainer = null; mActivityBackCallback = null; mAppPairsController.onDestroy(); mSplitSelectDataHolder.onDestroy(); @@ -646,7 +646,7 @@ public class SplitSelectStateController { } } - public void initSplitFromDesktopController(Launcher launcher) { + public void initSplitFromDesktopController(QuickstepLauncher launcher) { initSplitFromDesktopController(new SplitFromDesktopController(launcher)); } @@ -955,7 +955,7 @@ public class SplitSelectStateController { public class SplitFromDesktopController { private static final String TAG = "SplitFromDesktopController"; - private final Launcher mLauncher; + private final QuickstepLauncher mLauncher; private final OverviewComponentObserver mOverviewComponentObserver; private final int mSplitPlaceholderSize; private final int mSplitPlaceholderInset; @@ -963,7 +963,7 @@ public class SplitSelectStateController { private ISplitSelectListener mSplitSelectListener; private Drawable mAppIcon; - public SplitFromDesktopController(Launcher launcher) { + public SplitFromDesktopController(QuickstepLauncher launcher) { mLauncher = launcher; RecentsAnimationDeviceState deviceState = new RecentsAnimationDeviceState( launcher.getApplicationContext()); diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java index 16d707bb10..2cd421aac3 100644 --- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java +++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java @@ -35,7 +35,6 @@ import android.view.View; import com.android.internal.jank.Cuj; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.anim.PendingAnimation; @@ -46,6 +45,7 @@ import com.android.launcher3.model.data.AppPairInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.PackageItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.quickstep.views.FloatingTaskView; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; @@ -53,13 +53,14 @@ import com.android.systemui.shared.system.InteractionJankMonitorWrapper; /** Handles when the stage split lands on the home screen. */ public class SplitToWorkspaceController { - private final Launcher mLauncher; + private final QuickstepLauncher mLauncher; private final SplitSelectStateController mController; private final int mHalfDividerSize; private final IconCache mIconCache; - public SplitToWorkspaceController(Launcher launcher, SplitSelectStateController controller) { + public SplitToWorkspaceController(QuickstepLauncher launcher, + SplitSelectStateController controller) { mLauncher = launcher; mController = controller; mIconCache = LauncherAppState.getInstanceNoCreate().getIconCache(); diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java index d6d6a119bd..997a842dc2 100644 --- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java +++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java @@ -38,7 +38,6 @@ import androidx.annotation.Nullable; import com.android.launcher3.CellLayout; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Hotseat; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.QuickstepTransitionManager; import com.android.launcher3.R; @@ -75,13 +74,13 @@ public class StaggeredWorkspaceAnim { private final AnimatorSet mAnimators = new AnimatorSet(); private final @Nullable View mIgnoredView; - public StaggeredWorkspaceAnim(Launcher launcher, float velocity, boolean animateOverviewScrim, - @Nullable View ignoredView) { + public StaggeredWorkspaceAnim(QuickstepLauncher launcher, float velocity, + boolean animateOverviewScrim, @Nullable View ignoredView) { this(launcher, velocity, animateOverviewScrim, ignoredView, true); } - public StaggeredWorkspaceAnim(Launcher launcher, float velocity, boolean animateOverviewScrim, - @Nullable View ignoredView, boolean staggerWorkspace) { + public StaggeredWorkspaceAnim(QuickstepLauncher launcher, float velocity, + boolean animateOverviewScrim, @Nullable View ignoredView, boolean staggerWorkspace) { prepareToAnimate(launcher, animateOverviewScrim); mIgnoredView = ignoredView; @@ -124,7 +123,8 @@ public class StaggeredWorkspaceAnim { for (int i = hotseatIcons.getChildCount() - 1; i >= 0; i--) { View child = hotseatIcons.getChildAt(i); CellLayoutLayoutParams lp = ((CellLayoutLayoutParams) child.getLayoutParams()); - addStaggeredAnimationForView(child, lp.getCellY() + 1, totalRows, duration); + addStaggeredAnimationForView(child, lp.getCellY() + 1, + totalRows, duration); } } else { final int hotseatRow, qsbRow; @@ -194,7 +194,8 @@ public class StaggeredWorkspaceAnim { for (int i = itemsContainer.getChildCount() - 1; i >= 0; i--) { View child = itemsContainer.getChildAt(i); CellLayoutLayoutParams lp = ((CellLayoutLayoutParams) child.getLayoutParams()); - addStaggeredAnimationForView(child, lp.getCellY() + lp.cellVSpan, totalRows, duration); + addStaggeredAnimationForView(child, lp.getCellY() + lp.cellVSpan, + totalRows, duration); } mAnimators.addListener(new AnimatorListenerAdapter() { @@ -209,7 +210,7 @@ public class StaggeredWorkspaceAnim { /** * Setup workspace with 0 duration to prepare for our staggered animation. */ - private void prepareToAnimate(Launcher launcher, boolean animateOverviewScrim) { + private void prepareToAnimate(QuickstepLauncher launcher, boolean animateOverviewScrim) { StateAnimationConfig config = new StateAnimationConfig(); config.animFlags = SKIP_OVERVIEW | SKIP_DEPTH_CONTROLLER | SKIP_SCRIM; config.duration = 0; @@ -294,12 +295,10 @@ public class StaggeredWorkspaceAnim { mAnimators.play(alpha); } - private void addDepthAnimationForState(Launcher launcher, LauncherState state, long duration) { - if (!(launcher instanceof QuickstepLauncher)) { - return; - } + private void addDepthAnimationForState(QuickstepLauncher launcher, LauncherState state, + long duration) { PendingAnimation builder = new PendingAnimation(duration); - DepthController depthController = ((QuickstepLauncher) launcher).getDepthController(); + DepthController depthController = launcher.getDepthController(); depthController.setStateWithAnimation(state, new StateAnimationConfig(), builder); mAnimators.play(builder.buildAnim()); } diff --git a/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java b/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java index cdadd711a8..89d8cc48ce 100644 --- a/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java +++ b/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java @@ -24,8 +24,8 @@ import static com.android.launcher3.BaseActivity.EVENT_STOPPED; import androidx.annotation.NonNull; -import com.android.launcher3.BaseActivity; import com.android.quickstep.RecentsModel; +import com.android.quickstep.views.RecentsViewContainer; /** * This class tracks the failure of a task launch through the TaskView.launchTask() call, in an @@ -38,7 +38,7 @@ import com.android.quickstep.RecentsModel; */ public class TaskRemovedDuringLaunchListener { - private BaseActivity mActivity; + private RecentsViewContainer mContainer; private int mLaunchedTaskId = INVALID_TASK_ID; private Runnable mTaskLaunchFailedCallback = null; @@ -49,16 +49,16 @@ public class TaskRemovedDuringLaunchListener { * Registers a failure listener callback if it detects a scenario in which an app launch * failed before the transition finished. */ - public void register(BaseActivity activity, int launchedTaskId, + public void register(RecentsViewContainer container, int launchedTaskId, @NonNull Runnable taskLaunchFailedCallback) { // The normal task launch case, Launcher stops and updates its state correctly - activity.addEventCallback(EVENT_STOPPED, mUnregisterCallback); + container.addEventCallback(EVENT_STOPPED, mUnregisterCallback); // The transition hasn't finished but Launcher was resumed, check if the launch failed - activity.addEventCallback(EVENT_RESUMED, mResumeCallback); + container.addEventCallback(EVENT_RESUMED, mResumeCallback); // If we somehow don't get any of the above signals, then just unregister this listener - activity.addEventCallback(EVENT_DESTROYED, mUnregisterCallback); + container.addEventCallback(EVENT_DESTROYED, mUnregisterCallback); - mActivity = activity; + mContainer = container; mLaunchedTaskId = launchedTaskId; mTaskLaunchFailedCallback = taskLaunchFailedCallback; } @@ -67,11 +67,11 @@ public class TaskRemovedDuringLaunchListener { * Unregisters the failure listener. */ private void unregister() { - mActivity.removeEventCallback(EVENT_STOPPED, mUnregisterCallback); - mActivity.removeEventCallback(EVENT_RESUMED, mResumeCallback); - mActivity.removeEventCallback(EVENT_DESTROYED, mUnregisterCallback); + mContainer.removeEventCallback(EVENT_STOPPED, mUnregisterCallback); + mContainer.removeEventCallback(EVENT_RESUMED, mResumeCallback); + mContainer.removeEventCallback(EVENT_DESTROYED, mUnregisterCallback); - mActivity = null; + mContainer = null; mLaunchedTaskId = INVALID_TASK_ID; mTaskLaunchFailedCallback = null; } diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java index 1152de2750..fcb865f10d 100644 --- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java @@ -51,6 +51,7 @@ import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds; import com.android.launcher3.util.TraceHelper; import com.android.quickstep.BaseActivityInterface; +import com.android.quickstep.BaseContainerInterface; import com.android.quickstep.TaskAnimationManager; import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties; import com.android.quickstep.views.TaskView.FullscreenDrawParams; @@ -70,7 +71,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { private final float[] mTempPoint = new float[2]; private final Context mContext; - private final BaseActivityInterface mSizeStrategy; + private final BaseContainerInterface mSizeStrategy; @NonNull private RecentsOrientedState mOrientationState; @@ -122,7 +123,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { private int mTaskRectTranslationX; private int mTaskRectTranslationY; - public TaskViewSimulator(Context context, BaseActivityInterface sizeStrategy) { + public TaskViewSimulator(Context context, BaseContainerInterface sizeStrategy) { mContext = context; mSizeStrategy = sizeStrategy; diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java index c8141b4642..4aea1b8282 100644 --- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java +++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java @@ -20,7 +20,7 @@ import android.view.ViewGroup; import android.view.WindowManager; import com.android.launcher3.Hotseat; -import com.android.launcher3.Launcher; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.systemui.unfold.updates.RotationChangeProvider; /** @@ -28,10 +28,10 @@ import com.android.systemui.unfold.updates.RotationChangeProvider; */ public class UnfoldMoveFromCenterHotseatAnimator extends BaseUnfoldMoveFromCenterAnimator { - private final Launcher mLauncher; + private final QuickstepLauncher mLauncher; - public UnfoldMoveFromCenterHotseatAnimator(Launcher launcher, WindowManager windowManager, - RotationChangeProvider rotationChangeProvider) { + public UnfoldMoveFromCenterHotseatAnimator(QuickstepLauncher launcher, + WindowManager windowManager, RotationChangeProvider rotationChangeProvider) { super(windowManager, rotationChangeProvider); mLauncher = launcher; } diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java index c05b38f5f2..0ec3ae05d7 100644 --- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java +++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java @@ -19,9 +19,9 @@ import android.view.View; import android.view.WindowManager; import com.android.launcher3.CellLayout; -import com.android.launcher3.Launcher; import com.android.launcher3.ShortcutAndWidgetContainer; import com.android.launcher3.Workspace; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.systemui.unfold.updates.RotationChangeProvider; /** @@ -29,10 +29,10 @@ import com.android.systemui.unfold.updates.RotationChangeProvider; */ public class UnfoldMoveFromCenterWorkspaceAnimator extends BaseUnfoldMoveFromCenterAnimator { - private final Launcher mLauncher; + private final QuickstepLauncher mLauncher; - public UnfoldMoveFromCenterWorkspaceAnimator(Launcher launcher, WindowManager windowManager, - RotationChangeProvider rotationChangeProvider) { + public UnfoldMoveFromCenterWorkspaceAnimator(QuickstepLauncher launcher, + WindowManager windowManager, RotationChangeProvider rotationChangeProvider) { super(windowManager, rotationChangeProvider); mLauncher = launcher; } diff --git a/quickstep/src/com/android/quickstep/util/unfold/LauncherUnfoldTransitionController.kt b/quickstep/src/com/android/quickstep/util/unfold/LauncherUnfoldTransitionController.kt index 54d317d564..09563f5527 100644 --- a/quickstep/src/com/android/quickstep/util/unfold/LauncherUnfoldTransitionController.kt +++ b/quickstep/src/com/android/quickstep/util/unfold/LauncherUnfoldTransitionController.kt @@ -21,15 +21,15 @@ import android.view.Surface import com.android.launcher3.Alarm import com.android.launcher3.DeviceProfile import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener -import com.android.launcher3.Launcher import com.android.launcher3.anim.PendingAnimation import com.android.launcher3.config.FeatureFlags +import com.android.launcher3.uioverrides.QuickstepLauncher import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener /** Controls animations that are happening during unfolding foldable devices */ class LauncherUnfoldTransitionController( - private val launcher: Launcher, + private val launcher: QuickstepLauncher, private val progressProvider: ProxyUnfoldTransitionProvider ) : OnDeviceProfileChangeListener, ActivityLifecycleCallbacksAdapter, TransitionProgressListener { diff --git a/quickstep/src/com/android/quickstep/util/unfold/UnfoldAnimationBuilder.kt b/quickstep/src/com/android/quickstep/util/unfold/UnfoldAnimationBuilder.kt index d2c4728362..2f90ee760e 100644 --- a/quickstep/src/com/android/quickstep/util/unfold/UnfoldAnimationBuilder.kt +++ b/quickstep/src/com/android/quickstep/util/unfold/UnfoldAnimationBuilder.kt @@ -20,7 +20,6 @@ import android.view.ViewGroup import com.android.app.animation.Interpolators.LINEAR import com.android.app.animation.Interpolators.clampToProgress import com.android.launcher3.CellLayout -import com.android.launcher3.Launcher import com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY import com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_UNFOLD_ANIMATION import com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X @@ -28,6 +27,7 @@ import com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y import com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY import com.android.launcher3.Workspace import com.android.launcher3.anim.PendingAnimation +import com.android.launcher3.uioverrides.QuickstepLauncher import com.android.launcher3.util.HorizontalInsettableView private typealias ViewGroupAction = (ViewGroup, Boolean) -> Unit @@ -112,7 +112,7 @@ object UnfoldAnimationBuilder { * Builds an animation for the unfold experience and adds it to the provided PendingAnimation */ fun buildUnfoldAnimation( - launcher: Launcher, + launcher: QuickstepLauncher, isVerticalFold: Boolean, screenSize: Point, anim: PendingAnimation diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java index acda2e153d..b8afd9ddd9 100644 --- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java +++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java @@ -68,7 +68,7 @@ public class ClearAllButton extends Button { } }; - private final StatefulActivity mActivity; + private final RecentsViewContainer mContainer; private float mScrollAlpha = 1; private float mContentAlpha = 1; private float mVisibilityAlpha = 1; @@ -92,7 +92,7 @@ public class ClearAllButton extends Button { public ClearAllButton(Context context, AttributeSet attrs) { super(context, attrs); mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL; - mActivity = StatefulActivity.fromContext(context); + mContainer = RecentsViewContainer.containerFromContext(context); if (Flags.enableFocusOutline()) { TypedArray styledAttrs = context.obtainStyledAttributes(attrs, @@ -326,7 +326,7 @@ public class ClearAllButton extends Button { * Get the Y translation that is set in the original layout position, before scrolling. */ private float getOriginalTranslationY() { - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + DeviceProfile deviceProfile = mContainer.getDeviceProfile(); if (deviceProfile.isTablet) { if (enableGridOnlyOverview()) { return (getRecentsView().getLastComputedTaskSize().height() diff --git a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java index a5be142235..6a9a268334 100644 --- a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java +++ b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java @@ -33,6 +33,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; +import com.android.launcher3.uioverrides.QuickstepLauncher; /** * Floating view show on launcher home screen that notifies the user that an app will be launched to @@ -47,7 +48,7 @@ public class DesktopAppSelectView extends LinearLayout { private static final int SHOW_CONTENT_ALPHA_DURATION = 83; private static final int HIDE_DURATION = 83; - private final Launcher mLauncher; + private final RecentsViewContainer mContainer; private View mText; private View mCloseButton; @@ -71,7 +72,7 @@ public class DesktopAppSelectView extends LinearLayout { public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - mLauncher = Launcher.getLauncher(context); + mContainer = RecentsViewContainer.containerFromContext(context); } /** @@ -104,7 +105,7 @@ public class DesktopAppSelectView extends LinearLayout { } private void show() { - mLauncher.getDragLayer().addView(this); + mContainer.getDragLayer().addView(this); // Set up initial values getBackground().setAlpha(0); @@ -163,7 +164,7 @@ public class DesktopAppSelectView extends LinearLayout { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); - mLauncher.getDragLayer().removeView(DesktopAppSelectView.this); + mContainer.getDragLayer().removeView(DesktopAppSelectView.this); mHideAnimation = null; } }); diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java index 10b4168601..78b17632a3 100644 --- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java +++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java @@ -118,7 +118,7 @@ public class DesktopTaskView extends TaskView { mBackgroundView = findViewById(R.id.background); int topMarginPx = - mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; + mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx; FrameLayout.LayoutParams params = (LayoutParams) mBackgroundView.getLayoutParams(); params.topMargin = topMarginPx; mBackgroundView.setLayoutParams(params); @@ -303,7 +303,7 @@ public class DesktopTaskView extends TaskView { @Override protected void setThumbnailOrientation(RecentsOrientedState orientationState) { - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + DeviceProfile deviceProfile = mContainer.getDeviceProfile(); int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx; LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams(); @@ -420,7 +420,7 @@ public class DesktopTaskView extends TaskView { setMeasuredDimension(containerWidth, containerHeight); - int thumbnailTopMarginPx = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; + int thumbnailTopMarginPx = mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx; containerHeight -= thumbnailTopMarginPx; int thumbnails = mSnapshotViewMap.size(); @@ -428,8 +428,8 @@ public class DesktopTaskView extends TaskView { return; } - int windowWidth = mActivity.getDeviceProfile().widthPx; - int windowHeight = mActivity.getDeviceProfile().heightPx; + int windowWidth = mContainer.getDeviceProfile().widthPx; + int windowHeight = mContainer.getDeviceProfile().heightPx; float scaleWidth = containerWidth / (float) windowWidth; float scaleHeight = containerHeight / (float) windowHeight; diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java index 840382d141..8fa5375739 100644 --- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java +++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java @@ -45,8 +45,6 @@ import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.StringRes; -import com.android.launcher3.BaseActivity; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -83,7 +81,7 @@ public final class DigitalWellBeingToast { private static final String TAG = DigitalWellBeingToast.class.getSimpleName(); - private final BaseDraggingActivity mActivity; + private final RecentsViewContainer mContainer; private final TaskView mTaskView; private final LauncherApps mLauncherApps; @@ -102,10 +100,10 @@ public final class DigitalWellBeingToast { private float mSplitOffsetTranslationY; private float mSplitOffsetTranslationX; - public DigitalWellBeingToast(BaseDraggingActivity activity, TaskView taskView) { - mActivity = activity; + public DigitalWellBeingToast(RecentsViewContainer container, TaskView taskView) { + mContainer = container; mTaskView = taskView; - mLauncherApps = activity.getSystemService(LauncherApps.class); + mLauncherApps = container.asContext().getSystemService(LauncherApps.class); } private void setNoLimit() { @@ -120,9 +118,10 @@ public final class DigitalWellBeingToast { mAppUsageLimitTimeMs = appUsageLimitTimeMs; mAppRemainingTimeMs = appRemainingTimeMs; mHasLimit = true; - TextView toast = mActivity.getViewCache().getView(R.layout.digital_wellbeing_toast, - mActivity, mTaskView); - toast.setText(prefixTextWithIcon(mActivity, R.drawable.ic_hourglass_top, getText())); + TextView toast = mContainer.getViewCache().getView(R.layout.digital_wellbeing_toast, + mContainer.asContext(), mTaskView); + toast.setText(prefixTextWithIcon(mContainer.asContext(), R.drawable.ic_hourglass_top, + getText())); toast.setOnClickListener(this::openAppUsageSettings); replaceBanner(toast); @@ -170,14 +169,14 @@ public final class DigitalWellBeingToast { public void setSplitConfiguration(SplitBounds splitBounds) { mSplitBounds = splitBounds; if (mSplitBounds == null - || !mActivity.getDeviceProfile().isTablet + || !mContainer.getDeviceProfile().isTablet || mTaskView.isFocusedTask()) { mSplitBannerConfig = SPLIT_BANNER_FULLSCREEN; return; } // For portrait grid only height of task changes, not width. So we keep the text the same - if (!mActivity.getDeviceProfile().isLeftRightSplit) { + if (!mContainer.getDeviceProfile().isLeftRightSplit) { mSplitBannerConfig = SPLIT_GRID_BANNER_LARGE; return; } @@ -226,7 +225,7 @@ public final class DigitalWellBeingToast { // Use a specific string for usage less than one minute but non-zero. if (duration.compareTo(Duration.ZERO) > 0) { - return mActivity.getString(durationLessThanOneMinuteStringId); + return mContainer.asContext().getString(durationLessThanOneMinuteStringId); } // Otherwise, return 0-minute string. @@ -250,7 +249,7 @@ public final class DigitalWellBeingToast { R.string.shorter_duration_less_than_one_minute, false /* forceFormatWidth */); if (forContentDesc || mSplitBannerConfig == SPLIT_BANNER_FULLSCREEN) { - return mActivity.getString( + return mContainer.asContext().getString( R.string.time_left_for_app, readableDuration); } @@ -270,11 +269,12 @@ public final class DigitalWellBeingToast { mTask.getTopComponent().getPackageName()).addFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); try { - final BaseActivity activity = BaseActivity.fromContext(view.getContext()); + final RecentsViewContainer container = + RecentsViewContainer.containerFromContext(view.getContext()); final ActivityOptions options = ActivityOptions.makeScaleUpAnimation( view, 0, 0, view.getWidth(), view.getHeight()); - activity.startActivity(intent, options.toBundle()); + container.asContext().startActivity(intent, options.toBundle()); // TODO: add WW logging on the app usage settings click. } catch (ActivityNotFoundException e) { @@ -286,7 +286,7 @@ public final class DigitalWellBeingToast { private String getContentDescriptionForTask( Task task, long appUsageLimitTimeMs, long appRemainingTimeMs) { return appUsageLimitTimeMs >= 0 && appRemainingTimeMs >= 0 ? - mActivity.getString( + mContainer.asContext().getString( R.string.task_contents_description_with_remaining_time, task.titleDescription, getText(appRemainingTimeMs, true /* forContentDesc */)) : @@ -303,7 +303,7 @@ public final class DigitalWellBeingToast { mBanner.setOutlineProvider(mOldBannerOutlineProvider); mTaskView.removeView(mBanner); mBanner.setOnClickListener(null); - mActivity.getViewCache().recycleView(R.layout.digital_wellbeing_toast, mBanner); + mContainer.getViewCache().recycleView(R.layout.digital_wellbeing_toast, mBanner); } } @@ -318,7 +318,7 @@ public final class DigitalWellBeingToast { private void setupAndAddBanner() { FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mBanner.getLayoutParams(); - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + DeviceProfile deviceProfile = mContainer.getDeviceProfile(); layoutParams.bottomMargin = ((ViewGroup.MarginLayoutParams) mTaskView.getThumbnail().getLayoutParams()).bottomMargin; RecentsPagedOrientationHandler orientationHandler = mTaskView.getPagedOrientationHandler(); diff --git a/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt b/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt index 1c1e1674e5..0d49309d1c 100644 --- a/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt +++ b/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt @@ -26,7 +26,6 @@ import android.graphics.drawable.Drawable import android.os.Build import android.view.animation.Interpolator import com.android.app.animation.Interpolators -import com.android.launcher3.Launcher import com.android.launcher3.R import com.android.launcher3.Utilities import com.android.quickstep.util.AnimUtils @@ -55,7 +54,7 @@ class FloatingAppPairBackground( private val ARRAY_OF_ZEROES = FloatArray(8) } - private val launcher: Launcher + private val container: RecentsViewContainer private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG) // Animation interpolators @@ -70,15 +69,15 @@ class FloatingAppPairBackground( private val desiredSplitRatio: Float init { - launcher = Launcher.getLauncher(context) - val dp = launcher.deviceProfile + container = RecentsViewContainer.containerFromContext(context) + val dp = container.deviceProfile // Set up background paint color val ta = context.theme.obtainStyledAttributes(R.styleable.FolderIconPreview) backgroundPaint.style = Paint.Style.FILL backgroundPaint.color = ta.getColor(R.styleable.FolderIconPreview_folderPreviewColor, 0) ta.recycle() // Set up timings and interpolators - val timings = AnimUtils.getDeviceAppPairLaunchTimings(launcher.deviceProfile.isTablet) + val timings = AnimUtils.getDeviceAppPairLaunchTimings(container.deviceProfile.isTablet) expandXInterpolator = Interpolators.clampToProgress( timings.getStagedRectScaleXInterpolator(), @@ -105,9 +104,9 @@ class FloatingAppPairBackground( ) // Find device-specific measurements - deviceCornerRadius = QuickStepContract.getWindowCornerRadius(launcher) + deviceCornerRadius = QuickStepContract.getWindowCornerRadius(container.asContext()) deviceHalfDividerSize = - launcher.resources.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2f + container.asContext().resources.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2f val dividerCenterPos = dividerPos + deviceHalfDividerSize desiredSplitRatio = if (dp.isLeftRightSplit) dividerCenterPos / dp.widthPx @@ -115,7 +114,7 @@ class FloatingAppPairBackground( } override fun draw(canvas: Canvas) { - if (launcher.deviceProfile.isLeftRightSplit) { + if (container.deviceProfile.isLeftRightSplit) { drawLeftRightSplit(canvas) } else { drawTopBottomSplit(canvas) @@ -150,39 +149,37 @@ class FloatingAppPairBackground( val dividerCenterPos = width * desiredSplitRatio // The left half of the background image - val leftSide = RectF( - 0f, - 0f, - dividerCenterPos - changingDividerSize, - height - ) + val leftSide = RectF(0f, 0f, dividerCenterPos - changingDividerSize, height) // The right half of the background image - val rightSide = RectF( - dividerCenterPos + changingDividerSize, - 0f, - width, - height - ) + val rightSide = RectF(dividerCenterPos + changingDividerSize, 0f, width, height) // Draw background drawCustomRoundedRect( canvas, leftSide, floatArrayOf( - cornerRadiusX, cornerRadiusY, - changingInnerRadiusX, changingInnerRadiusY, - changingInnerRadiusX, changingInnerRadiusY, - cornerRadiusX, cornerRadiusY + cornerRadiusX, + cornerRadiusY, + changingInnerRadiusX, + changingInnerRadiusY, + changingInnerRadiusX, + changingInnerRadiusY, + cornerRadiusX, + cornerRadiusY, ) ) drawCustomRoundedRect( canvas, rightSide, floatArrayOf( - changingInnerRadiusX, changingInnerRadiusY, - cornerRadiusX, cornerRadiusY, - cornerRadiusX, cornerRadiusY, - changingInnerRadiusX, changingInnerRadiusY + changingInnerRadiusX, + changingInnerRadiusY, + cornerRadiusX, + cornerRadiusY, + cornerRadiusX, + cornerRadiusY, + changingInnerRadiusX, + changingInnerRadiusY, ) ) @@ -250,39 +247,37 @@ class FloatingAppPairBackground( val dividerCenterPos = height * desiredSplitRatio // The top half of the background image - val topSide = RectF( - 0f, - 0f, - width, - dividerCenterPos - changingDividerSize - ) + val topSide = RectF(0f, 0f, width, dividerCenterPos - changingDividerSize) // The bottom half of the background image - val bottomSide = RectF( - 0f, - dividerCenterPos + changingDividerSize, - width, - height - ) + val bottomSide = RectF(0f, dividerCenterPos + changingDividerSize, width, height) // Draw background drawCustomRoundedRect( canvas, topSide, floatArrayOf( - cornerRadiusX, cornerRadiusY, - cornerRadiusX, cornerRadiusY, - changingInnerRadiusX, changingInnerRadiusY, - changingInnerRadiusX, changingInnerRadiusY + cornerRadiusX, + cornerRadiusY, + cornerRadiusX, + cornerRadiusY, + changingInnerRadiusX, + changingInnerRadiusY, + changingInnerRadiusX, + changingInnerRadiusY ) ) drawCustomRoundedRect( canvas, bottomSide, floatArrayOf( - changingInnerRadiusX, changingInnerRadiusY, - changingInnerRadiusX, changingInnerRadiusY, - cornerRadiusX, cornerRadiusY, - cornerRadiusX, cornerRadiusY + changingInnerRadiusX, + changingInnerRadiusY, + changingInnerRadiusX, + changingInnerRadiusY, + cornerRadiusX, + cornerRadiusY, + cornerRadiusX, + cornerRadiusY ) ) @@ -338,8 +333,10 @@ class FloatingAppPairBackground( // Fallback rectangle with uniform rounded corners val scaleFactorX = floatingView.scaleX val scaleFactorY = floatingView.scaleY - val cornerRadiusX = QuickStepContract.getWindowCornerRadius(launcher) / scaleFactorX - val cornerRadiusY = QuickStepContract.getWindowCornerRadius(launcher) / scaleFactorY + val cornerRadiusX = + QuickStepContract.getWindowCornerRadius(container.asContext()) / scaleFactorX + val cornerRadiusY = + QuickStepContract.getWindowCornerRadius(container.asContext()) / scaleFactorY c.drawRoundRect(rect, cornerRadiusX, cornerRadiusY, backgroundPaint) } } diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java index 18922a6fb3..e479c16200 100644 --- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java +++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java @@ -36,12 +36,10 @@ import android.widget.FrameLayout; import androidx.annotation.Nullable; import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.BaseActivity; import com.android.launcher3.InsettableFrameLayout; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.PendingAnimation; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.taskbar.TaskbarActivityContext; import com.android.launcher3.util.SplitConfigurationOptions; import com.android.launcher3.views.BaseDragLayer; @@ -54,7 +52,7 @@ import com.android.systemui.shared.system.QuickStepContract; /** * Create an instance via - * {@link #getFloatingTaskView(StatefulActivity, View, Bitmap, Drawable, RectF)} to + * {@link #getFloatingTaskView(RecentsViewContainer, View, Bitmap, Drawable, RectF)} to * which will have the thumbnail from the provided existing TaskView overlaying the taskview itself. * * Can then animate the taskview using @@ -67,32 +65,32 @@ public class FloatingTaskView extends FrameLayout { public static final FloatProperty PRIMARY_TRANSLATE_OFFSCREEN = new FloatProperty("floatingTaskPrimaryTranslateOffscreen") { - @Override - public void setValue(FloatingTaskView view, float translation) { - ((RecentsView) view.mActivity.getOverviewPanel()).getPagedOrientationHandler() - .setFloatingTaskPrimaryTranslation( - view, - translation, - view.mActivity.getDeviceProfile() - ); - } + @Override + public void setValue(FloatingTaskView view, float translation) { + ((RecentsView) view.mContainer.getOverviewPanel()).getPagedOrientationHandler() + .setFloatingTaskPrimaryTranslation( + view, + translation, + view.mContainer.getDeviceProfile() + ); + } - @Override - public Float get(FloatingTaskView view) { - return ((RecentsView) view.mActivity.getOverviewPanel()) - .getPagedOrientationHandler() - .getFloatingTaskPrimaryTranslation( - view, - view.mActivity.getDeviceProfile() - ); - } - }; + @Override + public Float get(FloatingTaskView view) { + return ((RecentsView) view.mContainer.getOverviewPanel()) + .getPagedOrientationHandler() + .getFloatingTaskPrimaryTranslation( + view, + view.mContainer.getDeviceProfile() + ); + } + }; private int mSplitHolderSize; private FloatingTaskThumbnailView mThumbnailView; private SplitPlaceholderView mSplitPlaceholderView; private RectF mStartingPosition; - private final StatefulActivity mActivity; + private final RecentsViewContainer mContainer; private final boolean mIsRtl; private final FullscreenDrawParams mFullscreenParams; private RecentsPagedOrientationHandler mOrientationHandler; @@ -110,7 +108,7 @@ public class FloatingTaskView extends FrameLayout { public FloatingTaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - mActivity = BaseActivity.fromContext(context); + mContainer = RecentsViewContainer.containerFromContext(context); mIsRtl = Utilities.isRtl(getResources()); mFullscreenParams = new FullscreenDrawParams(context); @@ -126,7 +124,7 @@ public class FloatingTaskView extends FrameLayout { mSplitPlaceholderView.setAlpha(0); } - private void init(StatefulActivity launcher, View originalView, @Nullable Bitmap thumbnail, + private void init(RecentsViewContainer launcher, View originalView, @Nullable Bitmap thumbnail, Drawable icon, RectF positionOut) { mStartingPosition = positionOut; updateInitialPositionForView(originalView); @@ -153,7 +151,7 @@ public class FloatingTaskView extends FrameLayout { * Configures and returns a an instance of {@link FloatingTaskView} initially matching the * appearance of {@code originalView}. */ - public static FloatingTaskView getFloatingTaskView(StatefulActivity launcher, + public static FloatingTaskView getFloatingTaskView(RecentsViewContainer launcher, View originalView, @Nullable Bitmap thumbnail, Drawable icon, RectF positionOut) { final ViewGroup dragLayer = launcher.getDragLayer(); final FloatingTaskView floatingView = (FloatingTaskView) launcher.getLayoutInflater() @@ -179,13 +177,13 @@ public class FloatingTaskView extends FrameLayout { originalView.getBoundsOnScreen(mTmpRect); mStartingPosition.set(mTmpRect); int[] dragLayerPositionRelativeToScreen = - mActivity.getDragLayer().getLocationOnScreen(); + mContainer.getDragLayer().getLocationOnScreen(); mStartingPosition.offset( -dragLayerPositionRelativeToScreen[0], -dragLayerPositionRelativeToScreen[1]); } else { Rect viewBounds = new Rect(0, 0, originalView.getWidth(), originalView.getHeight()); - Utilities.getBoundsForViewInDragLayer(mActivity.getDragLayer(), originalView, + Utilities.getBoundsForViewInDragLayer(mContainer.getDragLayer(), originalView, viewBounds, false /* ignoreTransform */, null /* recycle */, mStartingPosition); } @@ -235,7 +233,7 @@ public class FloatingTaskView extends FrameLayout { // Position the floating view exactly on top of the original lp.topMargin = Math.round(pos.top); if (mIsRtl) { - lp.setMarginStart(mActivity.getDeviceProfile().widthPx - Math.round(pos.right)); + lp.setMarginStart(mContainer.getDeviceProfile().widthPx - Math.round(pos.right)); } else { lp.setMarginStart(Math.round(pos.left)); } @@ -252,7 +250,7 @@ public class FloatingTaskView extends FrameLayout { */ public void addStagingAnimation(PendingAnimation animation, RectF startingBounds, Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask) { - boolean isTablet = mActivity.getDeviceProfile().isTablet; + boolean isTablet = mContainer.getDeviceProfile().isTablet; boolean splittingFromOverview = fadeWithThumbnail; SplitAnimationTimings timings; @@ -276,7 +274,7 @@ public class FloatingTaskView extends FrameLayout { public void addConfirmAnimation(PendingAnimation animation, RectF startingBounds, Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask) { SplitAnimationTimings timings = - AnimUtils.getDeviceSplitToConfirmTimings(mActivity.getDeviceProfile().isTablet); + AnimUtils.getDeviceSplitToConfirmTimings(mContainer.getDeviceProfile().isTablet); addAnimation(animation, startingBounds, endBounds, fadeWithThumbnail, isStagedTask, timings); @@ -291,7 +289,7 @@ public class FloatingTaskView extends FrameLayout { Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask, SplitAnimationTimings timings) { mFullscreenParams.setIsStagedTask(isStagedTask); - final BaseDragLayer dragLayer = mActivity.getDragLayer(); + final BaseDragLayer dragLayer = mContainer.getDragLayer(); int[] dragLayerBounds = new int[2]; dragLayer.getLocationOnScreen(dragLayerBounds); SplitOverlayProperties prop = new SplitOverlayProperties(endBounds, @@ -391,7 +389,7 @@ public class FloatingTaskView extends FrameLayout { mOrientationHandler.updateSplitIconParams(iconView, onScreenRectCenterX, onScreenRectCenterY, mFullscreenParams.mScaleX, mFullscreenParams.mScaleY, iconView.getDrawableWidth(), iconView.getDrawableHeight(), - mActivity.getDeviceProfile(), mStagePosition); + mContainer.getDeviceProfile(), mStagePosition); } public int getStagePosition() { diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java index 486fc2cf08..4dde635da7 100644 --- a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java +++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java @@ -33,10 +33,10 @@ import android.widget.FrameLayout; import androidx.annotation.Nullable; -import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.dragndrop.DragLayer; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.Themes; import com.android.launcher3.views.FloatingView; import com.android.launcher3.views.ListenerView; @@ -49,7 +49,7 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener, OnGlobalLayoutListener, FloatingView { private static final Matrix sTmpMatrix = new Matrix(); - private final Launcher mLauncher; + private final QuickstepLauncher mLauncher; private final ListenerView mListenerView; private final FloatingWidgetBackgroundView mBackgroundView; private final RectF mBackgroundOffset = new RectF(); @@ -80,7 +80,7 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener, public FloatingWidgetView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - mLauncher = Launcher.getLauncher(context); + mLauncher = QuickstepLauncher.getLauncher(context); mListenerView = new ListenerView(context, attrs); mBackgroundView = new FloatingWidgetBackgroundView(context, attrs, defStyleAttr); addView(mBackgroundView); @@ -283,7 +283,7 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener, * @param windowSize the size of the window when launched * @param windowCornerRadius the corner radius of the window */ - public static FloatingWidgetView getFloatingWidgetView(Launcher launcher, + public static FloatingWidgetView getFloatingWidgetView(QuickstepLauncher launcher, LauncherAppWidgetHostView originalView, RectF widgetBackgroundPosition, Size windowSize, float windowCornerRadius, boolean appTargetsAreTranslucent, int fallbackBackgroundColor) { diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java index 259927d4e7..9e1c856455 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java @@ -41,11 +41,11 @@ import com.android.systemui.shared.recents.utilities.PreviewPositionHelper; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition; +import kotlin.Unit; + import java.util.HashMap; import java.util.function.Consumer; -import kotlin.Unit; - /** * TaskView that contains and shows thumbnails for not one, BUT TWO(!!) tasks * @@ -81,7 +81,7 @@ public class GroupedTaskView extends TaskView { public GroupedTaskView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - mDigitalWellBeingToast2 = new DigitalWellBeingToast(mActivity, this); + mDigitalWellBeingToast2 = new DigitalWellBeingToast(mContainer, this); } @Override @@ -356,7 +356,7 @@ public class GroupedTaskView extends TaskView { if (initSplitTaskId == INVALID_TASK_ID) { getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(mSnapshotView, mSnapshotView2, widthSize, heightSize, mSplitBoundsConfig, - mActivity.getDeviceProfile(), getLayoutDirection() == LAYOUT_DIRECTION_RTL); + mContainer.getDeviceProfile(), getLayoutDirection() == LAYOUT_DIRECTION_RTL); // Should we be having a separate translation step apart from the measuring above? // The following only applies to large screen for now, but for future reference // we'd want to abstract this out in PagedViewHandlers to get the primary/secondary @@ -373,7 +373,7 @@ public class GroupedTaskView extends TaskView { container.getThumbnailView().measure(widthMeasureSpec, View.MeasureSpec.makeMeasureSpec( heightSize - - mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx, + mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx, MeasureSpec.EXACTLY)); } if (!enableOverviewIconMenu()) { @@ -392,7 +392,7 @@ public class GroupedTaskView extends TaskView { @Override public void setOrientationState(RecentsOrientedState orientationState) { - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + DeviceProfile deviceProfile = mContainer.getDeviceProfile(); if (enableOverviewIconMenu() && mSplitBoundsConfig != null) { ViewGroup.LayoutParams layoutParams = getLayoutParams(); Pair groupedTaskViewSizes = @@ -425,7 +425,7 @@ public class GroupedTaskView extends TaskView { return; } - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + DeviceProfile deviceProfile = mContainer.getDeviceProfile(); int taskIconHeight = deviceProfile.overviewTaskIconSizePx; boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL; diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 352ebfe7b0..06c2aa3804 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -72,7 +72,7 @@ public class LauncherRecentsView extends RecentsView getStateManager() { + return mContainer.getStateManager(); } @Override protected void onTaskLaunchAnimationEnd(boolean success) { if (success) { - mActivity.getStateManager().moveToRestState(); + getStateManager().moveToRestState(); } else { - LauncherState state = mActivity.getStateManager().getState(); - mActivity.getAllAppsController().setState(state); + LauncherState state = getStateManager().getState(); + mContainer.getAllAppsController().setState(state); } super.onTaskLaunchAnimationEnd(success); } @@ -115,14 +120,14 @@ public class LauncherRecentsView extends RecentsView : the container that should host recents view + * @param : the type of base state that will be used */ -public abstract class RecentsView, + +public abstract class RecentsView> extends PagedView implements Insettable, TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback, TaskVisualsChangeListener { @@ -444,7 +446,7 @@ public abstract class RecentsView mSizeStrategy; + protected final BaseContainerInterface mSizeStrategy; @Nullable protected RecentsAnimationController mRecentsAnimationController; @Nullable @@ -481,7 +483,7 @@ public abstract class RecentsView { - Animator animatorFade = mActivity.getStateManager().createStateElementAnimation( + Animator animatorFade = getStateManager().createStateElementAnimation( RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM, 1f, 0f); - Animator animatorAppear = mActivity.getStateManager().createStateElementAnimation( + Animator animatorAppear = getStateManager().createStateElementAnimation( RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM, 0f, 1f); animatorFade.addListener(new AnimatorListenerAdapter() { @Override @@ -1089,13 +1091,13 @@ public abstract class RecentsView remoteTargetHandle.getTransformParams() .setSyncTransactionApplier(mSyncTransactionApplier)); RecentsModel.INSTANCE.get(getContext()).addThumbnailChangeListener(this); - mIPipAnimationListener.setActivityAndRecentsView(mActivity, this); + mIPipAnimationListener.setActivityAndRecentsView(mContainer, this); SystemUiProxy.INSTANCE.get(getContext()).setPipAnimationListener( mIPipAnimationListener); mOrientationState.initListeners(); @@ -1110,7 +1112,7 @@ public abstract class RecentsView remoteTargetHandle.getTransformParams() @@ -1250,7 +1252,7 @@ public abstract class RecentsView= 0; --i) { RemoteAnimationTarget app = apps[i]; - float dx = mActivity.getDeviceProfile().widthPx * (1 - percent) / 2 + float dx = mContainer.getDeviceProfile().widthPx * (1 - percent) / 2 + app.screenSpaceBounds.left * percent; - float dy = mActivity.getDeviceProfile().heightPx * (1 - percent) / 2 + float dy = mContainer.getDeviceProfile().heightPx * (1 - percent) / 2 + app.screenSpaceBounds.top * percent; matrix.setScale(percent, percent); matrix.postTranslate(dx, dy); @@ -1295,7 +1297,7 @@ public abstract class RecentsView 0) { @@ -1496,7 +1498,7 @@ public abstract class RecentsView getStateManager(); + public void reset() { setCurrentTask(-1); mCurrentPageScrollDiff = 0; @@ -2619,7 +2623,7 @@ public abstract class RecentsView { setLayoutRotation(newRotation, mOrientationState.getDisplayRotation()); - mActivity.getDragLayer().recreateControllers(); + mContainer.getDragLayer().recreateControllers(); setRecentsChangedOrientation(false).start(); })); pa.start(); @@ -2648,7 +2652,7 @@ public abstract class RecentsView endState = mSizeStrategy.stateFromGestureEndTarget(endTarget); - if (endState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile())) { + if (endState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile())) { TaskView runningTaskView = getRunningTaskView(); float runningTaskPrimaryGridTranslation = 0; float runningTaskSecondaryGridTranslation = 0; @@ -2932,7 +2936,7 @@ public abstract class RecentsView mSplitSelectStateController.getSplitAnimationController(). - playAnimPlaceholderToFullscreen(mActivity, view, + playAnimPlaceholderToFullscreen(mContainer, view, Optional.of(() -> resetFromSplitSelectionState()))); // SplitInstructionsView: animate in safeRemoveDragLayerView(mSplitSelectStateController.getSplitInstructionsView()); SplitInstructionsView splitInstructionsView = - SplitInstructionsView.getSplitInstructionsView(mActivity); + SplitInstructionsView.getSplitInstructionsView(mContainer); splitInstructionsView.setAlpha(0); anim.setViewAlpha(splitInstructionsView, 1, clampToProgress(LINEAR, timings.getInstructionsContainerFadeInStartOffset(), @@ -3447,7 +3451,7 @@ public abstract class RecentsView mActivity.getDisplay().getRotation()); + "RecentsView.updateRecentsRotation", () -> mContainer.getDisplay().getRotation()); mOrientationState.setRecentsRotation(rotation); } @@ -4420,14 +4424,14 @@ public abstract class RecentsView{ @@ -4828,14 +4832,14 @@ public abstract class RecentsView, FloatProperty> taskViewsFloat = orientationHandler.getSplitSelectTaskOffset( TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION, - mActivity.getDeviceProfile()); + mContainer.getDeviceProfile()); taskViewsFloat.first.set(this, getSplitSelectTranslation()); taskViewsFloat.second.set(this, 0f); @@ -5120,10 +5124,10 @@ public abstract class RecentsView UPDATE_SYSUI_FLAGS_THRESHOLD) { - mActivity.getSystemUiController().updateUiState( + mContainer.getSystemUiController().updateUiState( UI_STATE_FULLSCREEN_TASK, targetSysUiFlags); } else { - mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0); + mContainer.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0); } // Passing the threshold from taskview to fullscreen app will vibrate @@ -5185,7 +5189,7 @@ public abstract class RecentsView extends + private static class PinnedStackAnimationListener extends IPipAnimationListener.Stub { @Nullable private T mActivity; @@ -6204,7 +6208,7 @@ public abstract class RecentsView mActivity.setLocusContext(id, Bundle.EMPTY)); + UI_HELPER_EXECUTOR.post(() -> mContainer.setLocusContext(id, Bundle.EMPTY)); } /** diff --git a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java index a3e5a35fbb..a56d51e515 100644 --- a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java +++ b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java @@ -43,6 +43,7 @@ import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.states.StateAnimationConfig; + import com.android.quickstep.util.SplitSelectStateController; /** @@ -57,7 +58,7 @@ public class SplitInstructionsView extends LinearLayout { private static final float BOUNCE_HEIGHT = 20; private static final int DURATION_DEFAULT_SPLIT_DISMISS = 350; - private final StatefulActivity mLauncher; + private final RecentsViewContainer mContainer; public boolean mIsCurrentlyAnimating = false; public static final FloatProperty UNFOLD = @@ -96,13 +97,13 @@ public class SplitInstructionsView extends LinearLayout { public SplitInstructionsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - mLauncher = (StatefulActivity) context; + mContainer = RecentsViewContainer.containerFromContext(context); } - public static SplitInstructionsView getSplitInstructionsView(StatefulActivity launcher) { - ViewGroup dragLayer = launcher.getDragLayer(); + public static SplitInstructionsView getSplitInstructionsView(RecentsViewContainer container) { + ViewGroup dragLayer = container.getDragLayer(); final SplitInstructionsView splitInstructionsView = - (SplitInstructionsView) launcher.getLayoutInflater().inflate( + (SplitInstructionsView) container.getLayoutInflater().inflate( R.layout.split_instructions_view, dragLayer, false @@ -139,12 +140,12 @@ public class SplitInstructionsView extends LinearLayout { } private void exitSplitSelection() { - SplitSelectStateController splitSelectController = - ((RecentsView) mLauncher.getOverviewPanel()).getSplitSelectController(); + RecentsView recentsView = mContainer.getOverviewPanel(); + SplitSelectStateController splitSelectController = recentsView.getSplitSelectController(); - StateManager stateManager = mLauncher.getStateManager(); + StateManager stateManager = recentsView.getStateManager(); BaseState startState = stateManager.getState(); - long duration = startState.getTransitionDuration(mLauncher, false); + long duration = startState.getTransitionDuration(mContainer.asContext(), false); if (duration == 0) { // Case where we're in contextual on workspace (NORMAL), which by default has 0 // transition duration @@ -155,7 +156,7 @@ public class SplitInstructionsView extends LinearLayout { AnimatorSet stateAnim = stateManager.createAtomicAnimation( startState, NORMAL, config); AnimatorSet dismissAnim = splitSelectController.getSplitAnimationController() - .createPlaceholderDismissAnim(mLauncher, + .createPlaceholderDismissAnim(mContainer, LAUNCHER_SPLIT_SELECTION_EXIT_CANCEL_BUTTON, duration); stateAnim.play(dismissAnim); stateManager.setCurrentAnimation(stateAnim, NORMAL); @@ -163,10 +164,10 @@ public class SplitInstructionsView extends LinearLayout { } void ensureProperRotation() { - ((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler() + ((RecentsView) mContainer.getOverviewPanel()).getPagedOrientationHandler() .setSplitInstructionsParams( this, - mLauncher.getDeviceProfile(), + mContainer.getDeviceProfile(), getMeasuredHeight(), getMeasuredWidth() ); diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java index 956dd263a2..fcbb45b9e2 100644 --- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java +++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java @@ -46,7 +46,6 @@ import androidx.annotation.Nullable; import com.android.app.animation.Interpolators; import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.anim.AnimationSuccessListener; @@ -69,7 +68,7 @@ public class TaskMenuView extends AbstractFloatingView { private static final int REVEAL_OPEN_DURATION = enableOverviewIconMenu() ? 417 : 150; private static final int REVEAL_CLOSE_DURATION = enableOverviewIconMenu() ? 333 : 100; - private BaseDraggingActivity mActivity; + private RecentsViewContainer mContainer; private TextView mTaskName; @Nullable private AnimatorSet mOpenCloseAnimator; @@ -89,7 +88,7 @@ public class TaskMenuView extends AbstractFloatingView { public TaskMenuView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - mActivity = BaseDraggingActivity.fromContext(context); + mContainer = RecentsViewContainer.containerFromContext(context); setClipToOutline(true); } @@ -103,7 +102,7 @@ public class TaskMenuView extends AbstractFloatingView { @Override public boolean onControllerInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { - BaseDragLayer dl = mActivity.getDragLayer(); + BaseDragLayer dl = mContainer.getDragLayer(); if (!dl.isEventOverView(this, ev)) { // TODO: log this once we have a new container type for it? close(true); @@ -141,7 +140,7 @@ public class TaskMenuView extends AbstractFloatingView { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (!(enableOverviewIconMenu() - && ((RecentsView) mActivity.getOverviewPanel()).isOnGridBottomRow(mTaskView))) { + && ((RecentsView) mContainer.getOverviewPanel()).isOnGridBottomRow(mTaskView))) { // TODO(b/326952853): Cap menu height for grid bottom row in a way that doesn't break // additionalTranslationY. int maxMenuHeight = calculateMaxHeight(); @@ -166,10 +165,10 @@ public class TaskMenuView extends AbstractFloatingView { public static boolean showForTask(TaskIdAttributeContainer taskContainer, @Nullable Runnable onClosingStartCallback) { - BaseDraggingActivity activity = BaseDraggingActivity.fromContext( + RecentsViewContainer container = RecentsViewContainer.containerFromContext( taskContainer.getTaskView().getContext()); - final TaskMenuView taskMenuView = (TaskMenuView) activity.getLayoutInflater().inflate( - R.layout.task_menu, activity.getDragLayer(), false); + final TaskMenuView taskMenuView = (TaskMenuView) container.getLayoutInflater().inflate( + R.layout.task_menu, container.getDragLayer(), false); taskMenuView.setOnClosingStartCallback(onClosingStartCallback); return taskMenuView.populateAndShowForTask(taskContainer); } @@ -182,7 +181,7 @@ public class TaskMenuView extends AbstractFloatingView { if (isAttachedToWindow()) { return false; } - mActivity.getDragLayer().addView(this); + mContainer.getDragLayer().addView(this); mTaskView = taskContainer.getTaskView(); mTaskContainer = taskContainer; if (!populateAndLayoutMenu()) { @@ -215,7 +214,7 @@ public class TaskMenuView extends AbstractFloatingView { } private void addMenuOption(SystemShortcut menuOption) { - LinearLayout menuOptionView = (LinearLayout) mActivity.getLayoutInflater().inflate( + LinearLayout menuOptionView = (LinearLayout) mContainer.getLayoutInflater().inflate( R.layout.task_view_menu_option, this, false); if (enableOverviewIconMenu()) { ((GradientDrawable) menuOptionView.getBackground()).setCornerRadius(0); @@ -224,7 +223,7 @@ public class TaskMenuView extends AbstractFloatingView { menuOptionView.findViewById(R.id.icon), menuOptionView.findViewById(R.id.text)); LayoutParams lp = (LayoutParams) menuOptionView.getLayoutParams(); mTaskView.getPagedOrientationHandler().setLayoutParamsForTaskMenuOptionItem(lp, - menuOptionView, mActivity.getDeviceProfile()); + menuOptionView, mContainer.getDeviceProfile()); // Set an onClick listener on each menu option. The onClick method is responsible for // ending LiveTile mode on the thumbnail if needed. menuOptionView.setOnClickListener(menuOption::onClick); @@ -232,19 +231,19 @@ public class TaskMenuView extends AbstractFloatingView { } private void orientAroundTaskView(TaskIdAttributeContainer taskContainer) { - RecentsView recentsView = mActivity.getOverviewPanel(); + RecentsView recentsView = mContainer.getOverviewPanel(); RecentsPagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler(); measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); // Get Position - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); - mActivity.getDragLayer().getDescendantRectRelativeToSelf( + DeviceProfile deviceProfile = mContainer.getDeviceProfile(); + mContainer.getDragLayer().getDescendantRectRelativeToSelf( enableOverviewIconMenu() ? getIconView().findViewById(R.id.icon_view_menu_anchor) : taskContainer.getThumbnailView(), sTempRect); - Rect insets = mActivity.getDragLayer().getInsets(); + Rect insets = mContainer.getDragLayer().getInsets(); BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams(); params.width = orientationHandler.getTaskMenuWidth(taskContainer.getThumbnailView(), deviceProfile, taskContainer.getStagePosition()); @@ -325,12 +324,12 @@ public class TaskMenuView extends AbstractFloatingView { IconAppChipView iconAppChip = (IconAppChipView) mTaskContainer.getIconView().asView(); float additionalTranslationY = 0; - if (((RecentsView) mActivity.getOverviewPanel()).isOnGridBottomRow(mTaskView)) { + if (((RecentsView) mContainer.getOverviewPanel()).isOnGridBottomRow(mTaskView)) { // Animate menu up for enough room to display full menu when task on bottom row. float menuBottom = getHeight() + mMenuTranslationYBeforeOpen; float taskBottom = mTaskView.getHeight() + mTaskView.getPersistentTranslationY(); - float taskbarTop = mActivity.getDeviceProfile().heightPx - - mActivity.getDeviceProfile().getOverviewActionsClaimedSpaceBelow(); + float taskbarTop = mContainer.getDeviceProfile().heightPx + - mContainer.getDeviceProfile().getOverviewActionsClaimedSpaceBelow(); float midpoint = (taskBottom + taskbarTop) / 2f; additionalTranslationY = -Math.max(menuBottom - midpoint, 0); } @@ -345,11 +344,11 @@ public class TaskMenuView extends AbstractFloatingView { menuTranslationYAnim.setInterpolator(EMPHASIZED); float additionalTranslationX = 0; - if (mActivity.getDeviceProfile().isLandscape + if (mContainer.getDeviceProfile().isLandscape && mTaskContainer.getStagePosition() == STAGE_POSITION_BOTTOM_OR_RIGHT) { // Animate menu and icon when split task would display off the side of the screen. additionalTranslationX = Math.max( - getTranslationX() + getWidth() - (mActivity.getDeviceProfile().widthPx + getTranslationX() + getWidth() - (mContainer.getDeviceProfile().widthPx - getResources().getDimensionPixelSize( R.dimen.task_menu_edge_padding) * 2), 0); } @@ -410,7 +409,7 @@ public class TaskMenuView extends AbstractFloatingView { private void closeComplete() { testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE, "TaskMenuView.java.closeComplete"); mIsOpen = false; - mActivity.getDragLayer().removeView(this); + mContainer.getDragLayer().removeView(this); mRevealAnimator = null; } @@ -433,7 +432,7 @@ public class TaskMenuView extends AbstractFloatingView { private int calculateMaxHeight() { float taskInsetMargin = getResources().getDimension(R.dimen.task_card_margin); return mTaskView.getPagedOrientationHandler().getTaskMenuHeight(taskInsetMargin, - mActivity.getDeviceProfile(), getTranslationX(), getTranslationY()); + mContainer.getDeviceProfile(), getTranslationX(), getTranslationY()); } private void setOnClosingStartCallback(Runnable onClosingStartCallback) { diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt index dcf681c345..c124f03228 100644 --- a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt +++ b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt @@ -29,7 +29,6 @@ import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import android.widget.LinearLayout -import com.android.launcher3.BaseDraggingActivity import com.android.launcher3.DeviceProfile import com.android.launcher3.InsettableFrameLayout import com.android.launcher3.R @@ -40,24 +39,22 @@ import com.android.launcher3.util.Themes import com.android.quickstep.TaskOverlayFactory import com.android.quickstep.views.TaskView.TaskIdAttributeContainer -class TaskMenuViewWithArrow : ArrowPopup { +class TaskMenuViewWithArrow : ArrowPopup where T : RecentsViewContainer, T : Context { companion object { const val TAG = "TaskMenuViewWithArrow" - fun showForTask( + fun showForTask( taskContainer: TaskIdAttributeContainer, alignedOptionIndex: Int = 0 - ): Boolean { - val activity = - BaseDraggingActivity.fromContext( - taskContainer.taskView.context - ) + ): Boolean where T : RecentsViewContainer, T : Context { + val container: RecentsViewContainer = + RecentsViewContainer.containerFromContext(taskContainer.taskView.context) val taskMenuViewWithArrow = - activity.layoutInflater.inflate( + container.layoutInflater.inflate( R.layout.task_menu_with_arrow, - activity.dragLayer, + container.dragLayer, false - ) as TaskMenuViewWithArrow<*> + ) as TaskMenuViewWithArrow return taskMenuViewWithArrow.populateAndShowForTask(taskContainer, alignedOptionIndex) } diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java index 077247b09a..7e4673939a 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java @@ -48,7 +48,6 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.core.graphics.ColorUtils; -import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Utilities; import com.android.launcher3.util.MainThreadInitializedObject; @@ -122,7 +121,7 @@ public class TaskThumbnailView extends View { } }; - private final BaseActivity mActivity; + private final RecentsViewContainer mContainer; @Nullable private TaskOverlay mOverlay; private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -171,7 +170,7 @@ public class TaskThumbnailView extends View { mBackgroundPaint.setColor(Color.WHITE); mSplashBackgroundPaint.setColor(Color.WHITE); mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); - mActivity = BaseActivity.fromContext(context); + mContainer = RecentsViewContainer.containerFromContext(context); // Initialize with placeholder value. It is overridden later by TaskView mFullscreenParams = TEMP_PARAMS.get(context); @@ -308,7 +307,7 @@ public class TaskThumbnailView extends View { RectF boundsInBitmapSpace = new RectF(); boundsToBitmapSpace.mapRect(boundsInBitmapSpace, viewRect); - DeviceProfile dp = mActivity.getDeviceProfile(); + DeviceProfile dp = mContainer.getDeviceProfile(); int bottomInset = dp.isTablet ? Math.round(bitmapRect.bottom - boundsInBitmapSpace.bottom) : 0; return Insets.of(0, 0, 0, bottomInset); @@ -549,7 +548,7 @@ public class TaskThumbnailView extends View { } private void updateThumbnailMatrix() { - DeviceProfile dp = mActivity.getDeviceProfile(); + DeviceProfile dp = mContainer.getDeviceProfile(); mPreviewPositionHelper.setOrientationChanged(false); if (mBitmapShader != null && mThumbnailData != null) { mPreviewRect.set(0, 0, mThumbnailData.thumbnail.getWidth(), diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 5338d814bf..ec571154a0 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -87,7 +87,6 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.popup.SystemShortcut; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.util.ActivityOptionsWrapper; @@ -119,8 +118,6 @@ import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.QuickStepContract; -import kotlin.Unit; - import java.lang.annotation.Retention; import java.util.Arrays; import java.util.Collections; @@ -129,6 +126,8 @@ import java.util.List; import java.util.function.Consumer; import java.util.stream.Stream; +import kotlin.Unit; + /** * A task in the Recents view. */ @@ -335,7 +334,7 @@ public class TaskView extends FrameLayout implements Reusable { private float mNonGridScale = 1; private float mDismissScale = 1; protected final FullscreenDrawParams mCurrentFullscreenParams; - protected final StatefulActivity mActivity; + protected final RecentsViewContainer mContainer; // Various causes of changing primary translation, which we aggregate to setTranslationX/Y(). private float mDismissTranslationX; @@ -417,11 +416,11 @@ public class TaskView extends FrameLayout implements Reusable { int defStyleRes, BorderAnimator focusBorderAnimator, BorderAnimator hoverBorderAnimator) { super(context, attrs, defStyleAttr, defStyleRes); - mActivity = StatefulActivity.fromContext(context); + mContainer = RecentsViewContainer.containerFromContext(context); setOnClickListener(this::onClick); mCurrentFullscreenParams = new FullscreenDrawParams(context); - mDigitalWellBeingToast = new DigitalWellBeingToast(mActivity, this); + mDigitalWellBeingToast = new DigitalWellBeingToast(mContainer, this); boolean keyboardFocusHighlightEnabled = FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get() || Flags.enableFocusOutline(); @@ -617,7 +616,7 @@ public class TaskView extends FrameLayout implements Reusable { float viewHalfHeight = view.getHeight() / 2f; tempCenterCoords[0] = viewHalfWidth; tempCenterCoords[1] = viewHalfHeight; - getDescendantCoordRelativeToAncestor(view.asView(), mActivity.getDragLayer(), + getDescendantCoordRelativeToAncestor(view.asView(), mContainer.getDragLayer(), tempCenterCoords, false); transformingTouchDelegate.setBounds( (int) (tempCenterCoords[0] - viewHalfWidth), @@ -829,7 +828,7 @@ public class TaskView extends FrameLayout implements Reusable { if (callbackList != null) { callbackList.add(() -> Log.d("b/310064698", mTask + " - onClick - launchCompleted")); } - mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo()) + mContainer.getStatsLogManager().logger().withItemInfo(getItemInfo()) .log(LAUNCHER_TASK_LAUNCH_TAP); } @@ -871,7 +870,7 @@ public class TaskView extends FrameLayout implements Reusable { "TaskView.launchTaskAnimated: startActivityFromRecentsAsync"); TestLogging.recordEvent( TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask); - ActivityOptionsWrapper opts = mActivity.getActivityLaunchOptions(this, null); + ActivityOptionsWrapper opts = mContainer.getActivityLaunchOptions(this, null); opts.options.setLaunchDisplayId( getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId()); if (ActivityManagerWrapper.getInstance() @@ -929,7 +928,7 @@ public class TaskView extends FrameLayout implements Reusable { // We only listen for failures to launch in quickswitch because the during this // gesture launcher is in the background state, vs other launches which are in // the actual overview state - failureListener.register(mActivity, mTask.key.id, () -> { + failureListener.register(mContainer, mTask.key.id, () -> { notifyTaskLaunchFailed(TAG); RecentsView rv = getRecentsView(); if (rv != null) { @@ -1032,7 +1031,7 @@ public class TaskView extends FrameLayout implements Reusable { TaskViewUtils.composeRecentsLaunchAnimator( anim, this, targets.apps, targets.wallpapers, targets.nonApps, true /* launcherClosing */, - mActivity.getStateManager(), recentsView, + recentsView.getStateManager(), recentsView, recentsView.getDepthController()); anim.addListener(new AnimatorListenerAdapter() { @Override @@ -1143,12 +1142,12 @@ public class TaskView extends FrameLayout implements Reusable { return true; } - if (!mActivity.getDeviceProfile().isTablet + if (!mContainer.getDeviceProfile().isTablet && !getRecentsView().isClearAllHidden()) { getRecentsView().snapToPage(getRecentsView().indexOfChild(this)); return false; } else { - mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo()) + mContainer.getStatsLogManager().logger().withItemInfo(getItemInfo()) .log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS); return showTaskMenuWithContainer(iconView); } @@ -1157,7 +1156,7 @@ public class TaskView extends FrameLayout implements Reusable { protected boolean showTaskMenuWithContainer(TaskViewIcon iconView) { TaskIdAttributeContainer menuContainer = mTaskIdAttributeContainer[iconView == mIconView ? 0 : 1]; - DeviceProfile dp = mActivity.getDeviceProfile(); + DeviceProfile dp = mContainer.getDeviceProfile(); if (enableOverviewIconMenu() && iconView instanceof IconAppChipView) { ((IconAppChipView) iconView).revealAnim(/* isRevealing= */ true); return TaskMenuView.showForTask(menuContainer, @@ -1211,7 +1210,7 @@ public class TaskView extends FrameLayout implements Reusable { } protected void setThumbnailOrientation(RecentsOrientedState orientationState) { - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + DeviceProfile deviceProfile = mContainer.getDeviceProfile(); int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx; // TODO(b/271468547), we should default to setting trasnlations only on the snapshot instead @@ -1228,7 +1227,7 @@ public class TaskView extends FrameLayout implements Reusable { * Returns whether the task is part of overview grid and not being focused. */ public boolean isGridTask() { - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + DeviceProfile deviceProfile = mContainer.getDeviceProfile(); return deviceProfile.isTablet && !isFocusedTask(); } @@ -1335,7 +1334,7 @@ public class TaskView extends FrameLayout implements Reusable { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - if (mActivity.getDeviceProfile().isTablet) { + if (mContainer.getDeviceProfile().isTablet) { setPivotX(getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : right - left); setPivotY(mSnapshotView.getTop()); } else { @@ -1692,10 +1691,10 @@ public class TaskView extends FrameLayout implements Reusable { mFullscreenProgress = progress; mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE); mSnapshotView.getTaskOverlay().setFullscreenProgress(progress); - + RecentsView recentsView = mContainer.getOverviewPanel(); // Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are // oversized and banner would look disproportionately large. - if (mActivity.getStateManager().getState() != BACKGROUND_APP) { + if (recentsView.getStateManager().getState() != BACKGROUND_APP) { setIconsAndBannersTransitionProgress(progress, true); } @@ -1729,7 +1728,7 @@ public class TaskView extends FrameLayout implements Reusable { float boxTranslationY; int expectedWidth; int expectedHeight; - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + DeviceProfile deviceProfile = mContainer.getDeviceProfile(); final int thumbnailPadding = deviceProfile.overviewTaskThumbnailTopMarginPx; final Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize(); final int taskWidth = lastComputedTaskSize.width(); diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt index a7ed8a73b2..0de5f197ea 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt @@ -37,6 +37,7 @@ import com.android.launcher3.util.SplitConfigurationOptions import com.android.quickstep.RecentsModel import com.android.quickstep.SystemUiProxy import com.android.quickstep.util.SplitSelectStateController.SplitFromDesktopController +import com.android.quickstep.views.RecentsViewContainer import com.android.systemui.shared.recents.model.Task import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50 import java.util.function.Consumer @@ -63,7 +64,7 @@ class SplitSelectStateControllerTest { private val statsLogger: StatsLogger = mock() private val stateManager: StateManager = mock() private val handler: Handler = mock() - private val context: StatefulActivity<*> = mock() + private val context: RecentsViewContainer = mock() private val recentsModel: RecentsModel = mock() private val pendingIntent: PendingIntent = mock() private val splitFromDesktopController: SplitFromDesktopController = mock() diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index 1c2ed4343d..cf93a79c54 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -111,8 +111,6 @@ public abstract class BaseDraggingActivity extends BaseActivity return false; } - public abstract T getOverviewPanel(); - public abstract View getRootView(); public void returnToHomescreen() { diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java index 688da4934f..0860ae5743 100644 --- a/src/com/android/launcher3/popup/RemoteActionShortcut.java +++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java @@ -33,22 +33,22 @@ import android.widget.TextView; import android.widget.Toast; import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.model.data.ItemInfo; +import com.android.launcher3.views.ActivityContext; import java.lang.ref.WeakReference; -public class RemoteActionShortcut extends SystemShortcut { +public class RemoteActionShortcut extends SystemShortcut { private static final String TAG = "RemoteActionShortcut"; private static final boolean DEBUG = Utilities.IS_DEBUG_DEVICE; private final RemoteAction mAction; public RemoteActionShortcut(RemoteAction action, - BaseDraggingActivity activity, ItemInfo itemInfo, View originalView) { - super(0, R.id.action_remote_action_shortcut, activity, itemInfo, originalView); + T context, ItemInfo itemInfo, View originalView) { + super(0, R.id.action_remote_action_shortcut, context, itemInfo, originalView); mAction = action; } @@ -80,7 +80,7 @@ public class RemoteActionShortcut extends SystemShortcut { mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo) .log(LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP); - final WeakReference weakTarget = new WeakReference<>(mTarget); + final WeakReference weakTarget = new WeakReference<>(mTarget); final String actionIdentity = mAction.getTitle() + ", " + mItemInfo.getTargetComponent().getPackageName(); @@ -95,7 +95,7 @@ public class RemoteActionShortcut extends SystemShortcut { mItemInfo.getTargetComponent().getPackageName()), (pendingIntent, intent, resultCode, resultData, resultExtras) -> { if (DEBUG) Log.d(TAG, "Action is complete: " + actionIdentity); - final BaseDraggingActivity target = weakTarget.get(); + final T target = weakTarget.get(); if (resultData != null && !resultData.isEmpty()) { Log.e(TAG, "Remote action returned result: " + actionIdentity + " : " + resultData); diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java index 910b0293ec..0299a23382 100644 --- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java +++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java @@ -199,11 +199,6 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity return mAppsView; } - @Override - public T getOverviewPanel() { - return null; - } - @Override public View getRootView() { return mDragLayer; diff --git a/src/com/android/quickstep/views/RecentsViewContainer.java b/src/com/android/quickstep/views/RecentsViewContainer.java new file mode 100644 index 0000000000..0c3f4f1ee5 --- /dev/null +++ b/src/com/android/quickstep/views/RecentsViewContainer.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.quickstep.views; + +import android.app.Activity; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.LocusId; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.Window; + +import com.android.launcher3.BaseActivity; +import com.android.launcher3.util.SystemUiController; +import com.android.launcher3.views.ActivityContext; +import com.android.launcher3.views.ScrimView; + +/** + * Interface to be implemented by the parent view of RecentsView + */ +public interface RecentsViewContainer extends ActivityContext { + + /** + * Returns an instance of an implementation of RecentsViewContainer + * @param context will find instance of recentsViewContainer from given context. + */ + static T containerFromContext(Context context) { + if (context instanceof RecentsViewContainer) { + return (T) context; + } else if (context instanceof ContextWrapper) { + return containerFromContext(((ContextWrapper) context).getBaseContext()); + } else { + throw new IllegalArgumentException("Cannot find RecentsViewContainer in parent tree"); + } + } + + /** + * Returns {@link SystemUiController} to manage various window flags to control system UI. + */ + SystemUiController getSystemUiController(); + + /** + * Returns {@link ScrimView} + */ + ScrimView getScrimView(); + + /** + * Returns the Overview Panel as a View + */ + T getOverviewPanel(); + + /** + * Returns the RootView + */ + View getRootView(); + + /** + * Dispatches a generic motion event to the view hierarchy. + * Returns the current RecentsViewContainer as context + */ + default Context asContext() { + return (Context) this; + } + + /** + * @see Window.Callback#dispatchGenericMotionEvent(MotionEvent) + */ + boolean dispatchGenericMotionEvent(MotionEvent ev); + + /** + * @see Window.Callback#dispatchKeyEvent(KeyEvent) + */ + boolean dispatchKeyEvent(KeyEvent ev); + + /** + * Returns overview actions view as a view + */ + View getActionsView(); + + /** + * @see BaseActivity#addForceInvisibleFlag(int) + * @param flag {@link BaseActivity.InvisibilityFlags} + */ + void addForceInvisibleFlag(@BaseActivity.InvisibilityFlags int flag); + + /** + * @see BaseActivity#clearForceInvisibleFlag(int) + * @param flag {@link BaseActivity.InvisibilityFlags} + */ + void clearForceInvisibleFlag(@BaseActivity.InvisibilityFlags int flag); + + /** + * @see android.app.Activity#setLocusContext(LocusId, Bundle) + * @param id {@link LocusId} + * @param bundle {@link Bundle} + */ + void setLocusContext(LocusId id, Bundle bundle); + + /** + * @see BaseActivity#isStarted() + * @return boolean + */ + boolean isStarted(); + + /** + * @see BaseActivity#addEventCallback(int, Runnable) + * @param event {@link BaseActivity.ActivityEvent} + * @param callback runnable to be executed upon event + */ + void addEventCallback(@BaseActivity.ActivityEvent int event, Runnable callback); + + /** + * @see BaseActivity#removeEventCallback(int, Runnable) + * @param event {@link BaseActivity.ActivityEvent} + * @param callback runnable to be executed upon event + */ + void removeEventCallback(@BaseActivity.ActivityEvent int event, Runnable callback); + + /** + * @see com.android.quickstep.util.TISBindHelper#runOnBindToTouchInteractionService(Runnable) + * @param r runnable to be executed upon event + */ + void runOnBindToTouchInteractionService(Runnable r); + + /** + * @see Activity#getWindow() + * @return Window + */ + Window getWindow(); + + /** + * @see + * BaseActivity#addMultiWindowModeChangedListener(BaseActivity.MultiWindowModeChangedListener) + * @param listener {@link BaseActivity.MultiWindowModeChangedListener} + */ + void addMultiWindowModeChangedListener( + BaseActivity.MultiWindowModeChangedListener listener); + + /** + * @see + * BaseActivity#removeMultiWindowModeChangedListener( + * BaseActivity.MultiWindowModeChangedListener) + * @param listener {@link BaseActivity.MultiWindowModeChangedListener} + */ + void removeMultiWindowModeChangedListener( + BaseActivity.MultiWindowModeChangedListener listener); + + /** + * Begins transition from overview back to homescreen + */ + void returnToHomescreen(); +} From f75709e78b99a87fbf7ca5e647da213e9e6b9bd8 Mon Sep 17 00:00:00 2001 From: randypfohl Date: Fri, 22 Mar 2024 09:43:04 -0700 Subject: [PATCH 20/20] fixing tests to match new abstraction This change will let us move from activity to other parent views for recent viewss Change-Id: I2424d94f799f87b2d2262da96b289aac6dfadee9 --- .../quickstep/AbstractQuickStepTest.java | 6 ++--- .../quickstep/DesktopSystemShortcutTest.kt | 3 ++- .../quickstep/TaplOverviewIconTest.java | 3 ++- .../com/android/quickstep/TaskViewTest.java | 3 ++- .../android/launcher3/LauncherIntentTest.java | 2 +- .../allapps/TaplAllAppsIconsWorkingTest.java | 3 ++- .../allapps/TaplKeyboardFocusTest.java | 3 ++- .../allapps/TaplOpenCloseAllAppsTest.java | 3 ++- .../appiconmenu/TaplAppIconMenuTest.java | 2 +- .../celllayout/TaplReorderWidgetsTest.java | 3 ++- .../compat/TaplPromiseIconUiTest.java | 2 +- .../launcher3/dragging/TaplDragTest.java | 3 ++- .../dragging/TaplUninstallRemoveTest.java | 4 +-- .../launcher3/ui/AbstractLauncherUiTest.java | 26 +++++++++---------- .../launcher3/ui/PortraitLandscapeRunner.java | 10 ++++--- .../launcher3/ui/TaplTestsLauncher3Test.java | 3 ++- .../launcher3/ui/TaplWorkProfileTest.java | 3 ++- .../ui/widget/TaplAddConfigWidgetTest.java | 2 +- .../ui/widget/TaplAddWidgetTest.java | 3 ++- .../ui/widget/TaplBindWidgetTest.java | 3 ++- .../ui/widget/TaplRequestPinItemTest.java | 2 +- .../ui/widget/TaplWidgetPickerTest.java | 2 +- .../ui/workspace/TaplThemeIconsTest.java | 3 ++- .../workspace/TaplTwoPanelWorkspaceTest.java | 2 +- .../ui/workspace/TaplWorkspaceTest.java | 2 +- 25 files changed, 58 insertions(+), 43 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java index 6a48b772a4..44c23ba9a2 100644 --- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java +++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java @@ -23,9 +23,9 @@ import android.os.SystemProperties; import androidx.test.uiautomator.By; import androidx.test.uiautomator.Until; -import com.android.launcher3.Launcher; import com.android.launcher3.tapl.LaunchedAppState; import com.android.launcher3.ui.AbstractLauncherUiTest; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.quickstep.views.RecentsView; import org.junit.rules.RuleChain; @@ -34,7 +34,7 @@ import org.junit.rules.TestRule; /** * Base class for all instrumentation tests that deal with Quickstep. */ -public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest { +public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest { public static final boolean ENABLE_SHELL_TRANSITIONS = SystemProperties.getBoolean("persist.wm.debug.shell_transit", true); @Override @@ -46,7 +46,7 @@ public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest { } @Override - protected void onLauncherActivityClose(Launcher launcher) { + protected void onLauncherActivityClose(QuickstepLauncher launcher) { RecentsView recentsView = launcher.getOverviewPanel(); if (recentsView != null) { recentsView.finishRecentsAnimation(false /* toRecents */, null); diff --git a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt index b90839d5a8..7dabbca417 100644 --- a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt +++ b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt @@ -25,6 +25,7 @@ import com.android.launcher3.Launcher import com.android.launcher3.logging.StatsLogManager import com.android.launcher3.logging.StatsLogManager.LauncherEvent import com.android.launcher3.model.data.WorkspaceItemInfo +import com.android.launcher3.uioverrides.QuickstepLauncher import com.android.launcher3.util.SplitConfigurationOptions import com.android.quickstep.views.LauncherRecentsView import com.android.quickstep.views.TaskView @@ -45,7 +46,7 @@ class DesktopSystemShortcutTest { @get:Rule val setFlagsRule = SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT) - private val launcher: Launcher = mock() + private val launcher: QuickstepLauncher = mock() private val statsLogManager: StatsLogManager = mock() private val statsLogger: StatsLogManager.StatsLogger = mock() private val recentsView: LauncherRecentsView = mock() diff --git a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java index 3f3b9eda1f..fa10b61ad4 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java +++ b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java @@ -27,6 +27,7 @@ import android.platform.test.annotations.PlatinumTest; import com.android.launcher3.tapl.OverviewTask.OverviewSplitTask; import com.android.launcher3.tapl.OverviewTaskMenu; import com.android.launcher3.ui.AbstractLauncherUiTest; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.rule.TestStabilityRule; import org.junit.Test; @@ -35,7 +36,7 @@ import org.junit.Test; * This test run in both Out of process (Oop) and in-process (Ipc). * Tests the app Icon in overview. */ -public class TaplOverviewIconTest extends AbstractLauncherUiTest { +public class TaplOverviewIconTest extends AbstractLauncherUiTest { private static final String CALCULATOR_APP_PACKAGE = resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR); diff --git a/quickstep/tests/src/com/android/quickstep/TaskViewTest.java b/quickstep/tests/src/com/android/quickstep/TaskViewTest.java index d744194d42..8eec9034ca 100644 --- a/quickstep/tests/src/com/android/quickstep/TaskViewTest.java +++ b/quickstep/tests/src/com/android/quickstep/TaskViewTest.java @@ -35,6 +35,7 @@ import android.view.MotionEvent; import androidx.test.filters.SmallTest; import com.android.launcher3.statemanager.StatefulActivity; +import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.quickstep.util.BorderAnimator; import com.android.quickstep.views.TaskView; @@ -47,7 +48,7 @@ import org.mockito.MockitoAnnotations; public class TaskViewTest { @Mock - private StatefulActivity mContext; + private QuickstepLauncher mContext; @Mock private Resources mResource; @Mock diff --git a/tests/src/com/android/launcher3/LauncherIntentTest.java b/tests/src/com/android/launcher3/LauncherIntentTest.java index d1110c3c7a..aeeb42a363 100644 --- a/tests/src/com/android/launcher3/LauncherIntentTest.java +++ b/tests/src/com/android/launcher3/LauncherIntentTest.java @@ -34,7 +34,7 @@ import org.junit.runner.RunWith; @LargeTest @RunWith(AndroidJUnit4.class) -public class LauncherIntentTest extends AbstractLauncherUiTest { +public class LauncherIntentTest extends AbstractLauncherUiTest { public final Intent allAppsIntent = new Intent(Intent.ACTION_ALL_APPS); diff --git a/tests/src/com/android/launcher3/allapps/TaplAllAppsIconsWorkingTest.java b/tests/src/com/android/launcher3/allapps/TaplAllAppsIconsWorkingTest.java index 10e9f8abb1..0b233e5492 100644 --- a/tests/src/com/android/launcher3/allapps/TaplAllAppsIconsWorkingTest.java +++ b/tests/src/com/android/launcher3/allapps/TaplAllAppsIconsWorkingTest.java @@ -18,6 +18,7 @@ package com.android.launcher3.allapps; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.tapl.AppIcon; import com.android.launcher3.tapl.HomeAllApps; @@ -30,7 +31,7 @@ import org.junit.Test; * The test runs in Out of process (Oop) and in process. * Makes sure the basic behaviors of Icons on AllApps are working. */ -public class TaplAllAppsIconsWorkingTest extends AbstractLauncherUiTest { +public class TaplAllAppsIconsWorkingTest extends AbstractLauncherUiTest { /** * Makes sure we can launch an icon from All apps diff --git a/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java b/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java index 0360470215..20684eb5ef 100644 --- a/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java +++ b/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java @@ -26,6 +26,7 @@ import android.view.KeyEvent; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.tapl.HomeAllApps; import com.android.launcher3.ui.AbstractLauncherUiTest; @@ -37,7 +38,7 @@ import org.junit.runner.RunWith; @SmallTest @RunWith(AndroidJUnit4.class) -public class TaplKeyboardFocusTest extends AbstractLauncherUiTest { +public class TaplKeyboardFocusTest extends AbstractLauncherUiTest { @Test public void testAllAppsFocusApp() { diff --git a/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java b/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java index e462c4f9b1..f3f6fa5614 100644 --- a/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java +++ b/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java @@ -28,6 +28,7 @@ import android.platform.test.annotations.PlatinumTest; import androidx.test.filters.FlakyTest; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.tapl.AllApps; import com.android.launcher3.ui.AbstractLauncherUiTest; @@ -40,7 +41,7 @@ import org.junit.Test; * Test that we can open and close the all apps in multiple situations. * The test runs in Out of process (Oop) and in process. */ -public class TaplOpenCloseAllAppsTest extends AbstractLauncherUiTest { +public class TaplOpenCloseAllAppsTest extends AbstractLauncherUiTest { public static final String READ_DEVICE_CONFIG_PERMISSION = "android.permission.READ_DEVICE_CONFIG"; diff --git a/tests/src/com/android/launcher3/appiconmenu/TaplAppIconMenuTest.java b/tests/src/com/android/launcher3/appiconmenu/TaplAppIconMenuTest.java index c69d1b9988..55d3252843 100644 --- a/tests/src/com/android/launcher3/appiconmenu/TaplAppIconMenuTest.java +++ b/tests/src/com/android/launcher3/appiconmenu/TaplAppIconMenuTest.java @@ -38,7 +38,7 @@ import org.junit.Test; * Tests the AppIconMenu (the menu that appears when you long press an app icon) and also make sure * we can launch a shortcut from it. */ -public class TaplAppIconMenuTest extends AbstractLauncherUiTest { +public class TaplAppIconMenuTest extends AbstractLauncherUiTest { private boolean isOptionsPopupVisible(Launcher launcher) { final ArrowPopup popup = launcher.getOptionsPopup(); diff --git a/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java b/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java index 1b036453ce..389d027dc1 100644 --- a/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java +++ b/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java @@ -30,6 +30,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.MultipageCellLayout; import com.android.launcher3.celllayout.board.CellLayoutBoard; @@ -59,7 +60,7 @@ import java.util.Map; @SmallTest @RunWith(AndroidJUnit4.class) -public class TaplReorderWidgetsTest extends AbstractLauncherUiTest { +public class TaplReorderWidgetsTest extends AbstractLauncherUiTest { @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind(); diff --git a/tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java b/tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java index 7ed0fa5b8f..1500538633 100644 --- a/tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java +++ b/tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java @@ -52,7 +52,7 @@ import java.util.UUID; */ @LargeTest @RunWith(AndroidJUnit4.class) -public class TaplPromiseIconUiTest extends AbstractLauncherUiTest { +public class TaplPromiseIconUiTest extends AbstractLauncherUiTest { @Rule public final CheckFlagsRule mCheckFlagsRule = diff --git a/tests/src/com/android/launcher3/dragging/TaplDragTest.java b/tests/src/com/android/launcher3/dragging/TaplDragTest.java index bf1ba39fef..d64d096c72 100644 --- a/tests/src/com/android/launcher3/dragging/TaplDragTest.java +++ b/tests/src/com/android/launcher3/dragging/TaplDragTest.java @@ -33,6 +33,7 @@ import android.os.SystemClock; import android.platform.test.annotations.PlatinumTest; import android.util.Log; +import com.android.launcher3.Launcher; import com.android.launcher3.tapl.Folder; import com.android.launcher3.tapl.FolderIcon; import com.android.launcher3.tapl.HomeAllApps; @@ -57,7 +58,7 @@ import org.junit.Test; * * Can drag an icon from AllApps into the workspace * * Can drag an icon on the Workspace to other positions of the Workspace. */ -public class TaplDragTest extends AbstractLauncherUiTest { +public class TaplDragTest extends AbstractLauncherUiTest { /** * Adds two icons to the Workspace and combines them into a folder, then makes sure the icons diff --git a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java index e21309f0e5..df71ec09d4 100644 --- a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java +++ b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java @@ -17,7 +17,6 @@ package com.android.launcher3.dragging; import static com.android.launcher3.testing.shared.TestProtocol.ICON_MISSING; import static com.android.launcher3.testing.shared.TestProtocol.UIOBJECT_STALE_ELEMENT; -import static com.android.launcher3.ui.AbstractLauncherUiTest.initialize; import static com.android.launcher3.util.TestConstants.AppNames.DUMMY_APP_NAME; import static com.android.launcher3.util.TestConstants.AppNames.GMAIL_APP_NAME; import static com.android.launcher3.util.TestConstants.AppNames.MAPS_APP_NAME; @@ -32,6 +31,7 @@ import android.graphics.Point; import android.platform.test.annotations.PlatinumTest; import android.util.Log; +import com.android.launcher3.Launcher; import com.android.launcher3.tapl.HomeAllApps; import com.android.launcher3.tapl.HomeAppIcon; import com.android.launcher3.tapl.Workspace; @@ -51,7 +51,7 @@ import java.util.Map; * Test runs in Out of process (Oop) and In process (Ipc) * Test the behaviour of uninstalling and removing apps both from AllApps, Workspace and Hotseat. */ -public class TaplUninstallRemoveTest extends AbstractLauncherUiTest { +public class TaplUninstallRemoveTest extends AbstractLauncherUiTest { /** * Deletes app both built-in and user-installed from the Workspace and makes sure it's no longer diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index d8635f9071..71090836bb 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -95,7 +95,7 @@ import java.util.function.Supplier; /** * Base class for all instrumentation tests providing various utility methods. */ -public abstract class AbstractLauncherUiTest { +public abstract class AbstractLauncherUiTest { public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10); public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 5; @@ -251,7 +251,7 @@ public abstract class AbstractLauncherUiTest { final ViewCaptureRule viewCaptureRule = new ViewCaptureRule( Launcher.ACTIVITY_TRACKER::getCreatedActivity); final RuleChain inner = RuleChain - .outerRule(new PortraitLandscapeRunner(this)) + .outerRule(new PortraitLandscapeRunner(this)) .around(new FailureWatcher(mLauncher, viewCaptureRule::getViewCaptureData)) // .around(viewCaptureRule) // b/315482167 .around(new TestIsolationRule(mLauncher, true)); @@ -426,12 +426,12 @@ public abstract class AbstractLauncherUiTest { } } - protected T getFromLauncher(Function f) { + protected T getFromLauncher(Function f) { if (!TestHelpers.isInLauncherProcess()) return null; return getOnUiThread(() -> f.apply(Launcher.ACTIVITY_TRACKER.getCreatedActivity())); } - protected void executeOnLauncher(Consumer f) { + protected void executeOnLauncher(Consumer f) { getFromLauncher(launcher -> { f.accept(launcher); return null; @@ -441,7 +441,7 @@ public abstract class AbstractLauncherUiTest { // Execute an action on Launcher, but forgive it when launcher is null. // Launcher can be null if teardown is happening after a failed setup step where launcher // activity failed to be created. - protected void executeOnLauncherInTearDown(Consumer f) { + protected void executeOnLauncherInTearDown(Consumer f) { executeOnLauncher(launcher -> { if (launcher != null) f.accept(launcher); }); @@ -469,20 +469,20 @@ public abstract class AbstractLauncherUiTest { // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide // flakiness. protected void waitForLauncherCondition(String - message, Function condition) { + message, Function condition) { waitForLauncherCondition(message, condition, DEFAULT_ACTIVITY_TIMEOUT); } // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide // flakiness. - protected T getOnceNotNull(String message, Function f) { + protected O getOnceNotNull(String message, Function f) { return getOnceNotNull(message, f, DEFAULT_ACTIVITY_TIMEOUT); } // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide // flakiness. protected void waitForLauncherCondition( - String message, Function condition, long timeout) { + String message, Function condition, long timeout) { verifyKeyguardInvisible(); if (!TestHelpers.isInLauncherProcess()) return; Wait.atMost(message, () -> getFromLauncher(condition), timeout, mLauncher); @@ -490,7 +490,7 @@ public abstract class AbstractLauncherUiTest { // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide // flakiness. - protected T getOnceNotNull(String message, Function f, long timeout) { + protected T getOnceNotNull(String message, Function f, long timeout) { if (!TestHelpers.isInLauncherProcess()) return null; final Object[] output = new Object[1]; @@ -506,7 +506,7 @@ public abstract class AbstractLauncherUiTest { // flakiness. protected void waitForLauncherCondition( String message, - Runnable testThreadAction, Function condition, + Runnable testThreadAction, Function condition, long timeout) { if (!TestHelpers.isInLauncherProcess()) return; Wait.atMost(message, () -> { @@ -648,7 +648,7 @@ public abstract class AbstractLauncherUiTest { "Launcher still active", launcher -> launcher == null, DEFAULT_UI_TIMEOUT); } - protected boolean isInLaunchedApp(Launcher launcher) { + protected boolean isInLaunchedApp(LAUNCHER_TYPE launcher) { return launcher == null || !launcher.hasBeenResumed(); } @@ -658,11 +658,11 @@ public abstract class AbstractLauncherUiTest { launcher -> launcher.getStateManager().getState() == state.get()); } - protected int getAllAppsScroll(Launcher launcher) { + protected int getAllAppsScroll(LAUNCHER_TYPE launcher) { return launcher.getAppsView().getActiveRecyclerView().computeVerticalScrollOffset(); } - protected void onLauncherActivityClose(Launcher launcher) { + protected void onLauncherActivityClose(LAUNCHER_TYPE launcher) { } protected HomeAppIcon createShortcutInCenterIfNotExist(String name) { diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java index fabe3f71e7..c4e74f20fa 100644 --- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java +++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java @@ -3,6 +3,7 @@ package com.android.launcher3.ui; import android.util.Log; import android.view.Surface; +import com.android.launcher3.Launcher; import com.android.launcher3.tapl.TestHelpers; import com.android.launcher3.util.rule.FailureWatcher; @@ -14,11 +15,12 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.Objects; import java.util.concurrent.TimeUnit; -public class PortraitLandscapeRunner implements TestRule { +public class PortraitLandscapeRunner implements TestRule { private static final String TAG = "PortraitLandscapeRunner"; - private AbstractLauncherUiTest mTest; + private AbstractLauncherUiTest mTest; // Annotation for tests that need to be run in portrait and landscape modes. @Retention(RetentionPolicy.RUNTIME) @@ -26,7 +28,7 @@ public class PortraitLandscapeRunner implements TestRule { public @interface PortraitLandscape { } - public PortraitLandscapeRunner(AbstractLauncherUiTest test) { + public PortraitLandscapeRunner(AbstractLauncherUiTest test) { mTest = test; } @@ -47,7 +49,7 @@ public class PortraitLandscapeRunner implements TestRule { mTest.mDevice.pressHome(); mTest.waitForLauncherCondition("Launcher activity wasn't created", - launcher -> launcher != null, + Objects::nonNull, TimeUnit.SECONDS.toMillis(20)); mTest.executeOnLauncher(launcher -> diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java index 6780ed57b7..342eedf2be 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java @@ -22,13 +22,14 @@ import androidx.test.filters.LargeTest; import androidx.test.runner.AndroidJUnit4; import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord; +import com.android.launcher3.Launcher; import org.junit.Test; import org.junit.runner.RunWith; @LargeTest @RunWith(AndroidJUnit4.class) -public class TaplTestsLauncher3Test extends AbstractLauncherUiTest { +public class TaplTestsLauncher3Test extends AbstractLauncherUiTest { @ScreenRecord // b/322823478 @Test diff --git a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java index eb1f49ff11..cccda88bbe 100644 --- a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java +++ b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java @@ -35,6 +35,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.R; import com.android.launcher3.allapps.ActivityAllAppsContainerView; @@ -58,7 +59,7 @@ import java.util.function.Predicate; @LargeTest @RunWith(AndroidJUnit4.class) -public class TaplWorkProfileTest extends AbstractLauncherUiTest { +public class TaplWorkProfileTest extends AbstractLauncherUiTest { private static final int WORK_PAGE = ActivityAllAppsContainerView.AdapterHolder.WORK; diff --git a/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java index 1db60144dc..e6e02b49ac 100644 --- a/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java @@ -52,7 +52,7 @@ import org.junit.runner.RunWith; */ @LargeTest @RunWith(AndroidJUnit4.class) -public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest { +public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest { @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind(); diff --git a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java index 6c243294c3..7845dec4a3 100644 --- a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java @@ -25,6 +25,7 @@ import android.platform.test.annotations.PlatinumTest; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; +import com.android.launcher3.Launcher; import com.android.launcher3.celllayout.FavoriteItemsTransaction; import com.android.launcher3.tapl.Widget; import com.android.launcher3.tapl.WidgetResizeFrame; @@ -46,7 +47,7 @@ import org.junit.runner.RunWith; */ @LargeTest @RunWith(AndroidJUnit4.class) -public class TaplAddWidgetTest extends AbstractLauncherUiTest { +public class TaplAddWidgetTest extends AbstractLauncherUiTest { @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind(); diff --git a/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java index e69cb4ce62..28d1faa5e7 100644 --- a/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java @@ -43,6 +43,7 @@ import android.widget.RemoteViews; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherSettings; @@ -76,7 +77,7 @@ import java.util.function.Consumer; */ @LargeTest @RunWith(AndroidJUnit4.class) -public class TaplBindWidgetTest extends AbstractLauncherUiTest { +public class TaplBindWidgetTest extends AbstractLauncherUiTest { @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind(); diff --git a/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java index 90a6d22f38..74047f0d01 100644 --- a/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java +++ b/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java @@ -59,7 +59,7 @@ import java.util.UUID; */ @LargeTest @RunWith(AndroidJUnit4.class) -public class TaplRequestPinItemTest extends AbstractLauncherUiTest { +public class TaplRequestPinItemTest extends AbstractLauncherUiTest { @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind(); diff --git a/tests/src/com/android/launcher3/ui/widget/TaplWidgetPickerTest.java b/tests/src/com/android/launcher3/ui/widget/TaplWidgetPickerTest.java index 4acdddc7e2..79724e1189 100644 --- a/tests/src/com/android/launcher3/ui/widget/TaplWidgetPickerTest.java +++ b/tests/src/com/android/launcher3/ui/widget/TaplWidgetPickerTest.java @@ -43,7 +43,7 @@ import org.junit.runner.RunWith; */ @MediumTest @RunWith(AndroidJUnit4.class) -public class TaplWidgetPickerTest extends AbstractLauncherUiTest { +public class TaplWidgetPickerTest extends AbstractLauncherUiTest { // b/325377690 : To get the log printed where DOWN key event is getting lost from TAPL. @Rule public final TestRule mEnableInputTransportPublisherRule = createEnableInputTransportPublisherRule(); diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplThemeIconsTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplThemeIconsTest.java index c60ee8c5ed..d6533171d3 100644 --- a/tests/src/com/android/launcher3/ui/workspace/TaplThemeIconsTest.java +++ b/tests/src/com/android/launcher3/ui/workspace/TaplThemeIconsTest.java @@ -31,6 +31,7 @@ import android.view.ViewGroup; import androidx.test.filters.LargeTest; import com.android.launcher3.BubbleTextView; +import com.android.launcher3.Launcher; import com.android.launcher3.icons.ThemedIconDrawable; import com.android.launcher3.tapl.HomeAllApps; import com.android.launcher3.tapl.HomeAppIcon; @@ -49,7 +50,7 @@ import java.util.Queue; * Note running these tests will clear the workspace on the device. */ @LargeTest -public class TaplThemeIconsTest extends AbstractLauncherUiTest { +public class TaplThemeIconsTest extends AbstractLauncherUiTest { private static final String APP_NAME = "IconThemedActivity"; private static final String SHORTCUT_NAME = "Shortcut 1"; diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java index 913dfa2285..2ce8eef2d8 100644 --- a/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java +++ b/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java @@ -55,7 +55,7 @@ import java.util.stream.Collectors; */ @LargeTest @RunWith(AndroidJUnit4.class) -public class TaplTwoPanelWorkspaceTest extends AbstractLauncherUiTest { +public class TaplTwoPanelWorkspaceTest extends AbstractLauncherUiTest { private AutoCloseable mLauncherLayout; diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java index 4edeb42fc1..9afde0db28 100644 --- a/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java +++ b/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java @@ -37,7 +37,7 @@ import org.junit.Test; /** * Test the basic interactions of the Workspace, adding pages, moving the pages and removing pages. */ -public class TaplWorkspaceTest extends AbstractLauncherUiTest { +public class TaplWorkspaceTest extends AbstractLauncherUiTest { private AutoCloseable mLauncherLayout;