Snap for 11697857 from c21b463a33 to 24Q3-release

Change-Id: I40cf37228c43e3110350ecd50e75848a9645b5cf
This commit is contained in:
Android Build Coastguard Worker
2024-04-10 23:21:01 +00:00
160 changed files with 2642 additions and 1584 deletions
+1
View File
@@ -38,6 +38,7 @@
<string name="nav_handle_long_press_handler_class" translatable="false"></string>
<string name="assist_utils_class" translatable="false"></string>
<string name="assist_state_manager_class" translatable="false"></string>
<string name="api_wrapper_class" translatable="false">com.android.launcher3.uioverrides.SystemApiWrapper</string>
<!-- The number of thumbnails and icons to keep in the cache. The thumbnail cache size also
determines how many thumbnails will be fetched in the background. -->
+2
View File
@@ -26,6 +26,8 @@
<string name="recent_task_option_pin">Pin</string>
<!-- Title for an option to enter freeform mode for a given app -->
<string name="recent_task_option_freeform">Freeform</string>
<!-- Title for an option to enter desktop windowing mode for a given app -->
<string name="recent_task_option_desktop">Desktop</string>
<!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
<string name="recents_empty_message">No recent items</string>
@@ -240,7 +240,11 @@ public class PredictionRowView<T extends Context & ActivityContext>
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);
}
@@ -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 {
@@ -499,7 +499,7 @@ public class HotseatPredictionController implements DragController.DragListener,
@Override
public void onClick(View view) {
dismissTaskMenuView(mTarget);
dismissTaskMenuView();
pinPrediction(mItemInfo);
}
}
@@ -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<BaseDraggingActivity> SHORTCUT_FACTORY =
(activity, info, originalView) -> (info.getTargetComponent() == null) ? null
: INSTANCE.get(activity).getShortcutForApp(
public static final SystemShortcut.Factory<ActivityContext> 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);
}
@@ -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);
}
}
@@ -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
@@ -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;
}
@@ -425,15 +425,15 @@ 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()
&& !mLauncher.areFreeformTasksVisible();
&& !mTaskbarLauncherStateController.isInOverviewUi()
&& !mLauncher.areDesktopTasksVisible();
}
@Override
@@ -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;
@@ -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());
}
@@ -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);
@@ -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 =
@@ -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,
@@ -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();
}
@@ -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;
}
@@ -193,7 +193,7 @@ public class TaskbarUIController {
}
/** Returns {@code true} if Taskbar is currently within overview. */
protected boolean isInOverview() {
protected boolean isInOverviewUi() {
return false;
}
@@ -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<String, LauncherActivityInfo> 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<UserHandle, UserIconInfo> queryAllUsers(Context context) {
UserManager um = context.getSystemService(UserManager.class);
Map<UserHandle, UserIconInfo> users = new ArrayMap<>();
List<UserHandle> 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<String> 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;
}
}
}
@@ -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(),
@@ -937,7 +943,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
@@ -1055,8 +1061,9 @@ public class QuickstepLauncher extends Launcher {
.playPlaceholderDismissAnim(this, splitDismissEvent);
}
public <T extends OverviewActionsView> T getActionsView() {
return (T) mActionsView;
@Override
public OverviewActionsView<?> getActionsView() {
return mActionsView;
}
@Override
@@ -1284,9 +1291,9 @@ public class QuickstepLauncher extends Launcher {
}
@Override
public boolean areFreeformTasksVisible() {
public boolean areDesktopTasksVisible() {
if (mDesktopVisibilityController != null) {
return mDesktopVisibilityController.areFreeformTasksVisible();
return mDesktopVisibilityController.areDesktopTasksVisible();
}
return false;
}
@@ -1369,25 +1376,25 @@ public class QuickstepLauncher extends Launcher {
}
private static final class LauncherTaskViewController extends
TaskViewTouchController<Launcher> {
TaskViewTouchController<QuickstepLauncher> {
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);
}
}
@@ -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<String, LauncherActivityInfo> =
mContext.getSystemService(LauncherApps::class.java)!!.activityOverrides
override fun createFadeOutAnimOptions(): ActivityOptions =
ActivityOptions.makeBasic().apply {
remoteTransition = RemoteTransition(FadeOutRemoteTransition())
}
override fun queryAllUsers(): Map<UserHandle, UserIconInfo> {
if (!allowPrivateProfile() || !enablePrivateSpace()) {
return super.queryAllUsers()
}
val users = ArrayMap<UserHandle, UserIconInfo>()
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<String> =
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
}
@@ -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
@@ -91,8 +90,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;
@@ -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};
}
}
@@ -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.<RecentsView>getOverviewPanel();
public static float[] getOverviewScaleAndOffsetForModalState(RecentsView recentsView) {
Rect taskSize = recentsView.getSelectedTaskBounds();
Rect modalTaskSize = new Rect();
recentsView.getModalTaskSize(modalTaskSize);
@@ -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();
@@ -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,
@@ -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;
@@ -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);
@@ -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();
}
@@ -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<T extends BaseDraggingActivity>
public abstract class TaskViewTouchController<CONTAINER extends Context & RecentsViewContainer>
extends AnimatorListenerAdapter implements TouchController,
SingleAxisSwipeDetector.Listener {
@@ -63,7 +64,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
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<T extends BaseDraggingActivity>
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<T extends BaseDraggingActivity>
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<T extends BaseDraggingActivity>
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<T extends BaseDraggingActivity>
// - 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<T extends BaseDraggingActivity>
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<T extends BaseDraggingActivity>
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;
}
@@ -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);
}
@@ -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();
@@ -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<T extends StatefulActivity<S>,
public abstract class AbsSwipeUpHandler<T extends RecentsViewContainer,
Q extends RecentsView, S extends BaseState<S>>
extends SwipeUpAnimationLogic implements OnApplyWindowInsetsListener,
RecentsAnimationCallbacks.RecentsAnimationListener {
@@ -171,7 +171,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
// 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<S, T> mActivityInterface;
protected final BaseContainerInterface<S, T> 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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
}, 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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
}
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<T extends StatefulActivity<S>,
// 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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
traceToken.close();
dragLayer.post(() ->
dragLayer.getViewTreeObserver().removeOnDrawListener(this));
if (activity != mActivity) {
if (container != mContainer) {
return;
}
@@ -615,7 +616,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
});
}
activity.getRootView().setOnApplyWindowInsetsListener(this);
container.getRootView().setOnApplyWindowInsetsListener(this);
mStateCallback.setState(STATE_LAUNCHER_STARTED);
}
@@ -631,21 +632,21 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
// 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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
*/
private void setIsInAllAppsRegion(boolean isInAllAppsRegion) {
if (mIsInAllAppsRegion == isInAllAppsRegion
|| !mActivityInterface.allowAllAppsFromOverview()) {
|| !mContainerInterface.allowAllAppsFromOverview()) {
return;
}
mIsInAllAppsRegion = isInAllAppsRegion;
@@ -821,8 +822,9 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
if (!canCreateNewOrUpdateExistingLauncherTransitionController()) {
return;
}
initTransitionEndpoints(mActivity.getDeviceProfile());
initTransitionEndpoints(mContainer.getDeviceProfile());
mAnimationFactory.createActivityInterface(mTransitionDragLength);
}
@@ -846,7 +848,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
*/
private boolean canCreateNewOrUpdateExistingLauncherTransitionController() {
return mGestureState.getEndTarget() != HOME
&& !mHasEndedLauncherTransition && mActivity != null;
&& !mHasEndedLauncherTransition && mContainer != null;
}
@Override
@@ -930,11 +932,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
// 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<T extends StatefulActivity<S>,
// 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<T extends StatefulActivity<S>,
.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<T extends StatefulActivity<S>,
@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<T extends StatefulActivity<S>,
*/
@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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
// 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<T extends StatefulActivity<S>,
}
}
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
}
// 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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
}
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<T extends StatefulActivity<S>,
* 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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
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<T extends StatefulActivity<S>,
// 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;
}
@@ -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<STATE_TYPE extends BaseState<STATE_TYPE>,
ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE>> {
public final boolean rotationSupportedByActivity;
ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE> & RecentsViewContainer> extends
BaseContainerInterface<STATE_TYPE, ACTIVITY_TYPE> {
private final STATE_TYPE mBackgroundState;
private STATE_TYPE mTargetState;
@@ -100,7 +81,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
*/
public void onTransitionCancelled(boolean activityVisible,
@Nullable GestureState.GestureEndTarget endTarget) {
ACTIVITY_TYPE activity = getCreatedActivity();
ACTIVITY_TYPE activity = getCreatedContainer();
if (activity == null) {
return;
}
@@ -109,12 +90,12 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
// 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.areFreeformTasksVisible()
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 freeform tasks are visible
// 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 = activity.getStateManager().getRestState();
// Do not animate the transition
@@ -124,49 +105,21 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
activity.getStateManager().goToState(startState, activityVisible);
}
public abstract int getSwipeUpDestinationAndLength(
DeviceProfile dp, Context context, Rect outRect,
RecentsPagedOrientationHandler orientationHandler);
/** Called when the animation to home has fully settled. */
public void onSwipeUpToHomeComplete(RecentsAnimationDeviceState deviceState) {}
public abstract void onAssistantVisibilityChanged(float visibility);
public abstract AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback);
public abstract ActivityInitListener createActivityInitListener(
Predicate<Boolean> 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<STATE_TYPE extends BaseState<STATE_T
@UiThread
public abstract boolean switchToRecentsIfVisible(Animator.AnimatorListener animatorListener);
public abstract Rect getOverviewWindowBounds(
Rect homeBounds, RemoteAnimationTarget target);
public abstract boolean allowMinimizeSplitScreen();
/** @return whether to allow going to All Apps from Overview. */
public abstract boolean allowAllAppsFromOverview();
public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
TaskbarUIController controller = getTaskbarController();
boolean isEventOverBubbleBarStashHandle =
@@ -193,20 +138,6 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|| isTrackpadMultiFingerSwipe(ev) || isEventOverBubbleBarStashHandle;
}
/**
* @return Whether the gesture in progress should be cancelled.
*/
public boolean shouldCancelCurrentGesture() {
return false;
}
public abstract void onExitOverview(RotationTouchHelper deviceState,
Runnable exitRunnable);
public abstract boolean isInLiveTileMode();
public abstract void onLaunchTaskFailed();
/**
* Closes any overlays.
*/
@@ -217,7 +148,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
public void switchRunningTaskViewToScreenshot(HashMap<Integer, ThumbnailData> thumbnailDatas,
Runnable runnable) {
ACTIVITY_TYPE activity = getCreatedActivity();
ACTIVITY_TYPE activity = getCreatedContainer();
if (activity == null) {
return;
}
@@ -231,230 +162,9 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
recentsView.switchToScreenshot(thumbnailDatas, runnable);
}
/**
* Calculates the taskView size for the provided device configuration.
*/
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);
}
/**
* 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) {
ACTIVITY_TYPE activity = getCreatedActivity();
if (activity == null) {
return null;
}
RecentsView recentsView = activity.getOverviewPanel();
STATE_TYPE state = stateFromGestureEndTarget(endTarget);
ScrimView scrimView = activity.getScrimView();
ObjectAnimator anim = ObjectAnimator.ofArgb(scrimView, VIEW_BACKGROUND_COLOR,
getOverviewScrimColorForState(activity, state));
anim.setDuration(duration);
anim.setInterpolator(recentsView == null || !recentsView.isKeyboardTaskFocusPending()
? LINEAR : INSTANT);
return anim;
}
return null;
}
/**
* 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(ACTIVITY_TYPE activity, STATE_TYPE state);
/**
* Returns the expected STATE_TYPE from the provided GestureEndTarget.
*/
public abstract STATE_TYPE stateFromGestureEndTarget(GestureState.GestureEndTarget endTarget);
/**
* 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;
}
protected void runOnInitBackgroundStateUI(Runnable callback) {
ACTIVITY_TYPE activity = getCreatedActivity();
ACTIVITY_TYPE activity = getCreatedContainer();
if (activity != null && activity.getStateManager().getState() == mBackgroundState) {
callback.run();
onInitBackgroundStateUI();
@@ -505,7 +215,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
DefaultAnimationFactory(Consumer<AnimatorControllerWithResistance> callback) {
mCallback = callback;
mActivity = getCreatedActivity();
mActivity = getCreatedContainer();
mStartState = mActivity.getStateManager().getState();
}
@@ -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<STATE_TYPE extends BaseState<STATE_TYPE>,
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<AnimatorControllerWithResistance> callback);
public abstract ActivityInitListener createActivityInitListener(
Predicate<Boolean> onInitListener);
/**
* Returns the expected STATE_TYPE from the provided GestureEndTarget.
*/
public abstract STATE_TYPE stateFromGestureEndTarget(GestureState.GestureEndTarget endTarget);
public abstract void switchRunningTaskViewToScreenshot(HashMap<Integer,
ThumbnailData> 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);
}
}
@@ -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.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(
container: RecentsViewContainer,
private val mTaskContainer: TaskIdAttributeContainer,
abstractFloatingViewHelper: AbstractFloatingViewHelper
) :
SystemShortcut<RecentsViewContainer>(
R.drawable.ic_caption_desktop_button_foreground,
R.string.recent_task_option_desktop,
container,
mTaskContainer.itemInfo,
mTaskContainer.taskView,
abstractFloatingViewHelper
) {
override fun onClick(view: View) {
dismissTaskMenuView()
val recentsView = mTarget!!.getOverviewPanel<RecentsView<*, *>>()
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(
container: RecentsViewContainer,
taskContainer: TaskIdAttributeContainer
): List<DesktopSystemShortcut>? {
return if (!Flags.enableDesktopWindowingMode()) null
else if (!taskContainer.task.isDockable) null
else
listOf(
DesktopSystemShortcut(
container,
taskContainer,
abstractFloatingViewHelper
)
)
}
override fun showForSplitscreen() = true
}
}
}
}
@@ -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",
@@ -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<RecentsState> stateManager = getCreatedActivity().getStateManager();
final StateManager<RecentsState> 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());
}
@@ -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);
}
}
@@ -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 <S extends BaseState<S>,
T extends StatefulActivity<S>> BaseActivityInterface<S, T> getActivityInterface() {
return mActivityInterface;
public <S extends BaseState<S>, T extends RecentsViewContainer>
BaseContainerInterface<S, T> getContainerInterface() {
return mContainerInterface;
}
/**
@@ -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<LauncherState> stateManager = getCreatedActivity().getStateManager();
final StateManager<LauncherState> stateManager = getCreatedContainer().getStateManager();
stateManager.addStateListener(
new StateManager.StateListener<LauncherState>() {
@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
@@ -75,7 +75,7 @@ public class LauncherSwipeHandlerV2 extends
protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> 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();
}
@@ -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 <T extends StatefulActivity<?>> boolean executeCommand(CommandInfo cmd) {
private <T extends StatefulActivity<?> & 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;
}
@@ -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();
@@ -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<RecentsState> {
public final class RecentsActivity extends StatefulActivity<RecentsState> implements
RecentsViewContainer {
private static final String TAG = "RecentsActivity";
public static final ActivityTracker<RecentsActivity> ACTIVITY_TRACKER =
@@ -109,7 +112,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
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<RecentsState> {
}
@Override
public <T extends View> T getOverviewPanel() {
return (T) mFallbackRecentsView;
public FallbackRecentsView getOverviewPanel() {
return mFallbackRecentsView;
}
public OverviewActionsView getActionsView() {
@Override
public OverviewActionsView<?> getActionsView() {
return mActionsView;
}
@@ -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;
@@ -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,11 +66,11 @@ 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) {
int visibleTasksCount = desktopVisibilityController.getVisibleFreeformTasksCount();
int visibleTasksCount = desktopVisibilityController.getVisibleDesktopTasksCount();
if (visibleTasksCount > 0) {
// Allocate +1 to account for a new task added to the desktop mode
int numHandles = visibleTasksCount + 1;
@@ -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);
@@ -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);
@@ -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) {
@@ -1475,6 +1475,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
//
@@ -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 */,
@@ -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<SystemShortcut> getEnabledShortcuts(TaskView taskView,
TaskIdAttributeContainer taskContainer) {
final ArrayList<SystemShortcut> 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<SystemShortcut> menuShortcuts = menuOption.getShortcuts(activity, taskContainer);
List<SystemShortcut> menuShortcuts = menuOption.getShortcuts(container, taskContainer);
if (menuShortcuts == null) {
continue;
}
@@ -79,15 +80,16 @@ 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 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<SystemShortcut> screenshotShortcuts = TaskShortcutFactory.SCREENSHOT
.getShortcuts(activity, taskContainer);
.getShortcuts(container, taskContainer);
if (screenshotShortcuts != null) {
shortcuts.addAll(screenshotShortcuts);
}
@@ -96,7 +98,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
// or in grid-only overview.
if (orientedState.getDisplayRotation() == ROTATION_0 || isGridOnlyOverview) {
List<SystemShortcut> modalShortcuts = TaskShortcutFactory.MODAL
.getShortcuts(activity, taskContainer);
.getShortcuts(container, taskContainer);
if (modalShortcuts != null) {
shortcuts.addAll(modalShortcuts);
}
@@ -136,6 +138,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
TaskShortcutFactory.PIN,
TaskShortcutFactory.INSTALL,
TaskShortcutFactory.FREE_FORM,
DesktopSystemShortcut.Companion.createFactory(),
TaskShortcutFactory.WELLBEING,
TaskShortcutFactory.SAVE_APP_PAIR
};
@@ -253,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);
}
/**
@@ -303,19 +306,19 @@ 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
public void onClick(View view) {
saveScreenshot(mThumbnailView.getTaskView().getTask());
dismissTaskMenuView(mActivity);
dismissTaskMenuView();
}
}
@@ -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<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
default List<SystemShortcut> getShortcuts(RecentsViewContainer container,
TaskIdAttributeContainer taskContainer) {
return null;
}
@@ -94,7 +94,7 @@ public interface TaskShortcutFactory {
TaskShortcutFactory APP_INFO = new TaskShortcutFactory() {
@Override
public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
public List<SystemShortcut> 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,25 +133,26 @@ 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<BaseDraggingActivity> {
class SaveAppPairSystemShortcut extends SystemShortcut<RecentsViewContainer> {
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;
}
@Override
public void onClick(View view) {
dismissTaskMenuView(mTarget);
dismissTaskMenuView();
((RecentsView) mTarget.getOverviewPanel())
.getSplitSelectController().getAppPairsController().saveAppPair(mTaskView);
}
}
class FreeformSystemShortcut extends SystemShortcut<BaseDraggingActivity> {
class FreeformSystemShortcut extends SystemShortcut<RecentsViewContainer> {
private static final String TAG = "FreeformSystemShortcut";
private Handler mHandler;
@@ -161,20 +162,20 @@ 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();
}
@Override
public void onClick(View view) {
dismissTaskMenuView(mTarget);
dismissTaskMenuView();
RecentsView rv = mTarget.getOverviewPanel();
rv.switchToScreenshot(() -> {
rv.finishRecentsAnimation(true /* toRecents */, false /* shouldPip */, () -> {
@@ -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<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
public List<SystemShortcut> 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<SplitPositionOption, SystemShortcut>) 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<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
public List<SystemShortcut> 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<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
public List<SystemShortcut> 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<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
public List<SystemShortcut> 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<BaseDraggingActivity> {
class PinSystemShortcut extends SystemShortcut<RecentsViewContainer> {
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,10 +419,10 @@ 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(mTarget);
dismissTaskMenuView();
mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo())
.log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP);
}
@@ -428,12 +430,12 @@ public interface TaskShortcutFactory {
TaskShortcutFactory INSTALL = new TaskShortcutFactory() {
@Override
public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
public List<SystemShortcut> 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<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
TaskIdAttributeContainer taskContainer) {
SystemShortcut<BaseDraggingActivity> wellbeingShortcut =
WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity,
SystemShortcut<ActivityContext> 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<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
public List<SystemShortcut> 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<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
TaskIdAttributeContainer taskContainer) {
SystemShortcut modalStateSystemShortcut =
taskContainer.getThumbnailView().getTaskOverlay()
@@ -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);
}
@@ -602,23 +603,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);
}
}
@@ -830,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();
@@ -1148,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();
@@ -1172,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()
@@ -1182,7 +1181,7 @@ public class TouchInteractionService extends Service {
&& !launcherResumedThroughShellTransition
&& !previousGestureState.isRecentsAnimationRunning();
if (gestureState.getActivityInterface().isInLiveTileMode()) {
if (gestureState.getContainerInterface().isInLiveTileMode()) {
return createOverviewInputConsumer(
previousGestureState,
gestureState,
@@ -1230,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,
@@ -1264,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"
@@ -1289,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);
}
}
@@ -1369,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.
@@ -1391,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;
@@ -1441,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);
@@ -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.<FallbackRecentsView>getOverviewPanel().startHome();
mContainer.<FallbackRecentsView>getOverviewPanel().startHome();
}
}
@@ -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
@@ -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<RecentsActivity, RecentsSta
public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr, FallbackActivityInterface.INSTANCE);
mActivity.getStateManager().addStateListener(this);
mContainer.getStateManager().addStateListener(this);
}
@Override
@@ -80,13 +81,18 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
@Override
protected void handleStartHome(boolean animated) {
mActivity.startHome();
AbstractFloatingView.closeAllOpenViews(mActivity, mActivity.isStarted());
mContainer.startHome();
AbstractFloatingView.closeAllOpenViews(mContainer, mContainer.isStarted());
}
@Override
protected boolean canStartHomeSafely() {
return mActivity.canStartHomeSafely();
return mContainer.canStartHomeSafely();
}
@Override
public StateManager<RecentsState> getStateManager() {
return mContainer.getStateManager();
}
/**
@@ -210,10 +216,10 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
public void setModalStateEnabled(int taskId, boolean animate) {
if (taskId != INVALID_TASK_ID) {
setSelectedTask(taskId);
mActivity.getStateManager().goToState(RecentsState.MODAL_TASK, animate);
mContainer.getStateManager().goToState(RecentsState.MODAL_TASK, animate);
} else {
if (mActivity.isInState(RecentsState.MODAL_TASK)) {
mActivity.getStateManager().goToState(DEFAULT, animate);
if (mContainer.isInState(RecentsState.MODAL_TASK)) {
mContainer.getStateManager().goToState(DEFAULT, animate);
}
}
}
@@ -223,13 +229,13 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
@SplitConfigurationOptions.StagePosition int stagePosition,
StatsLogManager.EventEnum splitEvent) {
super.initiateSplitSelect(taskView, stagePosition, splitEvent);
mActivity.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
mContainer.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
}
@Override
public void onStateTransitionStart(RecentsState toState) {
setOverviewStateEnabled(true);
setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
setOverviewFullscreenEnabled(toState.isFullScreen());
if (toState == MODAL_TASK) {
setOverviewSelectEnabled(true);
@@ -280,7 +286,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
public void setOverviewStateEnabled(boolean enabled) {
super.setOverviewStateEnabled(enabled);
if (enabled) {
RecentsState state = mActivity.getStateManager().getState();
RecentsState state = mContainer.getStateManager().getState();
setDisallowScrollToClearAll(!state.hasClearAllButton());
}
}
@@ -289,18 +295,18 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
public boolean onTouchEvent(MotionEvent ev) {
boolean result = super.onTouchEvent(ev);
// Do not let touch escape to siblings below this view.
return result || mActivity.getStateManager().getState().overviewUi();
return result || mContainer.getStateManager().getState().overviewUi();
}
@Override
public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
super.initiateSplitSelect(splitSelectSource);
mActivity.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
mContainer.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
}
@Override
protected boolean canLaunchFullscreenTask() {
return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
return !mContainer.isInState(OVERVIEW_SPLIT_SELECT);
}
/** Returns if app pairs are supported in this launcher. */
@@ -26,7 +26,8 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.util.Themes;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.RecentsViewContainer;
/**
* State definition for Fallback recents
@@ -126,12 +127,13 @@ public class RecentsState implements BaseState<RecentsState> {
/**
* 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<RecentsState> {
}
@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<RecentsState> {
}
@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<RecentsState> {
}
@Override
public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
public float[] getOverviewScaleAndOffset(RecentsViewContainer container) {
return new float[] { NO_SCALE, 1 };
}
}
@@ -26,7 +26,7 @@ public class RecentsTaskController extends TaskViewTouchController<RecentsActivi
@Override
protected boolean isRecentsInteractive() {
return mActivity.hasWindowFocus() || mActivity.getStateManager().getState().hasLiveTile();
return mContainer.hasWindowFocus() || mContainer.getStateManager().getState().hasLiveTile();
}
@Override
@@ -43,13 +43,13 @@ import android.view.MotionEvent;
import android.view.ViewConfiguration;
import com.android.app.animation.Interpolators;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.BaseContainerInterface;
import com.android.quickstep.GestureState;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.views.RecentsViewContainer;
import com.android.systemui.shared.system.InputMonitorCompat;
import java.util.function.Consumer;
@@ -78,7 +78,7 @@ public class AssistantInputConsumer extends DelegateInputConsumer {
private float mTimeFraction;
private long mDragTime;
private float mLastProgress;
private BaseActivityInterface mActivityInterface;
private BaseContainerInterface mContainerInterface;
private final float mDragDistThreshold;
private final float mFlingDistThreshold;
@@ -106,7 +106,7 @@ public class AssistantInputConsumer extends DelegateInputConsumer {
float slop = ViewConfiguration.get(context).getScaledTouchSlop();
mSquaredSlop = slop * slop;
mActivityInterface = gestureState.getActivityInterface();
mContainerInterface = gestureState.getContainerInterface();
boolean flingDisabled = deviceState.isAssistantGestureIsConstrained()
|| deviceState.isInDeferredGestureRegion(startEvent);
@@ -237,9 +237,9 @@ public class AssistantInputConsumer extends DelegateInputConsumer {
}
private void startAssistantInternal() {
BaseDraggingActivity launcherActivity = mActivityInterface.getCreatedActivity();
if (launcherActivity != null) {
launcherActivity.getRootView().performHapticFeedback(
RecentsViewContainer container = mContainerInterface.getCreatedContainer();
if (container != null) {
container.getRootView().performHapticFeedback(
13, // HapticFeedbackConstants.GESTURE_END
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
@@ -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);
}
@@ -49,7 +49,6 @@ import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.AbsSwipeUpHandler;
import com.android.quickstep.AbsSwipeUpHandler.Factory;
import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.GestureState;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.RecentsAnimationCallbacks;
@@ -86,8 +85,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
private final InputMonitorCompat mInputMonitorCompat;
private final InputEventReceiver mInputEventReceiver;
private final BaseActivityInterface mActivityInterface;
private final AbsSwipeUpHandler.Factory mHandlerFactory;
private final Consumer<OtherActivityInputConsumer> 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()
@@ -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<S extends BaseState<S>, T extends StatefulActivity<S>>
public class OverviewInputConsumer<S extends BaseState<S>, T extends RecentsViewContainer>
implements InputConsumer {
private final T mActivity;
private final BaseActivityInterface<?, T> mActivityInterface;
private final T mContainer;
private final BaseContainerInterface<?, T> mContainerInterface;
private final BaseDragLayer mTarget;
private final InputMonitorCompat mInputMonitor;
@@ -56,14 +56,14 @@ public class OverviewInputConsumer<S extends BaseState<S>, 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<S extends BaseState<S>, 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<S extends BaseState<S>, 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<S extends BaseState<S>, 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<S extends BaseState<S>, 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<S extends BaseState<S>, T extends StatefulAct
default:
break;
}
mActivity.dispatchKeyEvent(ev);
mContainer.dispatchKeyEvent(ev);
}
private void setTouchModeChanged(@NonNull View viewRoot) {
@@ -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);
}
@@ -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<LauncherState> stateManager = activity.getStateManager();
if (recentsOrientedState.getContainerInterface().allowAllAppsFromOverview()) {
RecentsViewContainer container =
recentsOrientedState.getContainerInterface().getCreatedContainer();
if (container != null) {
RecentsView recentsView = container.getOverviewPanel();
StateManager<LauncherState> 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;
}
@@ -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);
@@ -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<Long> getLPNHDurationMillis() {
return Optional.empty();
}
/** Get the Launcher overridden long press touch slop multiplier to trigger Assistant. */
public Optional<Long> getLPNHCustomSlopMultiplier() {
/**
* Get the Launcher overridden long press nav handle touch slop multiplier to trigger Assistant.
*/
public Optional<Float> getLPNHCustomSlopMultiplier() {
return Optional.empty();
}
/** Get the Launcher overridden long press home duration to trigger Assistant. */
public Optional<Long> getLPHDurationMillis() {
return Optional.empty();
}
/** Get the Launcher overridden long press home touch slop multiplier to trigger Assistant. */
public Optional<Float> 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;
@@ -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<InputConsumer> {
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<InputConsumer> {
*/
@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);
}
}
@@ -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> 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) {
@@ -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<ACTIVITY_TYPE extends StatefulActivity, STATE_TYPE>
extends AtomicAnimationFactory<STATE_TYPE> {
public class RecentsAtomicAnimationFactory<CONTAINER extends Context & RecentsViewContainer,
STATE_TYPE> extends AtomicAnimationFactory<STATE_TYPE> {
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)
@@ -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;
}
/**
@@ -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
@@ -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<Runnable>
) {
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)
}
}
}
@@ -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());
@@ -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();
@@ -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());
}
@@ -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;
}
@@ -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;
@@ -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;
}
@@ -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;
}
@@ -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 {
@@ -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
@@ -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()
@@ -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;
}
});
@@ -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;
@@ -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();
@@ -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)
}
}
@@ -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<FloatingTaskView> PRIMARY_TRANSLATE_OFFSCREEN =
new FloatProperty<FloatingTaskView>("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() {
@@ -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) {
@@ -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<Point, Point> 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;
@@ -72,7 +72,7 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
public LauncherRecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr, LauncherActivityInterface.INSTANCE);
mActivity.getStateManager().addStateListener(this);
getStateManager().addStateListener(this);
}
@Override
@@ -85,28 +85,33 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
@Override
protected void handleStartHome(boolean animated) {
StateManager stateManager = mActivity.getStateManager();
StateManager stateManager = getStateManager();
animated &= stateManager.shouldAnimateStateChange();
stateManager.goToState(NORMAL, animated);
if (FeatureFlags.enableSplitContextually()) {
mSplitSelectStateController.getSplitAnimationController()
.playPlaceholderDismissAnim(mActivity, LAUNCHER_SPLIT_SELECTION_EXIT_HOME);
.playPlaceholderDismissAnim(mContainer, LAUNCHER_SPLIT_SELECTION_EXIT_HOME);
}
AbstractFloatingView.closeAllOpenViews(mActivity, animated);
AbstractFloatingView.closeAllOpenViews(mContainer, animated);
}
@Override
protected boolean canStartHomeSafely() {
return mActivity.canStartHomeSafely();
return mContainer.canStartHomeSafely();
}
@Override
public StateManager<LauncherState> 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<QuickstepLauncher, Launcher
public void onTaskIconChanged(int taskId) {
super.onTaskIconChanged(taskId);
// If Launcher needs to return to split select state, do it now, after the icon has updated.
if (mActivity.hasPendingSplitSelectInfo()) {
PendingSplitSelectInfo recoveryData = mActivity.getPendingSplitSelectInfo();
if (mContainer.hasPendingSplitSelectInfo()) {
PendingSplitSelectInfo recoveryData = mContainer.getPendingSplitSelectInfo();
if (recoveryData.getStagedTaskId() == taskId) {
initiateSplitSelect(
getTaskViewByTaskId(recoveryData.getStagedTaskId()),
recoveryData.getStagePosition(), recoveryData.getSource()
);
mActivity.finishSplitSelectRecovery();
mContainer.finishSplitSelectRecovery();
}
}
}
@@ -139,7 +144,7 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
public void onStateTransitionStart(LauncherState toState) {
setOverviewStateEnabled(toState.overviewUi);
setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
setOverviewFullscreenEnabled(toState.getOverviewFullscreenProgress() == 1);
if (toState == OVERVIEW_MODAL_TASK) {
setOverviewSelectEnabled(true);
@@ -153,8 +158,8 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
}
setFreezeViewVisibility(true);
if (mActivity.getDesktopVisibilityController() != null) {
mActivity.getDesktopVisibilityController().onLauncherStateChanged(toState);
if (mContainer.getDesktopVisibilityController() != null) {
mContainer.getDesktopVisibilityController().onLauncherStateChanged(toState);
}
}
@@ -186,8 +191,8 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
public void setOverviewStateEnabled(boolean enabled) {
super.setOverviewStateEnabled(enabled);
if (enabled) {
LauncherState state = mActivity.getStateManager().getState();
boolean hasClearAllButton = (state.getVisibleElements(mActivity)
LauncherState state = getStateManager().getState();
boolean hasClearAllButton = (state.getVisibleElements(mContainer)
& CLEAR_ALL_BUTTON) != 0;
setDisallowScrollToClearAll(!hasClearAllButton);
}
@@ -197,30 +202,28 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
public boolean onTouchEvent(MotionEvent ev) {
boolean result = super.onTouchEvent(ev);
// Do not let touch escape to siblings below this view.
return result || mActivity.getStateManager().getState().overviewUi;
return result || getStateManager().getState().overviewUi;
}
@Override
protected DepthController getDepthController() {
return mActivity.getDepthController();
return mContainer.getDepthController();
}
@Override
public void setModalStateEnabled(int taskId, boolean animate) {
if (taskId != INVALID_TASK_ID) {
setSelectedTask(taskId);
mActivity.getStateManager().goToState(LauncherState.OVERVIEW_MODAL_TASK, animate);
} else {
if (mActivity.isInState(LauncherState.OVERVIEW_MODAL_TASK)) {
mActivity.getStateManager().goToState(LauncherState.OVERVIEW, animate);
}
getStateManager().goToState(LauncherState.OVERVIEW_MODAL_TASK, animate);
} else if (mContainer.isInState(LauncherState.OVERVIEW_MODAL_TASK)) {
getStateManager().goToState(LauncherState.OVERVIEW, animate);
}
}
@Override
protected void onDismissAnimationEnds() {
super.onDismissAnimationEnds();
if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
if (mContainer.isInState(OVERVIEW_SPLIT_SELECT)) {
// We want to keep the tasks translations in this temporary state
// after resetting the rest above
setTaskViewsPrimarySplitTranslation(mTaskViewsPrimarySplitTranslation);
@@ -233,13 +236,13 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
@SplitConfigurationOptions.StagePosition int stagePosition,
StatsLogManager.EventEnum splitEvent) {
super.initiateSplitSelect(taskView, stagePosition, splitEvent);
mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
}
@Override
public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
super.initiateSplitSelect(splitSelectSource);
mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
}
@Override
@@ -247,7 +250,7 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
if (FeatureFlags.enableSplitContextually()) {
return !mSplitSelectStateController.isSplitSelectActive();
} else {
return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
return !mContainer.isInState(OVERVIEW_SPLIT_SELECT);
}
}
@@ -256,7 +259,7 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
RotationTouchHelper rotationTouchHelper) {
super.onGestureAnimationStart(runningTasks, rotationTouchHelper);
DesktopVisibilityController desktopVisibilityController =
mActivity.getDesktopVisibilityController();
mContainer.getDesktopVisibilityController();
if (desktopVisibilityController != null) {
desktopVisibilityController.setRecentsGestureStart();
}
@@ -265,13 +268,14 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
@Override
public void onGestureAnimationEnd() {
DesktopVisibilityController desktopVisibilityController =
mActivity.getDesktopVisibilityController();
mContainer.getDesktopVisibilityController();
boolean showDesktopApps = false;
GestureState.GestureEndTarget endTarget = null;
if (desktopVisibilityController != null) {
desktopVisibilityController = mContainer.getDesktopVisibilityController();
endTarget = mCurrentGestureEndTarget;
if (endTarget == GestureState.GestureEndTarget.LAST_TASK
&& desktopVisibilityController.areFreeformTasksVisible()) {
&& desktopVisibilityController.areDesktopTasksVisible()) {
// Recents gesture was cancelled and we are returning to the previous task.
// After super class has handled clean up, show desktop apps on top again
showDesktopApps = true;
@@ -282,7 +286,7 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
desktopVisibilityController.setRecentsGestureEnd(endTarget);
}
if (showDesktopApps) {
SystemUiProxy.INSTANCE.get(mActivity).showDesktopApps(mActivity.getDisplayId(),
SystemUiProxy.INSTANCE.get(mContainer).showDesktopApps(mContainer.getDisplayId(),
null /* transition */);
}
}
@@ -61,7 +61,6 @@ import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_RIGHT;
import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_TAB;
import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_UP;
import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
import static com.android.window.flags.Flags.enableDesktopWindowingMode;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_ACTIONS_IN_MENU;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_DESKTOP;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
@@ -69,6 +68,7 @@ import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SELECT_ACTIVE;
import static com.android.window.flags.Flags.enableDesktopWindowingMode;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -129,7 +129,6 @@ import androidx.annotation.UiThread;
import androidx.core.graphics.ColorUtils;
import com.android.internal.jank.Cuj;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
@@ -149,7 +148,7 @@ import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.OverScroll;
@@ -163,10 +162,11 @@ 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;
import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.BaseContainerInterface;
import com.android.quickstep.GestureState;
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.RecentsAnimationController;
@@ -226,8 +226,11 @@ import java.util.stream.Collectors;
/**
* A list of recent tasks.
* @param <CONTAINER_TYPE> : the container that should host recents view
* @param <STATE_TYPE> : the type of base state that will be used
*/
public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE>,
public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewContainer,
STATE_TYPE extends BaseState<STATE_TYPE>> extends PagedView implements Insettable,
TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
TaskVisualsChangeListener {
@@ -443,7 +446,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
private static final float FOREGROUND_SCRIM_TINT = 0.32f;
protected final RecentsOrientedState mOrientationState;
protected final BaseActivityInterface<STATE_TYPE, ACTIVITY_TYPE> mSizeStrategy;
protected final BaseContainerInterface<STATE_TYPE, CONTAINER_TYPE> mSizeStrategy;
@Nullable
protected RecentsAnimationController mRecentsAnimationController;
@Nullable
@@ -480,7 +483,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// The threshold at which we update the SystemUI flags when animating from the task into the app
public static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.85f;
protected final ACTIVITY_TYPE mActivity;
protected final CONTAINER_TYPE mContainer;
private final float mFastFlingVelocity;
private final int mScrollHapticMinGapMillis;
private final RecentsModel mModel;
@@ -767,14 +770,14 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
private final RecentsFilterState mFilterState = new RecentsFilterState();
public RecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
BaseActivityInterface sizeStrategy) {
BaseContainerInterface sizeStrategy) {
super(context, attrs, defStyleAttr);
setEnableFreeScroll(true);
mSizeStrategy = sizeStrategy;
mActivity = BaseActivity.fromContext(context);
mContainer = RecentsViewContainer.containerFromContext(context);
mOrientationState = new RecentsOrientedState(
context, mSizeStrategy, this::animateRecentsRotationInPlace);
final int rotation = mActivity.getDisplay().getRotation();
final int rotation = mContainer.getDisplay().getRotation();
mOrientationState.setRecentsRotation(rotation);
mScrollHapticMinGapMillis = getResources()
@@ -826,7 +829,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
R.string.task_overlay_factory_class);
// Initialize quickstep specific cache params here, as this is constructed only once
mActivity.getViewCache().setCacheSize(R.layout.digital_wellbeing_toast, 5);
mContainer.getViewCache().setCacheSize(R.layout.digital_wellbeing_toast, 5);
mTintingColor = getForegroundScrimDimColor(context);
@@ -834,9 +837,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
if (FeatureFlags.ENABLE_MULTI_INSTANCE.get()) {
// invalidate the current list of tasks if filter changes with a fading in/out animation
mFilterState.setOnFilterUpdatedListener(() -> {
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
@@ -1088,13 +1091,13 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
super.onAttachedToWindow();
updateTaskStackListenerState();
mModel.getThumbnailCache().getHighResLoadingState().addCallback(this);
mActivity.addMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
mContainer.addMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
mSyncTransactionApplier = new SurfaceTransactionApplier(this);
runActionOnRemoteHandles(remoteTargetHandle -> 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();
@@ -1109,7 +1112,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
super.onDetachedFromWindow();
updateTaskStackListenerState();
mModel.getThumbnailCache().getHighResLoadingState().removeCallback(this);
mActivity.removeMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
mContainer.removeMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
mSyncTransactionApplier = null;
runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
@@ -1249,7 +1252,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
if (taskView == null || !isTaskViewVisible(taskView)) {
// TODO: Refine this animation.
SurfaceTransactionApplier surfaceApplier =
new SurfaceTransactionApplier(mActivity.getDragLayer());
new SurfaceTransactionApplier(mContainer.getDragLayer());
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
appAnimator.setInterpolator(ACCELERATE_DECELERATE);
@@ -1260,9 +1263,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
for (int i = apps.length - 1; i >= 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);
@@ -1294,7 +1297,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
});
} else {
TaskViewUtils.composeRecentsLaunchAnimator(anim, taskView, apps, wallpaper, nonApps,
true /* launcherClosing */, mActivity.getStateManager(), this,
true /* launcherClosing */, getStateManager(), this,
getDepthController());
}
anim.start();
@@ -1471,7 +1474,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
@Override
protected void onPageBeginTransition() {
super.onPageBeginTransition();
if (!mActivity.getDeviceProfile().isTablet) {
if (!mContainer.getDeviceProfile().isTablet) {
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, true);
}
if (mOverviewStateEnabled) { // only when in overview
@@ -1484,7 +1487,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
super.onPageEndTransition();
ActiveGestureLog.INSTANCE.addLog(
"onPageEndTransition: current page index updated", getNextPage());
if (isClearAllHidden() && !mActivity.getDeviceProfile().isTablet) {
if (isClearAllHidden() && !mContainer.getDeviceProfile().isTablet) {
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
}
if (getNextPage() > 0) {
@@ -1495,7 +1498,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
@Override
protected boolean isSignificantMove(float absoluteDelta, int pageOrientedSize) {
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
DeviceProfile deviceProfile = mContainer.getDeviceProfile();
if (!deviceProfile.isTablet) {
return super.isSignificantMove(absoluteDelta, pageOrientedSize);
}
@@ -1504,6 +1507,15 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
> 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);
@@ -1644,7 +1656,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* required to move the running task in grid.
*/
public void moveRunningTaskToFront() {
if (!mActivity.getDeviceProfile().isTablet) {
if (!mContainer.getDeviceProfile().isTablet) {
return;
}
@@ -2012,9 +2024,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
mInsets.set(insets);
// Update DeviceProfile dependant state.
DeviceProfile dp = mActivity.getDeviceProfile();
DeviceProfile dp = mContainer.getDeviceProfile();
setOverviewGridEnabled(
mActivity.getStateManager().getState().displayOverviewTasksAsGrid(dp));
getStateManager().getState().displayOverviewTasksAsGrid(dp));
if (enableGridOnlyOverview()) {
mActionsView.updateHiddenFlags(HIDDEN_ACTIONS_IN_MENU, dp.isTablet);
}
@@ -2051,7 +2063,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
if (forceRecreateDragLayerControllers
|| !getPagedOrientationHandler().equals(oldOrientationHandler)) {
// Changed orientations, update controllers so they intercept accordingly.
mActivity.getDragLayer().recreateControllers();
mContainer.getDragLayer().recreateControllers();
onOrientationChanged();
resetTaskVisuals();
}
@@ -2083,21 +2095,21 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// Update task size and padding that are dependent on DeviceProfile and insets.
private void updateSizeAndPadding() {
DeviceProfile dp = mActivity.getDeviceProfile();
DeviceProfile dp = mContainer.getDeviceProfile();
getTaskSize(mLastComputedTaskSize);
mTaskWidth = mLastComputedTaskSize.width();
mTaskHeight = mLastComputedTaskSize.height();
setPadding(mLastComputedTaskSize.left - mInsets.left,
mLastComputedTaskSize.top - dp.overviewTaskThumbnailTopMarginPx - mInsets.top,
dp.widthPx - mInsets.right - mLastComputedTaskSize.right,
dp.heightPx - mInsets.bottom - mLastComputedTaskSize.bottom);
mSizeStrategy.calculateGridSize(dp, mActivity, mLastComputedGridSize);
mSizeStrategy.calculateGridTaskSize(mActivity, dp, mLastComputedGridTaskSize,
mSizeStrategy.calculateGridSize(dp, mContainer, mLastComputedGridSize);
mSizeStrategy.calculateGridTaskSize(mContainer, dp, mLastComputedGridTaskSize,
getPagedOrientationHandler());
if (enableGridOnlyOverview()) {
mSizeStrategy.calculateCarouselTaskSize(mActivity, dp, mLastComputedCarouselTaskSize,
mSizeStrategy.calculateCarouselTaskSize(mContainer, dp, mLastComputedCarouselTaskSize,
getPagedOrientationHandler());
}
@@ -2131,7 +2143,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
float accumulatedTranslationX = 0;
float translateXToMiddle = 0;
if (enableGridOnlyOverview() && mActivity.getDeviceProfile().isTablet) {
if (enableGridOnlyOverview() && mContainer.getDeviceProfile().isTablet) {
translateXToMiddle = mIsRtl
? mLastComputedCarouselTaskSize.right - mLastComputedTaskSize.right
: mLastComputedCarouselTaskSize.left - mLastComputedTaskSize.left;
@@ -2153,7 +2165,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
public void getTaskSize(Rect outRect) {
mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect,
mSizeStrategy.calculateTaskSize(mContainer, mContainer.getDeviceProfile(), outRect,
getPagedOrientationHandler());
}
@@ -2202,7 +2214,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
/** Gets the task size for modal state. */
public void getModalTaskSize(Rect outRect) {
mSizeStrategy.calculateModalTaskSize(mActivity, mActivity.getDeviceProfile(), outRect,
mSizeStrategy.calculateModalTaskSize(mContainer, mContainer.getDeviceProfile(), outRect,
getPagedOrientationHandler());
}
@@ -2268,7 +2280,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
@Override
protected int getDestinationPage(int scaledScroll) {
if (!mActivity.getDeviceProfile().isTablet) {
if (!mContainer.getDeviceProfile().isTablet) {
return super.getDestinationPage(scaledScroll);
}
if (!isPageScrollsInitialized()) {
@@ -2418,7 +2430,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
public void startHome() {
startHome(mActivity.isStarted());
startHome(mContainer.isStarted());
}
public void startHome(boolean animated) {
@@ -2431,6 +2443,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
/** Returns whether user can start home based on state in {@link OverviewCommandHelper}. */
protected abstract boolean canStartHomeSafely();
public abstract StateManager<STATE_TYPE> getStateManager();
public void reset() {
setCurrentTask(-1);
mCurrentPageScrollDiff = 0;
@@ -2570,6 +2584,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
*/
public void onGestureAnimationStart(
Task[] runningTasks, RotationTouchHelper rotationTouchHelper) {
Log.d(TAG, "onGestureAnimationStart");
mActiveGestureRunningTasks = runningTasks;
// This needs to be called before the other states are set since it can create the task view
if (mOrientationState.setGestureActive(true)) {
@@ -2608,7 +2623,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
AnimatorSet pa = setRecentsChangedOrientation(true);
pa.addListener(AnimatorListeners.forSuccessCallback(() -> {
setLayoutRotation(newRotation, mOrientationState.getDisplayRotation());
mActivity.getDragLayer().recreateControllers();
mContainer.getDragLayer().recreateControllers();
setRecentsChangedOrientation(false).start();
}));
pa.start();
@@ -2637,7 +2652,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
if (!shouldRotateMenuForFakeRotation) {
return;
}
TaskMenuView tv = (TaskMenuView) getTopOpenViewWithType(mActivity, TYPE_TASK_MENU);
TaskMenuView tv = (TaskMenuView) getTopOpenViewWithType(mContainer, TYPE_TASK_MENU);
if (tv != null) {
// Rotation is supported on phone (details at b/254198019#comment4)
tv.onRotationChanged();
@@ -2658,7 +2673,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
BaseState<?> endState = mSizeStrategy.stateFromGestureEndTarget(endTarget);
if (endState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile())) {
if (endState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile())) {
TaskView runningTaskView = getRunningTaskView();
float runningTaskPrimaryGridTranslation = 0;
float runningTaskSecondaryGridTranslation = 0;
@@ -2921,7 +2936,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
return;
}
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
DeviceProfile deviceProfile = mContainer.getDeviceProfile();
int taskTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
int topRowWidth = 0;
@@ -3245,7 +3260,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
int secondaryTaskDimension = getPagedOrientationHandler().getSecondaryDimension(taskView);
int verticalFactor = getPagedOrientationHandler().getSecondaryTranslationDirectionFactor();
ResourceProvider rp = DynamicResource.provider(mActivity);
ResourceProvider rp = DynamicResource.provider(mContainer);
SpringProperty sp = new SpringProperty(SpringProperty.FLAG_CAN_SPRING_ON_START)
.setDampingRatio(rp.getFloat(R.dimen.dismiss_task_trans_y_damping_ratio))
.setStiffness(rp.getFloat(R.dimen.dismiss_task_trans_y_stiffness));
@@ -3273,10 +3288,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
*/
private void createInitialSplitSelectAnimation(PendingAnimation anim) {
getPagedOrientationHandler().getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
mSplitPlaceholderInset, mActivity.getDeviceProfile(),
mSplitPlaceholderInset, mContainer.getDeviceProfile(),
mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
SplitAnimationTimings timings =
AnimUtils.getDeviceOverviewToSplitTimings(mActivity.getDeviceProfile().isTablet);
AnimUtils.getDeviceOverviewToSplitTimings(mContainer.getDeviceProfile().isTablet);
RectF startingTaskRect = new RectF();
safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView());
@@ -3292,7 +3307,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
timings.getIconFadeEndOffset()));
}
FloatingTaskView firstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
FloatingTaskView firstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mContainer,
splitAnimInitProps.getOriginalView(),
splitAnimInitProps.getOriginalBitmap(),
splitAnimInitProps.getIconDrawable(), startingTaskRect);
@@ -3304,13 +3319,13 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// Allow user to click staged app to launch into fullscreen
firstFloatingTaskView.setOnClickListener(view ->
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(),
@@ -3436,7 +3451,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
boolean isClearAllHidden = isClearAllHidden();
boolean snapToLastTask = false;
boolean isLeftRightSplit =
mActivity.getDeviceProfile().isLeftRightSplit && isSplitSelectionActive();
mContainer.getDeviceProfile().isLeftRightSplit && isSplitSelectionActive();
TaskView lastGridTaskView = showAsGrid ? getLastGridTaskView() : null;
int currentPageScroll = getScrollForPage(mCurrentPage);
int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
@@ -3481,7 +3496,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// and adjust accordingly to the new shortTotalCompensation after dismiss.
int newClearAllShortTotalWidthTranslation = 0;
if (longRowWidth < mLastComputedGridSize.width()) {
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
DeviceProfile deviceProfile = mContainer.getDeviceProfile();
newClearAllShortTotalWidthTranslation =
(mIsRtl
? mLastComputedTaskSize.right
@@ -3568,7 +3583,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
SplitAnimationTimings splitTimings =
AnimUtils.getDeviceOverviewToSplitTimings(mActivity.getDeviceProfile().isTablet);
AnimUtils.getDeviceOverviewToSplitTimings(mContainer.getDeviceProfile().isTablet);
int distanceFromDismissedTask = 0;
for (int i = 0; i < count; i++) {
@@ -3777,7 +3792,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
announceForAccessibility(
getResources().getString(R.string.task_view_closed));
mActivity.getStatsLogManager().logger()
mContainer.getStatsLogManager().logger()
.withItemInfo(dismissedTaskView.getItemInfo())
.log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
}
@@ -3943,7 +3958,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// Update various scroll-dependent UI.
dispatchScrollChanged();
updateActionsViewFocusedScroll();
if (isClearAllHidden() && !mActivity.getDeviceProfile().isTablet) {
if (isClearAllHidden() && !mContainer.getDeviceProfile().isTablet) {
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING,
false);
}
@@ -4165,7 +4180,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
@SuppressWarnings("unused")
private void dismissAllTasks(View view) {
runDismissAnimation(createAllTasksDismissAnimation(DISMISS_TASK_DURATION));
mActivity.getStatsLogManager().logger().log(LAUNCHER_TASK_CLEAR_ALL);
mContainer.getStatsLogManager().logger().log(LAUNCHER_TASK_CLEAR_ALL);
}
private void dismissCurrentTask() {
@@ -4294,7 +4309,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* Updates {@link RecentsOrientedState}'s cached RecentsView rotation.
*/
public void updateRecentsRotation() {
final int rotation = mActivity.getDisplay().getRotation();
final int rotation = TraceHelper.allowIpcs(
"RecentsView.updateRecentsRotation", () -> mContainer.getDisplay().getRotation());
mOrientationState.setRecentsRotation(rotation);
}
@@ -4408,14 +4424,14 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
} else {
// Only update pivot when it is tablet and not in grid yet, so the pivot is correct
// for non-current tasks when swiping up to overview
if (enableGridOnlyOverview() && mActivity.getDeviceProfile().isTablet
if (enableGridOnlyOverview() && mContainer.getDeviceProfile().isTablet
&& !mOverviewGridEnabled) {
mTempRect.set(mLastComputedCarouselTaskSize);
} else {
mTempRect.set(mLastComputedTaskSize);
}
getPagedViewOrientedState().getFullScreenScaleAndPivot(mTempRect,
mActivity.getDeviceProfile(), mTempPointF);
mContainer.getDeviceProfile(), mTempPointF);
}
setPivotX(mTempPointF.x);
setPivotY(mTempPointF.y);
@@ -4515,7 +4531,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
TaskView taskView = (TaskView) child;
outRect.offset(taskView.getPersistentTranslationX(),
taskView.getPersistentTranslationY());
outRect.top += mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
outRect.top += mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
mTempMatrix.reset();
float persistentScale = taskView.getPersistentScale();
@@ -4627,7 +4643,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
if (isTopShift) {
distanceToOffscreen = -taskPosition.bottom;
} else if (isBottomShift) {
distanceToOffscreen = mActivity.getDeviceProfile().heightPx - taskPosition.top;
distanceToOffscreen = mContainer.getDeviceProfile().heightPx - taskPosition.top;
}
return distanceToOffscreen * offsetProgress;
}
@@ -4683,7 +4699,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
*/
public void initiateSplitSelect(TaskView taskView) {
int defaultSplitPosition = getPagedOrientationHandler()
.getDefaultSplitPosition(mActivity.getDeviceProfile());
.getDefaultSplitPosition(mContainer.getDeviceProfile());
initiateSplitSelect(taskView, defaultSplitPosition, LAUNCHER_OVERVIEW_ACTIONS_SPLIT);
}
@@ -4748,7 +4764,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
TaskThumbnailView thumbnail = taskIdAttributeContainer.getThumbnailView();
mSplitSelectStateController.getSplitAnimationController()
.addInitialSplitFromPair(taskIdAttributeContainer, builder,
mActivity.getDeviceProfile(),
mContainer.getDeviceProfile(),
mSplitHiddenTaskView.getWidth(), mSplitHiddenTaskView.getHeight(),
primaryTaskSelected);
builder.addOnFrameCallback(() ->{
@@ -4816,14 +4832,14 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
Rect firstTaskStartingBounds = new Rect();
Rect firstTaskEndingBounds = mTempRect;
boolean isTablet = mActivity.getDeviceProfile().isTablet;
boolean isTablet = mContainer.getDeviceProfile().isTablet;
SplitAnimationTimings timings = AnimUtils.getDeviceSplitToConfirmTimings(isTablet);
PendingAnimation pendingAnimation = new PendingAnimation(timings.getDuration());
int halfDividerSize = getResources()
.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
getPagedOrientationHandler().getFinalSplitPlaceholderBounds(halfDividerSize,
mActivity.getDeviceProfile(),
mContainer.getDeviceProfile(),
mSplitSelectStateController.getActiveSplitStagePosition(), firstTaskEndingBounds,
secondTaskEndingBounds);
@@ -4836,7 +4852,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
safeRemoveDragLayerView(mSecondFloatingTaskView);
mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity, secondView,
mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mContainer, secondView,
thumbnail, drawable, secondTaskStartingBounds);
mSecondFloatingTaskView.setAlpha(1);
mSecondFloatingTaskView.addConfirmAnimation(pendingAnimation, secondTaskStartingBounds,
@@ -4884,7 +4900,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
mSecondFloatingTaskView = null;
mSplitSelectSource = null;
mSplitSelectStateController.getSplitAnimationController()
.removeSplitInstructionsView(mActivity);
.removeSplitInstructionsView(mContainer);
}
if (mSecondSplitHiddenView != null) {
@@ -4905,7 +4921,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
if (mSplitHiddenTaskViewIndex == -1) {
return;
}
if (!mActivity.getDeviceProfile().isTablet) {
if (!mContainer.getDeviceProfile().isTablet) {
int pageToSnapTo = mCurrentPage;
if (mSplitHiddenTaskViewIndex <= pageToSnapTo) {
pageToSnapTo += 1;
@@ -4927,7 +4943,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
private void safeRemoveDragLayerView(@Nullable View viewToRemove) {
if (viewToRemove != null) {
mActivity.getDragLayer().removeView(viewToRemove);
mContainer.getDragLayer().removeView(viewToRemove);
}
}
@@ -4936,11 +4952,11 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* Note that the translation can be its primary or secondary dimension.
*/
public float getSplitSelectTranslation() {
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
DeviceProfile deviceProfile = mContainer.getDeviceProfile();
RecentsPagedOrientationHandler orientationHandler = getPagedOrientationHandler();
int splitPosition = getSplitSelectController().getActiveSplitStagePosition();
int splitPlaceholderSize =
mActivity.getResources().getDimensionPixelSize(R.dimen.split_placeholder_size);
mContainer.getResources().getDimensionPixelSize(R.dimen.split_placeholder_size);
int direction = orientationHandler.getSplitTranslationDirectionFactor(
splitPosition, deviceProfile);
@@ -4963,7 +4979,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
protected void onRotateInSplitSelectionState() {
getPagedOrientationHandler().getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
mSplitPlaceholderInset, mActivity.getDeviceProfile(),
mSplitPlaceholderInset, mContainer.getDeviceProfile(),
mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
mTempRectF.set(mTempRect);
FloatingTaskView firstFloatingTaskView =
@@ -4975,7 +4991,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
Pair<FloatProperty<RecentsView>, FloatProperty<RecentsView>> 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);
@@ -5108,10 +5124,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* Returns the scale up required on the view, so that it coves the screen completely
*/
public float getMaxScaleForFullScreen() {
if (enableGridOnlyOverview() && mActivity.getDeviceProfile().isTablet
if (enableGridOnlyOverview() && mContainer.getDeviceProfile().isTablet
&& !mOverviewGridEnabled) {
if (mLastComputedCarouselTaskSize.isEmpty()) {
mSizeStrategy.calculateCarouselTaskSize(mActivity, mActivity.getDeviceProfile(),
mSizeStrategy.calculateCarouselTaskSize(mContainer, mContainer.getDeviceProfile(),
mLastComputedCarouselTaskSize, getPagedOrientationHandler());
}
mTempRect.set(mLastComputedCarouselTaskSize);
@@ -5122,7 +5138,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
mTempRect.set(mLastComputedTaskSize);
}
return getPagedViewOrientedState().getFullScreenScaleAndPivot(
mTempRect, mActivity.getDeviceProfile(), mTempPointF);
mTempRect, mContainer.getDeviceProfile(), mTempPointF);
}
public PendingAnimation createTaskLaunchAnimation(
@@ -5148,10 +5164,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// Once we pass a certain threshold, update the sysui flags to match the target
// tasks' flags
if (animator.getAnimatedFraction() > 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
@@ -5173,7 +5189,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
DepthController depthController = getDepthController();
if (depthController != null) {
ObjectAnimator depthAnimator = ObjectAnimator.ofFloat(depthController.stateDepth,
MULTI_PROPERTY_VALUE, BACKGROUND_APP.getDepth(mActivity));
MULTI_PROPERTY_VALUE, BACKGROUND_APP.getDepth(mContainer));
anim.play(depthAnimator);
}
anim.play(ObjectAnimator.ofFloat(this, TASK_THUMBNAIL_SPLASH_ALPHA, 0f, 1f));
@@ -5206,7 +5222,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
Task task = tv.getTask();
if (task != null) {
mActivity.getStatsLogManager().logger().withItemInfo(tv.getItemInfo())
mContainer.getStatsLogManager().logger().withItemInfo(tv.getItemInfo())
.log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
}
} else {
@@ -5333,7 +5349,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator();
tvs.setOrientationState(mOrientationState);
tvs.setDp(mActivity.getDeviceProfile());
tvs.setDp(mContainer.getDeviceProfile());
tvs.recentsViewScale.value = 1;
});
@@ -5388,7 +5404,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// Notify the SysUI to use fade-in animation when entering PiP from live tile.
final SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.get(getContext());
systemUiProxy.setPipAnimationTypeToAlpha();
systemUiProxy.setShelfHeight(true, mActivity.getDeviceProfile().hotseatBarSizePx);
systemUiProxy.setShelfHeight(true, mContainer.getDeviceProfile().hotseatBarSizePx);
// Transaction to hide the task to avoid flicker for entering PiP from split-screen.
// See also {@link AbsSwipeUpHandler#maybeFinishSwipeToHome}.
PictureInPictureSurfaceTransaction tx =
@@ -5414,6 +5430,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* Called when a running recents animation has finished or canceled.
*/
public void onRecentsAnimationComplete() {
Log.d(TAG, "onRecentsAnimationComplete - mRecentsAnimationController: "
+ mRecentsAnimationController);
// At this point, the recents animation is not running and if the animation was canceled
// by a display rotation then reset this state to show the screenshot
setRunningTaskViewShowScreenshot(true);
@@ -5457,7 +5475,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
protected int getClearAllExtraPageSpacing() {
return showAsGrid()
? Math.max(mActivity.getDeviceProfile().overviewGridSideMargin - mPageSpacing, 0)
? Math.max(mContainer.getDeviceProfile().overviewGridSideMargin - mPageSpacing, 0)
: 0;
}
@@ -5906,7 +5924,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
return mTaskOverlayFactory;
}
public BaseActivityInterface getSizeStrategy() {
public BaseContainerInterface getSizeStrategy() {
return mSizeStrategy;
}
@@ -5938,7 +5956,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
requireTaskViewAt(i).setColorTint(mColorTint, mTintingColor);
}
Drawable scrimBg = mActivity.getScrimView().getBackground();
Drawable scrimBg = mContainer.getScrimView().getBackground();
if (scrimBg != null) {
if (tintAmount == 0f) {
scrimBg.setTintList(null);
@@ -5957,8 +5975,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
/** Returns {@code true} if the overview tasks are displayed as a grid. */
public boolean showAsGrid() {
return mOverviewGridEnabled || (mCurrentGestureEndTarget != null
&& mSizeStrategy.stateFromGestureEndTarget(
mCurrentGestureEndTarget).displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
&& mSizeStrategy.stateFromGestureEndTarget(mCurrentGestureEndTarget)
.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
}
private boolean showAsFullscreen() {
@@ -6124,7 +6142,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
}
private static class PinnedStackAnimationListener<T extends BaseActivity> extends
private static class PinnedStackAnimationListener<T extends RecentsViewContainer> extends
IPipAnimationListener.Stub {
@Nullable
private T mActivity;
@@ -6190,7 +6208,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
public void updateLocusId() {
String locusId = "Overview";
if (mOverviewStateEnabled && mActivity.isStarted()) {
if (mOverviewStateEnabled && mContainer.isStarted()) {
locusId += "|ENABLED";
} else {
locusId += "|DISABLED";
@@ -6198,7 +6216,28 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
final LocusId id = new LocusId(locusId);
// Set locus context is a binder call, don't want it to happen during a transition
UI_HELPER_EXECUTOR.post(() -> mActivity.setLocusContext(id, Bundle.EMPTY));
UI_HELPER_EXECUTOR.post(() -> mContainer.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 {
@@ -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<SplitInstructionsView> 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()
);
@@ -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) {
@@ -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<T : BaseDraggingActivity> : ArrowPopup<T> {
class TaskMenuViewWithArrow<T> : ArrowPopup<T> where T : RecentsViewContainer, T : Context {
companion object {
const val TAG = "TaskMenuViewWithArrow"
fun showForTask(
fun <T> showForTask(
taskContainer: TaskIdAttributeContainer,
alignedOptionIndex: Int = 0
): Boolean {
val activity =
BaseDraggingActivity.fromContext<BaseDraggingActivity>(
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<T>
return taskMenuViewWithArrow.populateAndShowForTask(taskContainer, alignedOptionIndex)
}
@@ -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(),
@@ -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();
@@ -487,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;
@@ -613,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),
@@ -813,13 +816,19 @@ 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();
mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
RunnableList callbackList = launchTasks();
Log.d("b/310064698", mTask + " - onClick - callbackList: " + callbackList);
if (callbackList != null) {
callbackList.add(() -> Log.d("b/310064698", mTask + " - onClick - launchCompleted"));
}
mContainer.getStatsLogManager().logger().withItemInfo(getItemInfo())
.log(LAUNCHER_TASK_LAUNCH_TAP);
}
@@ -861,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()
@@ -919,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) {
@@ -1022,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
@@ -1133,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);
}
@@ -1147,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,
@@ -1201,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
@@ -1218,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();
}
@@ -1325,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 {
@@ -1682,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);
}
@@ -1719,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();
@@ -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<LauncherState> = 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()
@@ -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<QuickstepLauncher> {
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);
@@ -0,0 +1,140 @@
/*
* 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.uioverrides.QuickstepLauncher
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: QuickstepLauncher = 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<LauncherRecentsView>()).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<Runnable>(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)
}
}
@@ -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<QuickstepLauncher> {
private static final String CALCULATOR_APP_PACKAGE =
resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
@@ -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);
}
}
}
@@ -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
+1
View File
@@ -78,6 +78,7 @@
<string name="launcher_restore_event_logger_class" translatable="false"></string>
<!-- Used for determining category of a widget presented in widget recommendations. -->
<string name="widget_recommendation_category_provider_class" translatable="false"></string>
<string name="api_wrapper_class" translatable="false"></string>
<!-- Default packages -->
<string name="wallpaper_picker_package" translatable="false"></string>

Some files were not shown because too many files have changed in this diff Show More