summaryrefslogtreecommitdiffstats
path: root/quickstep/recents_ui_overrides/src
diff options
context:
space:
mode:
authorLuca Stefani <luca.stefani.ge1@gmail.com>2020-03-07 13:43:59 +0100
committerLuca Stefani <luca.stefani.ge1@gmail.com>2020-03-07 13:43:59 +0100
commit0007a046cf4f4bfed563aa52ffab9ec5e94ee6f0 (patch)
tree2bc4acf2f54df560a34dcc7b7844d9d18cc58131 /quickstep/recents_ui_overrides/src
parent744d192669a148bde24d36bef02deb05c2f7a1fa (diff)
parent02826bbe04d9dc1e6111f5d6ffd8706ac1f8f908 (diff)
downloadpackages_apps_Trebuchet-0007a046cf4f4bfed563aa52ffab9ec5e94ee6f0.tar.gz
packages_apps_Trebuchet-0007a046cf4f4bfed563aa52ffab9ec5e94ee6f0.tar.bz2
packages_apps_Trebuchet-0007a046cf4f4bfed563aa52ffab9ec5e94ee6f0.zip
Merge tag 'android-10.0.0_r31' into HEAD
Android 10.0.0 release 31 * tag 'android-10.0.0_r31': (218 commits) Increase drag distance threshold when drag starts from deep press Fix shortcut componentname in workspace layout logging Fix shortcut componentname in workspace layout logging perform accessbility focus when the recyclerview doesn't gain focus after fragment replacement in SettingsActivity Persist predicted items when dragged to workspace Import translations. DO NOT MERGE Import translations. DO NOT MERGE Align badging logic with platform IconDrawableFactory. Fix bug where icon remains invisible after returning home. Fix quick switch from home biased towards returning home Fix recents scale sometimes lagging behind window scale Fix folder open/close animation when grid size is small. fix custom shortcut test Improve quick switch from home by tracking both x and y motion Move shelf peeking anim code to ShelfPeekAnim class Fix folder available height calculation Tapl: AllApps: ensuring a minimal vertical size of an icon Enable a11y scrolling with item drag disable custom shortcut test in oop include predicted_rank in app launch logging ... Change-Id: Id824c350cd133c4c8fa91de0f8793faed9003393
Diffstat (limited to 'quickstep/recents_ui_overrides/src')
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java72
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java15
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java113
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java14
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java30
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java6
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java15
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java29
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java75
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java26
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java473
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java8
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java11
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java30
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java4
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java41
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java71
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java22
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java21
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java6
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java11
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java10
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java113
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java24
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java2
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java16
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java1
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java17
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java11
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java47
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java8
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java5
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java12
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java105
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java66
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java12
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java4
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java106
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsExtraViewContainer.java54
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java192
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java2
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java39
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java1
43 files changed, 1498 insertions, 442 deletions
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 711594386..114fd8e10 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -17,9 +17,19 @@
package com.android.launcher3;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.LauncherState.BACKGROUND_APP;
+import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
@@ -27,10 +37,17 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.LauncherState.ScaleAndTranslation;
+import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.SpringAnimationBuilder;
import com.android.quickstep.util.ClipAnimationHelper;
@@ -38,9 +55,6 @@ import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
/**
* A {@link QuickstepAppTransitionManagerImpl} that also implements recents transitions from
* {@link RecentsView}.
@@ -50,6 +64,9 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
public static final int INDEX_SHELF_ANIM = 0;
public static final int INDEX_RECENTS_FADE_ANIM = 1;
public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = 2;
+ public static final int INDEX_PAUSE_TO_OVERVIEW_ANIM = 3;
+
+ public static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300;
public LauncherAppTransitionManagerImpl(Context context) {
super(context);
@@ -138,14 +155,43 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
@Override
public int getStateElementAnimationsCount() {
- return 3;
+ return 4;
}
@Override
public Animator createStateElementAnimation(int index, float... values) {
switch (index) {
- case INDEX_SHELF_ANIM:
- return mLauncher.getAllAppsController().createSpringAnimation(values);
+ case INDEX_SHELF_ANIM: {
+ AllAppsTransitionController aatc = mLauncher.getAllAppsController();
+ Animator springAnim = aatc.createSpringAnimation(values);
+
+ if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+ // Translate hotseat with the shelf until reaching overview.
+ float overviewProgress = OVERVIEW.getVerticalProgress(mLauncher);
+ ScaleAndTranslation sat = OVERVIEW.getHotseatScaleAndTranslation(mLauncher);
+ float shiftRange = aatc.getShiftRange();
+ if (values.length == 1) {
+ values = new float[] {aatc.getProgress(), values[0]};
+ }
+ ValueAnimator hotseatAnim = ValueAnimator.ofFloat(values);
+ hotseatAnim.addUpdateListener(anim -> {
+ float progress = (Float) anim.getAnimatedValue();
+ if (progress >= overviewProgress || mLauncher.isInState(BACKGROUND_APP)) {
+ float hotseatShift = (progress - overviewProgress) * shiftRange;
+ mLauncher.getHotseat().setTranslationY(hotseatShift + sat.translationY);
+ }
+ });
+ hotseatAnim.setInterpolator(LINEAR);
+ hotseatAnim.setDuration(springAnim.getDuration());
+
+ AnimatorSet anim = new AnimatorSet();
+ anim.play(hotseatAnim);
+ anim.play(springAnim);
+ return anim;
+ }
+
+ return springAnim;
+ }
case INDEX_RECENTS_FADE_ANIM:
return ObjectAnimator.ofFloat(mLauncher.getOverviewPanel(),
RecentsView.CONTENT_ALPHA, values);
@@ -155,6 +201,20 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
.setStiffness(250)
.setValues(values)
.build(mLauncher);
+ case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ builder.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
+ if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+ builder.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
+ builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
+ }
+ LauncherStateManager stateManager = mLauncher.getStateManager();
+ return stateManager.createAtomicAnimation(
+ stateManager.getCurrentStableState(), OVERVIEW, builder,
+ ANIM_ALL, ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW);
+ }
+
default:
return super.createStateElementAnimation(index, values);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
index 4ecc39cf6..65e69b604 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
@@ -17,6 +17,8 @@ package com.android.launcher3.appprediction;
import static android.content.pm.PackageManager.MATCH_INSTANT;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -30,8 +32,12 @@ import android.os.Message;
import android.util.ArrayMap;
import android.util.Log;
+import androidx.annotation.MainThread;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.LauncherIcons;
@@ -45,11 +51,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import androidx.annotation.MainThread;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
-
/**
* Utility class which loads and caches predicted items like instant apps and shortcuts, before
* they can be displayed on the UI
@@ -77,7 +78,7 @@ public class DynamicItemCache {
public DynamicItemCache(Context context, Runnable onUpdateCallback) {
mContext = context;
- mWorker = new Handler(LauncherModel.getWorkerLooper(), this::handleWorkerMessage);
+ mWorker = new Handler(MODEL_EXECUTOR.getLooper(), this::handleWorkerMessage);
mUiHandler = new Handler(Looper.getMainLooper(), this::handleUiMessage);
mInstantAppResolver = InstantAppResolver.newInstance(context);
mOnUpdateCallback = onUpdateCallback;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
index 24fc61bef..4c7943b10 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +16,7 @@
package com.android.launcher3.appprediction;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.annotation.TargetApi;
import android.app.prediction.AppPredictionContext;
@@ -34,19 +35,25 @@ import android.os.UserHandle;
import android.util.Log;
import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.model.AppLaunchTracker;
-import com.android.launcher3.util.UiThreadHelper;
+import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
+import com.android.systemui.plugins.AppLaunchEventsPlugin;
+import com.android.systemui.plugins.PluginListener;
-import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
+import java.util.ArrayList;
+import java.util.List;
/**
* Subclass of app tracker which publishes the data to the prediction engine and gets back results.
*/
@TargetApi(Build.VERSION_CODES.Q)
-public class PredictionAppTracker extends AppLaunchTracker {
+public class PredictionAppTracker extends AppLaunchTracker
+ implements PluginListener<AppLaunchEventsPlugin> {
private static final String TAG = "PredictionAppTracker";
private static final boolean DBG = false;
@@ -58,6 +65,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
protected final Context mContext;
private final Handler mMessageHandler;
+ private final List<AppLaunchEventsPlugin> mAppLaunchEventsPluginsList;
// Accessed only on worker thread
private AppPredictor mHomeAppPredictor;
@@ -65,10 +73,14 @@ public class PredictionAppTracker extends AppLaunchTracker {
public PredictionAppTracker(Context context) {
mContext = context;
- mMessageHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleMessage);
+ mMessageHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::handleMessage);
InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged);
mMessageHandler.sendEmptyMessage(MSG_INIT);
+
+ mAppLaunchEventsPluginsList = new ArrayList<>();
+ PluginManagerWrapper.INSTANCE.get(context)
+ .addPluginListener(this, AppLaunchEventsPlugin.class, true);
}
@UiThread
@@ -96,7 +108,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
AppPredictionManager apm = mContext.getSystemService(AppPredictionManager.class);
if (apm == null) {
- return null;
+ return null;
}
AppPredictor predictor = apm.createAppPredictionSession(
@@ -116,7 +128,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
*/
@WorkerThread
@Nullable
- public Bundle getAppPredictionContextExtras(Client client){
+ public Bundle getAppPredictionContextExtras(Client client) {
return null;
}
@@ -128,7 +140,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
destroy();
// Initialize the clients
- int count = InvariantDeviceProfile.INSTANCE.get(mContext).numColumns;
+ int count = InvariantDeviceProfile.INSTANCE.get(mContext).numAllAppsColumns;
mHomeAppPredictor = createPredictor(Client.HOME, count);
mRecentsOverviewPredictor = createPredictor(Client.OVERVIEW, count);
return true;
@@ -167,37 +179,98 @@ public class PredictionAppTracker extends AppLaunchTracker {
if (DBG) {
Log.d(TAG, String.format("Sent immediate message to update %s", client));
}
+
+ // Relay onReturnedToHome to every plugin.
+ mAppLaunchEventsPluginsList.forEach(AppLaunchEventsPlugin::onReturnedToHome);
}
@Override
@UiThread
public void onStartShortcut(String packageName, String shortcutId, UserHandle user,
- String container) {
+ String container) {
// TODO: Use the full shortcut info
- AppTarget target = new AppTarget
- .Builder(new AppTargetId("shortcut:" + shortcutId), packageName, user)
- .setClassName(shortcutId)
- .build();
+ AppTarget target = new AppTarget.Builder(
+ new AppTargetId("shortcut:" + shortcutId), packageName, user)
+ .setClassName(shortcutId)
+ .build();
+
sendLaunch(target, container);
+
+ // Relay onStartShortcut info to every connected plugin.
+ mAppLaunchEventsPluginsList
+ .forEach(plugin -> plugin.onStartShortcut(
+ packageName,
+ shortcutId,
+ user,
+ container != null ? container : CONTAINER_DEFAULT)
+ );
+
}
@Override
@UiThread
public void onStartApp(ComponentName cn, UserHandle user, String container) {
if (cn != null) {
- AppTarget target = new AppTarget
- .Builder(new AppTargetId("app:" + cn), cn.getPackageName(), user)
- .setClassName(cn.getClassName())
- .build();
+ AppTarget target = new AppTarget.Builder(
+ new AppTargetId("app:" + cn), cn.getPackageName(), user)
+ .setClassName(cn.getClassName())
+ .build();
sendLaunch(target, container);
+
+ // Relay onStartApp to every connected plugin.
+ mAppLaunchEventsPluginsList
+ .forEach(plugin -> plugin.onStartApp(
+ cn,
+ user,
+ container != null ? container : CONTAINER_DEFAULT)
+ );
}
}
+ @Override
@UiThread
- private void sendLaunch(AppTarget target, String container) {
- AppTargetEvent event = new AppTargetEvent.Builder(target, AppTargetEvent.ACTION_LAUNCH)
+ public void onDismissApp(ComponentName cn, UserHandle user, String container) {
+ if (cn == null) return;
+ AppTarget target = new AppTarget.Builder(
+ new AppTargetId("app: " + cn), cn.getPackageName(), user)
+ .setClassName(cn.getClassName())
+ .build();
+ sendDismiss(target, container);
+
+ // Relay onDismissApp to every connected plugin.
+ mAppLaunchEventsPluginsList
+ .forEach(plugin -> plugin.onDismissApp(
+ cn,
+ user,
+ container != null ? container : CONTAINER_DEFAULT)
+ );
+ }
+
+ @UiThread
+ private void sendEvent(AppTarget target, String container, int eventId) {
+ AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
.setLaunchLocation(container == null ? CONTAINER_DEFAULT : container)
.build();
Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget();
}
+
+ @UiThread
+ private void sendLaunch(AppTarget target, String container) {
+ sendEvent(target, container, AppTargetEvent.ACTION_LAUNCH);
+ }
+
+ @UiThread
+ private void sendDismiss(AppTarget target, String container) {
+ sendEvent(target, container, AppTargetEvent.ACTION_DISMISS);
+ }
+
+ @Override
+ public void onPluginConnected(AppLaunchEventsPlugin appLaunchEventsPlugin, Context context) {
+ mAppLaunchEventsPluginsList.add(appLaunchEventsPlugin);
+ }
+
+ @Override
+ public void onPluginDisconnected(AppLaunchEventsPlugin appLaunchEventsPlugin) {
+ mAppLaunchEventsPluginsList.remove(appLaunchEventsPlugin);
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
index 0c7ba9c95..f82af62aa 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -43,6 +43,7 @@ import com.android.launcher3.ItemInfo;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.allapps.AllAppsStore;
@@ -92,7 +93,7 @@ public class PredictionRowView extends LinearLayout implements
private final Launcher mLauncher;
private final PredictionUiStateManager mPredictionUiStateManager;
- private final int mNumPredictedAppsPerRow;
+ private int mNumPredictedAppsPerRow;
// The set of predicted app component names
private final List<ComponentKeyMapper> mPredictedAppComponents = new ArrayList<>();
@@ -128,7 +129,7 @@ public class PredictionRowView extends LinearLayout implements
mFocusHelper = new SimpleFocusIndicatorHelper(this);
- mNumPredictedAppsPerRow = LauncherAppState.getIDP(context).numColumns;
+ mNumPredictedAppsPerRow = LauncherAppState.getIDP(context).numAllAppsColumns;
mLauncher = Launcher.getLauncher(context);
mLauncher.addOnDeviceProfileChangeListener(this);
@@ -226,6 +227,7 @@ public class PredictionRowView extends LinearLayout implements
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
+ mNumPredictedAppsPerRow = dp.inv.numAllAppsColumns;
removeAllViews();
applyPredictionApps();
}
@@ -274,14 +276,14 @@ public class PredictionRowView extends LinearLayout implements
boolean predictionsEnabled = predictionCount > 0;
if (predictionsEnabled != mPredictionsEnabled) {
mPredictionsEnabled = predictionsEnabled;
- mLauncher.reapplyUi();
+ mLauncher.reapplyUi(false /* cancelCurrentAnimation */);
updateVisibility();
}
mParent.onHeightUpdated();
}
private List<ItemInfoWithIcon> processPredictedAppComponents(List<ComponentKeyMapper> components) {
- if (getAppsStore().getApps().isEmpty()) {
+ if (getAppsStore().getApps().length == 0) {
// Apps have not been bound yet.
return Collections.emptyList();
}
@@ -290,7 +292,9 @@ public class PredictionRowView extends LinearLayout implements
for (ComponentKeyMapper mapper : components) {
ItemInfoWithIcon info = mapper.getApp(getAppsStore());
if (info != null) {
- predictedApps.add(info);
+ ItemInfoWithIcon predictedApp = info.clone();
+ predictedApp.container = LauncherSettings.Favorites.CONTAINER_PREDICTION;
+ predictedApps.add(predictedApp);
} else {
if (FeatureFlags.IS_DOGFOOD_BUILD) {
Log.e(TAG, "Predicted app not found: " + mapper);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
index 1a59770a0..9c661074e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
@@ -25,12 +25,16 @@ import android.app.prediction.AppTarget;
import android.content.ComponentName;
import android.content.Context;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.AppInfo;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
+import com.android.launcher3.ItemInfo;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.StateListener;
import com.android.launcher3.Utilities;
@@ -39,12 +43,14 @@ import com.android.launcher3.allapps.AllAppsStore.OnUpdateListener;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.MainThreadInitializedObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.IntStream;
/**
* Handler responsible to updating the UI due to predicted apps changes. Operations:
@@ -322,6 +328,30 @@ public class PredictionUiStateManager implements StateListener, ItemInfoUpdateRe
return mCurrentState;
}
+ /**
+ * Fill in predicted_rank field based on app prediction.
+ * Only applicable when {@link ItemInfo#itemType} is one of the followings:
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_DEEP_SHORTCUT}
+ */
+ public static void fillInPredictedRank(
+ @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target) {
+ final PredictionUiStateManager manager = PredictionUiStateManager.INSTANCE.getNoCreate();
+ if (manager == null || itemInfo.getTargetComponent() == null || itemInfo.user == null
+ || (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+ && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
+ && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)) {
+ return;
+ }
+ final ComponentKey k = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
+ final List<ComponentKeyMapper> predictedApps = manager.getCurrentState().apps;
+ IntStream.range(0, predictedApps.size())
+ .filter((i) -> k.equals(predictedApps.get(i).getComponentKey()))
+ .findFirst()
+ .ifPresent((rank) -> target.predictedRank = rank);
+ }
+
public static class PredictionState {
public boolean isEnabled;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
index 596bc4f44..cac170c68 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
@@ -28,17 +28,17 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
import com.android.launcher3.uioverrides.touchcontrollers.NavBarToHomeTouchController;
+import com.android.launcher3.uioverrides.touchcontrollers.NoButtonQuickSwitchTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.OverviewToAllAppsTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
-import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.QuickSwitchTouchController;
+import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TransposedQuickSwitchTouchController;
import com.android.launcher3.util.TouchController;
@@ -145,7 +145,7 @@ public abstract class RecentsUiFactory {
ArrayList<TouchController> list = new ArrayList<>();
list.add(launcher.getDragController());
if (mode == NO_BUTTON) {
- list.add(new QuickSwitchTouchController(launcher));
+ list.add(new NoButtonQuickSwitchTouchController(launcher));
list.add(new NavBarToHomeTouchController(launcher));
list.add(new FlingAndHoldTouchController(launcher));
} else {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index 50cfac8e4..63ac52804 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -19,7 +19,6 @@ import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
-import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.util.LayoutUtils;
@@ -69,8 +68,16 @@ public class BackgroundAppState extends OverviewState {
if (taskCount == 0) {
return super.getOverviewScaleAndTranslation(launcher);
}
- TaskView dummyTask = recentsView.getTaskViewAt(Utilities.boundToRange(
- recentsView.getCurrentPage(), 0, taskCount - 1));
+ TaskView dummyTask;
+ if (recentsView.getCurrentPage() >= 0) {
+ if (recentsView.getCurrentPage() <= taskCount - 1) {
+ dummyTask = recentsView.getCurrentPageTaskView();
+ } else {
+ dummyTask = recentsView.getTaskViewAt(taskCount - 1);
+ }
+ } else {
+ dummyTask = recentsView.getTaskViewAt(0);
+ }
return recentsView.getTempClipAnimationHelper().updateForFullscreenOverview(dummyTask)
.getScaleAndTranslation();
}
@@ -91,7 +98,7 @@ public class BackgroundAppState extends OverviewState {
if ((getVisibleElements(launcher) & HOTSEAT_ICONS) != 0) {
// Translate hotseat offscreen if we show it in overview.
ScaleAndTranslation scaleAndTranslation = super.getHotseatScaleAndTranslation(launcher);
- scaleAndTranslation.translationY = LayoutUtils.getShelfTrackingDistance(launcher,
+ scaleAndTranslation.translationY += LayoutUtils.getShelfTrackingDistance(launcher,
launcher.getDeviceProfile());
return scaleAndTranslation;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 93d4de17d..ed5dba1fd 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -22,6 +22,7 @@ import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
@@ -32,7 +33,6 @@ import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
-import android.content.Context;
import android.graphics.Rect;
import android.view.View;
@@ -47,6 +47,7 @@ import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -91,8 +92,19 @@ public class OverviewState extends LauncherState {
@Override
public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
if ((getVisibleElements(launcher) & HOTSEAT_ICONS) != 0) {
- // If the hotseat icons are visible in overview, keep them in their normal position.
- return super.getWorkspaceScaleAndTranslation(launcher);
+ DeviceProfile dp = launcher.getDeviceProfile();
+ if (dp.allAppsIconSizePx >= dp.iconSizePx) {
+ return new ScaleAndTranslation(1, 0, 0);
+ } else {
+ float scale = ((float) dp.allAppsIconSizePx) / dp.iconSizePx;
+ // Distance between the screen center (which is the pivotY for hotseat) and the
+ // bottom of the hotseat (which we want to preserve)
+ float distanceFromBottom = dp.heightPx / 2 - dp.hotseatBarBottomPaddingPx;
+ // On scaling, the bottom edge is moved closer to the pivotY. We move the
+ // hotseat back down so that the bottom edge's position is preserved.
+ float translationY = distanceFromBottom * (1 - scale);
+ return new ScaleAndTranslation(scale, 0, translationY);
+ }
}
return getWorkspaceScaleAndTranslation(launcher);
}
@@ -160,15 +172,7 @@ public class OverviewState extends LauncherState {
}
public static float getDefaultSwipeHeight(Launcher launcher) {
- return getDefaultSwipeHeight(launcher, launcher.getDeviceProfile());
- }
-
- public static float getDefaultSwipeHeight(Context context, DeviceProfile dp) {
- float swipeHeight = dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx;
- if (SysUINavigationMode.getMode(context) == SysUINavigationMode.Mode.NO_BUTTON) {
- swipeHeight -= dp.getInsets().bottom;
- }
- return swipeHeight;
+ return LayoutUtils.getDefaultSwipeHeight(launcher, launcher.getDeviceProfile());
}
@Override
@@ -202,6 +206,7 @@ public class OverviewState extends LauncherState {
builder.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
builder.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
+ builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, OVERSHOOT_1_7);
builder.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
index ab346c059..3231f378d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
@@ -16,39 +16,37 @@
package com.android.launcher3.uioverrides.touchcontrollers;
+import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_PAUSE_TO_OVERVIEW_ANIM;
import static com.android.launcher3.LauncherState.ALL_APPS;
-import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
-import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
import static com.android.launcher3.LauncherStateManager.ATOMIC_OVERVIEW_PEEK_COMPONENT;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_HEADER_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
+import android.view.View;
import android.view.ViewConfiguration;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppTransitionManagerImpl;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.views.RecentsView;
@@ -77,7 +75,7 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
@Override
protected long getAtomicDuration() {
- return 300;
+ return LauncherAppTransitionManagerImpl.ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
}
@Override
@@ -105,8 +103,7 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
}
});
mPeekAnim.start();
- recentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
mLauncher.getDragLayer().getScrim().animateToSysuiMultiplier(isPaused ? 0 : 1,
peekDuration, 0);
@@ -131,16 +128,33 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
// Fade in prediction icons quickly, then rest of all apps after reaching overview.
float progressToReachOverview = NORMAL.getVerticalProgress(mLauncher)
- OVERVIEW.getVerticalProgress(mLauncher);
- builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(ACCEL,
- 0, ALL_APPS_CONTENT_FADE_THRESHOLD));
- builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(LINEAR,
- progressToReachOverview, 1));
+ builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
+ ACCEL,
+ 0,
+ ALL_APPS_CONTENT_FADE_THRESHOLD));
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
+ ACCEL,
+ progressToReachOverview,
+ progressToReachOverview + ALL_APPS_CONTENT_FADE_THRESHOLD));
// Get workspace out of the way quickly, to prepare for potential pause.
builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL_3);
builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, DEACCEL_3);
builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
return builder;
+ } else if (fromState == ALL_APPS && toState == NORMAL) {
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ // Keep all apps/predictions opaque until the very end of the transition.
+ float progressToReachOverview = OVERVIEW.getVerticalProgress(mLauncher);
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
+ DEACCEL,
+ progressToReachOverview - ALL_APPS_CONTENT_FADE_THRESHOLD,
+ progressToReachOverview));
+ builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
+ DEACCEL,
+ 1 - ALL_APPS_CONTENT_FADE_THRESHOLD,
+ 1));
+ return builder;
}
return super.getAnimatorSetBuilderForStates(fromState, toState);
}
@@ -155,20 +169,14 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
}
@Override
- public void onDragEnd(float velocity, boolean fling) {
+ public void onDragEnd(float velocity) {
if (mMotionPauseDetector.isPaused() && handlingOverviewAnim()) {
if (mPeekAnim != null) {
mPeekAnim.cancel();
}
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
- builder.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
- if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
- builder.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
- builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
- }
- AnimatorSet overviewAnim = mLauncher.getStateManager().createAtomicAnimation(
- NORMAL, OVERVIEW, builder, ANIM_ALL, ATOMIC_DURATION);
+ Animator overviewAnim = mLauncher.getAppTransitionManager().createStateElementAnimation(
+ INDEX_PAUSE_TO_OVERVIEW_ANIM);
overviewAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -177,7 +185,12 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
});
overviewAnim.start();
} else {
- super.onDragEnd(velocity, fling);
+ super.onDragEnd(velocity);
+ }
+
+ View searchView = mLauncher.getAppsView().getSearchView();
+ if (searchView instanceof FeedbackHandler) {
+ ((FeedbackHandler) searchView).resetFeedback();
}
mMotionPauseDetector.clear();
}
@@ -205,4 +218,16 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW);
}
}
+
+ /**
+ * Interface for views with feedback animation requiring reset
+ */
+ public interface FeedbackHandler {
+
+ /**
+ * reset searchWidget feedback
+ */
+ void resetFeedback();
+ }
+
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index d66af1ae2..ef50c7b5d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -23,6 +23,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.touch.AbstractStateChangeTouchController.SUCCESS_TRANSITION_PROGRESS;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -43,21 +44,25 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.AccessibilityManagerCompat;
-import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.config.BaseFlags;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.TouchController;
+import com.android.quickstep.util.AssistantUtilities;
import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
/**
* Handles swiping up on the nav bar to go home from launcher, e.g. overview or all apps.
*/
-public class NavBarToHomeTouchController implements TouchController, SwipeDetector.Listener {
+public class NavBarToHomeTouchController implements TouchController,
+ SingleAxisSwipeDetector.Listener {
private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL_3;
private final Launcher mLauncher;
- private final SwipeDetector mSwipeDetector;
+ private final SingleAxisSwipeDetector mSwipeDetector;
private final float mPullbackDistance;
private boolean mNoIntercept;
@@ -67,7 +72,8 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
public NavBarToHomeTouchController(Launcher launcher) {
mLauncher = launcher;
- mSwipeDetector = new SwipeDetector(mLauncher, this, SwipeDetector.VERTICAL);
+ mSwipeDetector = new SingleAxisSwipeDetector(mLauncher, this,
+ SingleAxisSwipeDetector.VERTICAL);
mPullbackDistance = mLauncher.getResources().getDimension(R.dimen.home_pullback_distance);
}
@@ -79,7 +85,8 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
if (mNoIntercept) {
return false;
}
- mSwipeDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_POSITIVE, false);
+ mSwipeDetector.setDetectableScrollConditions(SingleAxisSwipeDetector.DIRECTION_POSITIVE,
+ false /* ignoreSlop */);
}
if (mNoIntercept) {
@@ -101,6 +108,10 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
return true;
}
+ if (BaseFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
+ && AssistantUtilities.isExcludedAssistantRunning()) {
+ return true;
+ }
return false;
}
@@ -173,7 +184,8 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
}
@Override
- public void onDragEnd(float velocity, boolean fling) {
+ public void onDragEnd(float velocity) {
+ boolean fling = mSwipeDetector.isFling(velocity);
final int logAction = fling ? Touch.FLING : Touch.SWIPE;
float progress = mCurrentAnimation.getProgressFraction();
float interpolatedProgress = PULLBACK_INTERPOLATOR.getInterpolation(progress);
@@ -190,6 +202,8 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
AbstractFloatingView.closeAllOpenViews(mLauncher);
logStateChange(topOpenView.getLogContainerType(), logAction);
}
+ ActivityManagerWrapper.getInstance()
+ .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
} else {
// Quickly return to the state we came from (we didn't move far).
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
new file mode 100644
index 000000000..76374af6a
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -0,0 +1,473 @@
+/*
+ * Copyright (C) 2019 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.touchcontrollers;
+
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_PAUSE_TO_OVERVIEW_ANIM;
+import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.LauncherState.QUICK_SWITCH;
+import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
+import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW;
+import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_5;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
+import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
+import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
+import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
+import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.CANCEL;
+import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
+import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
+import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.graphics.PointF;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.LauncherStateManager.AnimationConfig;
+import com.android.launcher3.QuickstepAppTransitionManagerImpl;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.graphics.OverviewScrim;
+import com.android.launcher3.touch.BaseSwipeDetector;
+import com.android.launcher3.touch.BothAxesSwipeDetector;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.util.TouchController;
+import com.android.launcher3.util.VibratorWrapper;
+import com.android.quickstep.OverviewInteractionState;
+import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.util.MotionPauseDetector;
+import com.android.quickstep.util.ShelfPeekAnim;
+import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
+import com.android.quickstep.util.StaggeredWorkspaceAnim;
+import com.android.quickstep.views.LauncherRecentsView;
+
+/**
+ * Handles quick switching to a recent task from the home screen. To give as much flexibility to
+ * the user as possible, also handles swipe up and hold to go to overview and swiping back home.
+ */
+public class NoButtonQuickSwitchTouchController implements TouchController,
+ BothAxesSwipeDetector.Listener, MotionPauseDetector.OnMotionPauseListener {
+
+ /** The minimum progress of the scale/translationY animation until drag end. */
+ private static final float Y_ANIM_MIN_PROGRESS = 0.15f;
+ private static final Interpolator FADE_OUT_INTERPOLATOR = DEACCEL_5;
+ private static final Interpolator TRANSLATE_OUT_INTERPOLATOR = ACCEL_0_75;
+ private static final Interpolator SCALE_DOWN_INTERPOLATOR = DEACCEL;
+
+ private final Launcher mLauncher;
+ private final BothAxesSwipeDetector mSwipeDetector;
+ private final float mXRange;
+ private final float mYRange;
+ private final MotionPauseDetector mMotionPauseDetector;
+ private final float mMotionPauseMinDisplacement;
+
+ private boolean mNoIntercept;
+ private LauncherState mStartState;
+
+ private ShelfPeekAnim mShelfPeekAnim;
+ private boolean mIsHomeScreenVisible = true;
+
+ // As we drag, we control 3 animations: one to get non-overview components out of the way,
+ // and the other two to set overview properties based on x and y progress.
+ private AnimatorPlaybackController mNonOverviewAnim;
+ private AnimatorPlaybackController mXOverviewAnim;
+ private AnimatorPlaybackController mYOverviewAnim;
+
+ public NoButtonQuickSwitchTouchController(Launcher launcher) {
+ mLauncher = launcher;
+ mSwipeDetector = new BothAxesSwipeDetector(mLauncher, this);
+ mXRange = mLauncher.getDeviceProfile().widthPx / 2f;
+ mYRange = LayoutUtils.getShelfTrackingDistance(mLauncher, mLauncher.getDeviceProfile());
+ mMotionPauseDetector = new MotionPauseDetector(mLauncher);
+ mMotionPauseMinDisplacement = mLauncher.getResources().getDimension(
+ R.dimen.motion_pause_detector_min_displacement_from_app);
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mNoIntercept = !canInterceptTouch(ev);
+ if (mNoIntercept) {
+ return false;
+ }
+
+ // Only detect horizontal swipe for intercept, then we will allow swipe up as well.
+ mSwipeDetector.setDetectableScrollConditions(DIRECTION_RIGHT,
+ false /* ignoreSlopWhenSettling */);
+ }
+
+ if (mNoIntercept) {
+ return false;
+ }
+
+ onControllerTouchEvent(ev);
+ return mSwipeDetector.isDraggingOrSettling();
+ }
+
+ @Override
+ public boolean onControllerTouchEvent(MotionEvent ev) {
+ return mSwipeDetector.onTouchEvent(ev);
+ }
+
+ private boolean canInterceptTouch(MotionEvent ev) {
+ if (!mLauncher.isInState(LauncherState.NORMAL)) {
+ return false;
+ }
+ if ((ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) == 0) {
+ return false;
+ }
+ int stateFlags = OverviewInteractionState.INSTANCE.get(mLauncher).getSystemUiStateFlags();
+ if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void onDragStart(boolean start) {
+ mMotionPauseDetector.clear();
+ if (start) {
+ mShelfPeekAnim = ((QuickstepAppTransitionManagerImpl) mLauncher
+ .getAppTransitionManager()).getShelfPeekAnim();
+
+ mStartState = mLauncher.getStateManager().getState();
+
+ mMotionPauseDetector.setOnMotionPauseListener(this);
+
+ // We have detected horizontal drag start, now allow swipe up as well.
+ mSwipeDetector.setDetectableScrollConditions(DIRECTION_RIGHT | DIRECTION_UP,
+ false /* ignoreSlopWhenSettling */);
+
+ setupAnimators();
+ }
+ }
+
+ @Override
+ public void onMotionPauseChanged(boolean isPaused) {
+ ShelfAnimState shelfState = isPaused ? PEEK : HIDE;
+ if (shelfState == PEEK) {
+ // Some shelf elements (e.g. qsb) were hidden, but we need them visible when peeking.
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
+ allAppsController.setAlphas(NORMAL.getVisibleElements(mLauncher),
+ new AnimationConfig(), builder);
+ builder.build().setDuration(0).start();
+
+ if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+ // Hotseat was hidden, but we need it visible when peeking.
+ mLauncher.getHotseat().setAlpha(1);
+ }
+ }
+ mShelfPeekAnim.setShelfState(shelfState, ShelfPeekAnim.INTERPOLATOR,
+ ShelfPeekAnim.DURATION);
+ VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
+ }
+
+ private void setupAnimators() {
+ // Animate the non-overview components (e.g. workspace, shelf) out of the way.
+ AnimatorSetBuilder nonOverviewBuilder = new AnimatorSetBuilder();
+ nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_FADE, FADE_OUT_INTERPOLATOR);
+ nonOverviewBuilder.setInterpolator(ANIM_ALL_APPS_FADE, FADE_OUT_INTERPOLATOR);
+ nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, TRANSLATE_OUT_INTERPOLATOR);
+ nonOverviewBuilder.setInterpolator(ANIM_VERTICAL_PROGRESS, TRANSLATE_OUT_INTERPOLATOR);
+ updateNonOverviewAnim(QUICK_SWITCH, nonOverviewBuilder, ANIM_ALL);
+ mNonOverviewAnim.dispatchOnStart();
+
+ setupOverviewAnimators();
+ }
+
+ /** Create state animation to control non-overview components. */
+ private void updateNonOverviewAnim(LauncherState toState, AnimatorSetBuilder builder,
+ @LauncherStateManager.AnimationComponents int animComponents) {
+ builder.addFlag(FLAG_DONT_ANIMATE_OVERVIEW);
+ long accuracy = (long) (Math.max(mXRange, mYRange) * 2);
+ mNonOverviewAnim = mLauncher.getStateManager().createAnimationToNewWorkspace(toState,
+ builder, accuracy, this::clearState, animComponents);
+ }
+
+ private void setupOverviewAnimators() {
+ final LauncherState fromState = QUICK_SWITCH;
+ final LauncherState toState = OVERVIEW;
+ LauncherState.ScaleAndTranslation fromScaleAndTranslation = fromState
+ .getOverviewScaleAndTranslation(mLauncher);
+ LauncherState.ScaleAndTranslation toScaleAndTranslation = toState
+ .getOverviewScaleAndTranslation(mLauncher);
+ // Update RecentView's translationX to have it start offscreen.
+ LauncherRecentsView recentsView = mLauncher.getOverviewPanel();
+ float startScale = Utilities.mapRange(
+ SCALE_DOWN_INTERPOLATOR.getInterpolation(Y_ANIM_MIN_PROGRESS),
+ fromScaleAndTranslation.scale,
+ toScaleAndTranslation.scale);
+ fromScaleAndTranslation.translationX = recentsView.getOffscreenTranslationX(startScale);
+
+ // Set RecentView's initial properties.
+ recentsView.setScaleX(fromScaleAndTranslation.scale);
+ recentsView.setScaleY(fromScaleAndTranslation.scale);
+ recentsView.setTranslationX(fromScaleAndTranslation.translationX);
+ recentsView.setTranslationY(fromScaleAndTranslation.translationY);
+ recentsView.setContentAlpha(1);
+
+ // As we drag right, animate the following properties:
+ // - RecentsView translationX
+ // - OverviewScrim
+ AnimatorSet xOverviewAnim = new AnimatorSet();
+ xOverviewAnim.play(ObjectAnimator.ofFloat(recentsView, View.TRANSLATION_X,
+ toScaleAndTranslation.translationX));
+ xOverviewAnim.play(ObjectAnimator.ofFloat(
+ mLauncher.getDragLayer().getOverviewScrim(), OverviewScrim.SCRIM_PROGRESS,
+ toState.getOverviewScrimAlpha(mLauncher)));
+ long xAccuracy = (long) (mXRange * 2);
+ xOverviewAnim.setDuration(xAccuracy);
+ mXOverviewAnim = AnimatorPlaybackController.wrap(xOverviewAnim, xAccuracy);
+ mXOverviewAnim.dispatchOnStart();
+
+ // As we drag up, animate the following properties:
+ // - RecentsView translationY
+ // - RecentsView scale
+ // - RecentsView fullscreenProgress
+ AnimatorSet yAnimation = new AnimatorSet();
+ Animator translateYAnim = ObjectAnimator.ofFloat(recentsView, View.TRANSLATION_Y,
+ toScaleAndTranslation.translationY);
+ Animator scaleAnim = ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY,
+ toScaleAndTranslation.scale);
+ Animator fullscreenProgressAnim = ObjectAnimator.ofFloat(recentsView, FULLSCREEN_PROGRESS,
+ fromState.getOverviewFullscreenProgress(), toState.getOverviewFullscreenProgress());
+ scaleAnim.setInterpolator(SCALE_DOWN_INTERPOLATOR);
+ fullscreenProgressAnim.setInterpolator(SCALE_DOWN_INTERPOLATOR);
+ yAnimation.play(translateYAnim);
+ yAnimation.play(scaleAnim);
+ yAnimation.play(fullscreenProgressAnim);
+ long yAccuracy = (long) (mYRange * 2);
+ yAnimation.setDuration(yAccuracy);
+ mYOverviewAnim = AnimatorPlaybackController.wrap(yAnimation, yAccuracy);
+ mYOverviewAnim.dispatchOnStart();
+ }
+
+ @Override
+ public boolean onDrag(PointF displacement, MotionEvent ev) {
+ float xProgress = Math.max(0, displacement.x) / mXRange;
+ float yProgress = Math.max(0, -displacement.y) / mYRange;
+ yProgress = Utilities.mapRange(yProgress, Y_ANIM_MIN_PROGRESS, 1f);
+
+ boolean wasHomeScreenVisible = mIsHomeScreenVisible;
+ if (wasHomeScreenVisible && mNonOverviewAnim != null) {
+ mNonOverviewAnim.setPlayFraction(xProgress);
+ }
+ mIsHomeScreenVisible = FADE_OUT_INTERPOLATOR.getInterpolation(xProgress)
+ <= 1 - ALPHA_CUTOFF_THRESHOLD;
+
+ if (wasHomeScreenVisible && !mIsHomeScreenVisible) {
+ // Get the shelf all the way offscreen so it pops up when we decide to peek it.
+ mShelfPeekAnim.setShelfState(HIDE, LINEAR, 0);
+ }
+
+ // Only allow motion pause if the home screen is invisible, since some
+ // home screen elements will appear in the shelf on motion pause.
+ mMotionPauseDetector.setDisallowPause(mIsHomeScreenVisible
+ || -displacement.y < mMotionPauseMinDisplacement);
+ mMotionPauseDetector.addPosition(displacement.y, ev.getEventTime());
+
+ if (mIsHomeScreenVisible) {
+ // Cancel the shelf anim so it doesn't clobber mNonOverviewAnim.
+ mShelfPeekAnim.setShelfState(CANCEL, LINEAR, 0);
+ }
+
+ if (mXOverviewAnim != null) {
+ mXOverviewAnim.setPlayFraction(xProgress);
+ }
+ if (mYOverviewAnim != null) {
+ mYOverviewAnim.setPlayFraction(yProgress);
+ }
+ return true;
+ }
+
+ @Override
+ public void onDragEnd(PointF velocity) {
+ boolean horizontalFling = mSwipeDetector.isFling(velocity.x);
+ boolean verticalFling = mSwipeDetector.isFling(velocity.y);
+ boolean noFling = !horizontalFling && !verticalFling;
+ int logAction = noFling ? Touch.SWIPE : Touch.FLING;
+ if (mMotionPauseDetector.isPaused() && noFling) {
+ cancelAnimations();
+
+ Animator overviewAnim = mLauncher.getAppTransitionManager().createStateElementAnimation(
+ INDEX_PAUSE_TO_OVERVIEW_ANIM);
+ overviewAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ onAnimationToStateCompleted(OVERVIEW, logAction);
+ }
+ });
+ overviewAnim.start();
+ return;
+ }
+
+ final LauncherState targetState;
+ if (horizontalFling && verticalFling) {
+ if (velocity.x < 0) {
+ // Flinging left and up or down both go back home.
+ targetState = NORMAL;
+ } else {
+ if (velocity.y > 0) {
+ // Flinging right and down goes to quick switch.
+ targetState = QUICK_SWITCH;
+ } else {
+ // Flinging up and right could go either home or to quick switch.
+ // Determine the target based on the higher velocity.
+ targetState = Math.abs(velocity.x) > Math.abs(velocity.y)
+ ? QUICK_SWITCH : NORMAL;
+ }
+ }
+ } else if (horizontalFling) {
+ targetState = velocity.x > 0 ? QUICK_SWITCH : NORMAL;
+ } else if (verticalFling) {
+ targetState = velocity.y > 0 ? QUICK_SWITCH : NORMAL;
+ } else {
+ // If user isn't flinging, just snap to the closest state based on x progress.
+ boolean passedHorizontalThreshold = mXOverviewAnim.getInterpolatedProgress() > 0.5f;
+ targetState = passedHorizontalThreshold ? QUICK_SWITCH : NORMAL;
+ }
+
+ // Animate the various components to the target state.
+
+ float xProgress = mXOverviewAnim.getProgressFraction();
+ float startXProgress = Utilities.boundToRange(xProgress
+ + velocity.x * getSingleFrameMs(mLauncher) / mXRange, 0f, 1f);
+ final float endXProgress = targetState == NORMAL ? 0 : 1;
+ long xDuration = BaseSwipeDetector.calculateDuration(velocity.x,
+ Math.abs(endXProgress - startXProgress));
+ ValueAnimator xOverviewAnim = mXOverviewAnim.getAnimationPlayer();
+ xOverviewAnim.setFloatValues(startXProgress, endXProgress);
+ xOverviewAnim.setDuration(xDuration)
+ .setInterpolator(scrollInterpolatorForVelocity(velocity.x));
+ mXOverviewAnim.dispatchOnStartWithVelocity(endXProgress, velocity.x);
+
+ boolean flingUpToNormal = verticalFling && velocity.y < 0 && targetState == NORMAL;
+
+ float yProgress = mYOverviewAnim.getProgressFraction();
+ float startYProgress = Utilities.boundToRange(yProgress
+ - velocity.y * getSingleFrameMs(mLauncher) / mYRange, 0f, 1f);
+ final float endYProgress;
+ if (flingUpToNormal) {
+ endYProgress = 1;
+ } else if (targetState == NORMAL) {
+ // Keep overview at its current scale/translationY as it slides off the screen.
+ endYProgress = startYProgress;
+ } else {
+ endYProgress = 0;
+ }
+ long yDuration = BaseSwipeDetector.calculateDuration(velocity.y,
+ Math.abs(endYProgress - startYProgress));
+ ValueAnimator yOverviewAnim = mYOverviewAnim.getAnimationPlayer();
+ yOverviewAnim.setFloatValues(startYProgress, endYProgress);
+ yOverviewAnim.setDuration(yDuration);
+ mYOverviewAnim.dispatchOnStartWithVelocity(endYProgress, velocity.y);
+
+ ValueAnimator nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
+ if (flingUpToNormal && !mIsHomeScreenVisible) {
+ // We are flinging to home while workspace is invisible, run the same staggered
+ // animation as from an app.
+ // Update mNonOverviewAnim to do nothing so it doesn't interfere.
+ updateNonOverviewAnim(targetState, new AnimatorSetBuilder(), 0 /* animComponents */);
+ nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
+
+ new StaggeredWorkspaceAnim(mLauncher, velocity.y, false /* animateOverviewScrim */)
+ .start();
+ } else {
+ boolean canceled = targetState == NORMAL;
+ if (canceled) {
+ // Let the state manager know that the animation didn't go to the target state,
+ // but don't clean up yet (we already clean up when the animation completes).
+ mNonOverviewAnim.dispatchOnCancelWithoutCancelRunnable();
+ }
+ float startProgress = mNonOverviewAnim.getProgressFraction();
+ float endProgress = canceled ? 0 : 1;
+ nonOverviewAnim.setFloatValues(startProgress, endProgress);
+ mNonOverviewAnim.dispatchOnStartWithVelocity(endProgress,
+ horizontalFling ? velocity.x : velocity.y);
+ }
+
+ nonOverviewAnim.setDuration(Math.max(xDuration, yDuration));
+ mNonOverviewAnim.setEndAction(() -> onAnimationToStateCompleted(targetState, logAction));
+
+ cancelAnimations();
+ xOverviewAnim.start();
+ yOverviewAnim.start();
+ nonOverviewAnim.start();
+ }
+
+ private void onAnimationToStateCompleted(LauncherState targetState, int logAction) {
+ mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
+ getDirectionForLog(), mSwipeDetector.getDownX(), mSwipeDetector.getDownY(),
+ LauncherLogProto.ContainerType.NAVBAR,
+ mStartState.containerType,
+ targetState.containerType,
+ mLauncher.getWorkspace().getCurrentPage());
+ mLauncher.getStateManager().goToState(targetState, false, this::clearState);
+ }
+
+ private int getDirectionForLog() {
+ return Utilities.isRtl(mLauncher.getResources()) ? Direction.LEFT : Direction.RIGHT;
+ }
+
+ private void cancelAnimations() {
+ if (mNonOverviewAnim != null) {
+ mNonOverviewAnim.getAnimationPlayer().cancel();
+ }
+ if (mXOverviewAnim != null) {
+ mXOverviewAnim.getAnimationPlayer().cancel();
+ }
+ if (mYOverviewAnim != null) {
+ mYOverviewAnim.getAnimationPlayer().cancel();
+ }
+ mShelfPeekAnim.setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
+ mMotionPauseDetector.clear();
+ }
+
+ private void clearState() {
+ cancelAnimations();
+ mNonOverviewAnim = null;
+ mXOverviewAnim = null;
+ mYOverviewAnim = null;
+ mIsHomeScreenVisible = true;
+ mSwipeDetector.finishedScrolling();
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
index 20a248734..03862db1d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
@@ -47,9 +47,9 @@ public final class PortraitOverviewStateTouchHelper {
* @return true if we should intercept the motion event
*/
boolean canInterceptTouch(MotionEvent ev) {
- if (mRecentsView.getChildCount() > 0) {
+ if (mRecentsView.getTaskViewCount() > 0) {
// Allow swiping up in the gap between the hotseat and overview.
- return ev.getY() >= mRecentsView.getChildAt(0).getBottom();
+ return ev.getY() >= mRecentsView.getTaskViewAt(0).getBottom();
} else {
// If there are no tasks, we only intercept if we're below the hotseat height.
return isTouchOverHotseat(mLauncher, ev);
@@ -63,7 +63,7 @@ public final class PortraitOverviewStateTouchHelper {
* @return true if going back should take the user to the currently running task
*/
boolean shouldSwipeDownReturnToApp() {
- TaskView taskView = mRecentsView.getTaskViewAt(mRecentsView.getNextPage());
+ TaskView taskView = mRecentsView.getNextPageTaskView();
return taskView != null && mRecentsView.shouldSwipeDownLaunchApp();
}
@@ -76,7 +76,7 @@ public final class PortraitOverviewStateTouchHelper {
*/
PendingAnimation createSwipeDownToTaskAppAnimation(long duration) {
mRecentsView.setCurrentPage(mRecentsView.getPageNearestToCenterOfScreen());
- TaskView taskView = mRecentsView.getTaskViewAt(mRecentsView.getCurrentPage());
+ TaskView taskView = mRecentsView.getCurrentPageTaskView();
if (taskView == null) {
throw new IllegalStateException("There is no task view to animate to.");
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index eb571f607..14216ffdf 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -30,6 +30,7 @@ import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.view.MotionEvent;
@@ -42,7 +43,7 @@ import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
-import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.quickstep.OverviewInteractionState;
@@ -50,7 +51,7 @@ import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
-import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
/**
* Handles quick switching to a recent task from the home screen.
@@ -60,10 +61,10 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll
private @Nullable TaskView mTaskToLaunch;
public QuickSwitchTouchController(Launcher launcher) {
- this(launcher, SwipeDetector.HORIZONTAL);
+ this(launcher, SingleAxisSwipeDetector.HORIZONTAL);
}
- protected QuickSwitchTouchController(Launcher l, SwipeDetector.Direction dir) {
+ protected QuickSwitchTouchController(Launcher l, SingleAxisSwipeDetector.Direction dir) {
super(l, dir);
}
@@ -95,6 +96,8 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll
super.onDragStart(start);
mStartContainerType = LauncherLogProto.ContainerType.NAVBAR;
mTaskToLaunch = mLauncher.<RecentsView>getOverviewPanel().getTaskViewAt(0);
+ ActivityManagerWrapper.getInstance()
+ .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 00e4f58e9..ad02de109 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -19,6 +19,9 @@ import static com.android.launcher3.AbstractFloatingView.TYPE_ACCESSIBLE;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
+import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_BOTH;
+import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE;
+import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_POSITIVE;
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
import android.animation.Animator;
@@ -32,7 +35,8 @@ import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.touch.BaseSwipeDetector;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.FlingBlockCheck;
import com.android.launcher3.util.PendingAnimation;
@@ -46,15 +50,14 @@ import com.android.quickstep.views.TaskView;
* Touch controller for handling task view card swipes
*/
public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
- extends AnimatorListenerAdapter implements TouchController, SwipeDetector.Listener {
-
- private static final String TAG = "OverviewSwipeController";
+ extends AnimatorListenerAdapter implements TouchController,
+ SingleAxisSwipeDetector.Listener {
// Progress after which the transition is assumed to be a success in case user does not fling
public static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
protected final T mActivity;
- private final SwipeDetector mDetector;
+ private final SingleAxisSwipeDetector mDetector;
private final RecentsView mRecentsView;
private final int[] mTempCords = new int[2];
@@ -74,7 +77,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
public TaskViewTouchController(T activity) {
mActivity = activity;
mRecentsView = activity.getOverviewPanel();
- mDetector = new SwipeDetector(activity, this, SwipeDetector.VERTICAL);
+ mDetector = new SingleAxisSwipeDetector(activity, this, SingleAxisSwipeDetector.VERTICAL);
}
private boolean canInterceptTouch() {
@@ -113,7 +116,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
int directionsToDetectScroll = 0;
boolean ignoreSlopWhenSettling = false;
if (mCurrentAnimation != null) {
- directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
+ directionsToDetectScroll = DIRECTION_BOTH;
ignoreSlopWhenSettling = true;
} else {
mTaskBeingDragged = null;
@@ -126,12 +129,12 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
if (!SysUINavigationMode.getMode(mActivity).hasGestures) {
// Don't allow swipe down to open if we don't support swipe up
// to enter overview.
- directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
+ directionsToDetectScroll = DIRECTION_POSITIVE;
} else {
// The task can be dragged up to dismiss it,
// and down to open if it's the current page.
directionsToDetectScroll = i == mRecentsView.getCurrentPage()
- ? SwipeDetector.DIRECTION_BOTH : SwipeDetector.DIRECTION_POSITIVE;
+ ? DIRECTION_BOTH : DIRECTION_POSITIVE;
}
break;
}
@@ -165,8 +168,8 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
return;
}
int scrollDirections = mDetector.getScrollDirections();
- if (goingUp && ((scrollDirections & SwipeDetector.DIRECTION_POSITIVE) == 0)
- || !goingUp && ((scrollDirections & SwipeDetector.DIRECTION_NEGATIVE) == 0)) {
+ if (goingUp && ((scrollDirections & DIRECTION_POSITIVE) == 0)
+ || !goingUp && ((scrollDirections & DIRECTION_NEGATIVE) == 0)) {
// Trying to re-init in an unsupported direction.
return;
}
@@ -243,7 +246,8 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
}
@Override
- public void onDragEnd(float velocity, boolean fling) {
+ public void onDragEnd(float velocity) {
+ boolean fling = mDetector.isFling(velocity);
final boolean goingToEnd;
final int logAction;
boolean blockedFling = fling && mFlingBlockCheck.isBlocked();
@@ -260,7 +264,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
logAction = Touch.SWIPE;
goingToEnd = interpolatedProgress > SUCCESS_TRANSITION_PROGRESS;
}
- long animationDuration = SwipeDetector.calculateDuration(
+ long animationDuration = BaseSwipeDetector.calculateDuration(
velocity, goingToEnd ? (1 - progress) : progress);
if (blockedFling && !goingToEnd) {
animationDuration *= LauncherAnimUtils.blockedFlingDurationFactor(velocity);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
index f1e4041eb..0ed529184 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
@@ -17,12 +17,12 @@ package com.android.launcher3.uioverrides.touchcontrollers;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
public class TransposedQuickSwitchTouchController extends QuickSwitchTouchController {
public TransposedQuickSwitchTouchController(Launcher launcher) {
- super(launcher, SwipeDetector.VERTICAL);
+ super(launcher, SingleAxisSwipeDetector.VERTICAL);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index d627a7f14..5cce53ebf 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -15,16 +15,13 @@
*/
package com.android.quickstep;
-import static android.os.VibrationEffect.EFFECT_CLICK;
-import static android.os.VibrationEffect.createPredefined;
-
import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
-import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
-import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import android.animation.Animator;
@@ -39,14 +36,12 @@ import android.graphics.RectF;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
-import android.os.VibrationEffect;
-import android.os.Vibrator;
-import android.provider.Settings;
import android.view.MotionEvent;
import android.view.View;
-import android.view.WindowManager;
import android.view.animation.Interpolator;
+import androidx.annotation.UiThread;
+
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
@@ -54,8 +49,8 @@ import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.graphics.RotationMode;
+import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
@@ -75,8 +70,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import java.util.function.Consumer;
-import androidx.annotation.UiThread;
-
/**
* Base class for swipe up handler with some utility methods
*/
@@ -107,7 +100,6 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
protected final ClipAnimationHelper mClipAnimationHelper;
protected final TransformParams mTransformParams = new TransformParams();
- private final Vibrator mVibrator;
protected final Mode mMode;
// Shift in the range of [0, 1].
@@ -126,7 +118,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
protected Runnable mGestureEndCallback;
- protected final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
+ protected final Handler mMainThreadHandler = MAIN_EXECUTOR.getHandler();
protected MultiStateCallback mStateCallback;
protected boolean mCanceled;
@@ -148,7 +140,6 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
mClipAnimationHelper = new ClipAnimationHelper(context);
mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
- mVibrator = context.getSystemService(Vibrator.class);
initTransitionEndpoints(InvariantDeviceProfile.INSTANCE.get(mContext)
.getDeviceProfile(mContext));
}
@@ -162,19 +153,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
}
protected void performHapticFeedback() {
- if (!mVibrator.hasVibrator()) {
- return;
- }
- if (Settings.System.getInt(
- mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0) {
- return;
- }
-
- VibrationEffect effect = createPredefined(EFFECT_CLICK);
- if (effect == null) {
- return;
- }
- BACKGROUND_EXECUTOR.execute(() -> mVibrator.vibrate(effect));
+ VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
}
public Consumer<MotionEvent> getRecentsViewDispatcher(RotationMode rotationMode) {
@@ -229,10 +208,10 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
// Launch the task user scrolled to (mRecentsView.getNextPage()).
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
// We finish recents animation inside launchTask() when live tile is enabled.
- mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
+ mRecentsView.getNextPageTaskView().launchTask(false /* animate */,
true /* freezeTaskList */);
} else {
- int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
+ int taskId = mRecentsView.getNextPageTaskView().getTask().key.id;
mFinishingRecentsAnimationForNewTaskId = taskId;
mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
if (!mCanceled) {
@@ -275,7 +254,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
overviewStackBounds = getStackBounds(dp);
}
dp.updateInsets(targetSet.homeContentInsets);
- dp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
+ dp.updateIsSeascape(mContext);
if (runningTaskTarget != null) {
mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
index 36eb8a13b..54a366d8a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -24,7 +24,6 @@ import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_SHELF
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.INSTANT;
@@ -53,15 +52,15 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherInitListenerEx;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.QuickstepAppTransitionManagerImpl;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.util.ShelfPeekAnim;
+import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
@@ -167,18 +166,8 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
@Override
public void playAtomicAnimation(float velocity) {
- // Setup workspace with 0 duration to prepare for our staggered animation.
- LauncherStateManager stateManager = activity.getStateManager();
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
- // setRecentsAttachedToAppWindow() will animate recents out.
- builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW);
- stateManager.createAtomicAnimation(BACKGROUND_APP, NORMAL, builder, ANIM_ALL, 0);
- builder.build().start();
-
- // Stop scrolling so that it doesn't interfere with the translation offscreen.
- recentsView.getScroller().forceFinished(true);
-
- new StaggeredWorkspaceAnim(activity, workspaceView, velocity).start();
+ new StaggeredWorkspaceAnim(activity, velocity, true /* animateOverviewScrim */)
+ .start();
}
};
}
@@ -201,7 +190,9 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
activity.getAppsView().reset(false /* animate */);
return new AnimationFactory() {
- private ShelfAnimState mShelfState;
+ private final ShelfPeekAnim mShelfAnim =
+ ((QuickstepAppTransitionManagerImpl) activity.getAppTransitionManager())
+ .getShelfPeekAnim();
private boolean mIsAttachedToWindow;
@Override
@@ -230,30 +221,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
@Override
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator,
long duration) {
- if (mShelfState == shelfState) {
- return;
- }
- mShelfState = shelfState;
- activity.getStateManager().cancelStateElementAnimation(INDEX_SHELF_ANIM);
- if (mShelfState == ShelfAnimState.CANCEL) {
- return;
- }
- float shelfHiddenProgress = BACKGROUND_APP.getVerticalProgress(activity);
- float shelfOverviewProgress = OVERVIEW.getVerticalProgress(activity);
- // Peek based on default overview progress so we can see hotseat if we're showing
- // that instead of predictions in overview.
- float defaultOverviewProgress = OverviewState.getDefaultVerticalProgress(activity);
- float shelfPeekingProgress = shelfHiddenProgress
- - (shelfHiddenProgress - defaultOverviewProgress) * 0.25f;
- float toProgress = mShelfState == ShelfAnimState.HIDE
- ? shelfHiddenProgress
- : mShelfState == ShelfAnimState.PEEK
- ? shelfPeekingProgress
- : shelfOverviewProgress;
- Animator shelfAnim = activity.getStateManager()
- .createStateElementAnimation(INDEX_SHELF_ANIM, toProgress);
- shelfAnim.setInterpolator(interpolator);
- shelfAnim.setDuration(duration).start();
+ mShelfAnim.setShelfState(shelfState, interpolator, duration);
}
@Override
@@ -268,22 +236,12 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
int runningTaskIndex = recentsView.getRunningTaskIndex();
- if (runningTaskIndex == 0) {
+ if (runningTaskIndex == recentsView.getTaskViewStartIndex()) {
// If we are on the first task (we haven't quick switched), translate recents in
// from the side. Calculate the start translation based on current scale/scroll.
float currScale = recentsView.getScaleX();
float scrollOffsetX = recentsView.getScrollOffset();
-
- float offscreenX = NORMAL.getOverviewScaleAndTranslation(activity).translationX;
- // The first task is hidden, so offset by its width.
- int firstTaskWidth = recentsView.getTaskViewAt(0).getWidth();
- offscreenX -= (firstTaskWidth + recentsView.getPageSpacing()) * currScale;
- // Offset since scale pushes tasks outwards.
- offscreenX += firstTaskWidth * (currScale - 1) / 2;
- offscreenX = Math.max(0, offscreenX);
- if (recentsView.isRtl()) {
- offscreenX = -offscreenX;
- }
+ float offscreenX = recentsView.getOffscreenTranslationX(currScale);
float fromTranslationX = attached ? offscreenX - scrollOffsetX : 0;
float toTranslationX = attached ? 0 : offscreenX - scrollOffsetX;
@@ -351,8 +309,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
private void playScaleDownAnim(AnimatorSet anim, Launcher launcher, LauncherState fromState,
LauncherState endState) {
RecentsView recentsView = launcher.getOverviewPanel();
- TaskView v = recentsView.getTaskViewAt(recentsView.getCurrentPage());
- if (v == null) {
+ if (recentsView.getCurrentPageTaskView() == null) {
return;
}
@@ -380,7 +337,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
// recents as a whole needs to translate further to keep up with the app window.
TaskView runningTaskView = recentsView.getRunningTaskView();
if (runningTaskView == null) {
- runningTaskView = recentsView.getTaskViewAt(recentsView.getCurrentPage());
+ runningTaskView = recentsView.getCurrentPageTaskView();
if (runningTaskView == null) {
// There are no task views in LockTask mode when Overview is enabled.
return;
@@ -483,4 +440,4 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
public void onLaunchTaskSuccess(Launcher launcher) {
launcher.getStateManager().moveToRestState();
}
-} \ No newline at end of file
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
index 14ff47b6a..a8d402e56 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
@@ -15,8 +15,8 @@
*/
package com.android.quickstep;
-import static com.android.systemui.shared.system.ActivityManagerWrapper
- .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -29,7 +29,6 @@ import android.util.Log;
import android.view.ViewConfiguration;
import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -49,7 +48,6 @@ public class OverviewCommandHelper {
private final Context mContext;
private final ActivityManagerWrapper mAM;
private final RecentsModel mRecentsModel;
- private final MainThreadExecutor mMainThreadExecutor;
private final OverviewComponentObserver mOverviewComponentObserver;
private long mLastToggleTime;
@@ -57,7 +55,6 @@ public class OverviewCommandHelper {
public OverviewCommandHelper(Context context, OverviewComponentObserver observer) {
mContext = context;
mAM = ActivityManagerWrapper.getInstance();
- mMainThreadExecutor = new MainThreadExecutor();
mRecentsModel = RecentsModel.INSTANCE.get(mContext);
mOverviewComponentObserver = observer;
}
@@ -69,19 +66,19 @@ public class OverviewCommandHelper {
}
mAM.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
- mMainThreadExecutor.execute(new RecentsActivityCommand<>());
+ MAIN_EXECUTOR.execute(new RecentsActivityCommand<>());
}
public void onOverviewShown(boolean triggeredFromAltTab) {
- mMainThreadExecutor.execute(new ShowRecentsCommand(triggeredFromAltTab));
+ MAIN_EXECUTOR.execute(new ShowRecentsCommand(triggeredFromAltTab));
}
public void onOverviewHidden() {
- mMainThreadExecutor.execute(new HideRecentsCommand());
+ MAIN_EXECUTOR.execute(new HideRecentsCommand());
}
public void onTip(int actionType, int viewType) {
- mMainThreadExecutor.execute(() ->
+ MAIN_EXECUTOR.execute(() ->
UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
}
@@ -112,7 +109,7 @@ public class OverviewCommandHelper {
TaskView taskView = rv.getNextTaskView();
if (taskView == null) {
if (rv.getTaskViewCount() > 0) {
- taskView = (TaskView) rv.getPageAt(0);
+ taskView = rv.getTaskViewAt(0);
taskView.requestFocus();
} else {
rv.requestFocus();
@@ -164,9 +161,6 @@ public class OverviewCommandHelper {
@Override
public void run() {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.ALL_APPS_UPON_RECENTS, "RecentsActivityCommand.run");
- }
long elapsedTime = mCreateTime - mLastToggleTime;
mLastToggleTime = mCreateTime;
@@ -183,7 +177,7 @@ public class OverviewCommandHelper {
// Otherwise, start overview.
mListener = mHelper.createActivityInitListener(this::onActivityReady);
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
- this::createWindowAnimation, mContext, mMainThreadExecutor.getHandler(),
+ this::createWindowAnimation, mContext, MAIN_EXECUTOR.getHandler(),
mAnimationProvider.getRecentsLaunchDuration());
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
index da4642636..3c78dd8af 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -1,12 +1,12 @@
package com.android.quickstep;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
import android.content.Context;
import android.os.Bundle;
-import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.testing.TestInformationHandler;
import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
@@ -24,7 +24,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
switch (method) {
case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
final float swipeHeight =
- OverviewState.getDefaultSwipeHeight(mContext, mDeviceProfile);
+ LayoutUtils.getDefaultSwipeHeight(mContext, mDeviceProfile);
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
return response;
}
@@ -36,12 +36,6 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
return response;
}
- case TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED: {
- response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
- TouchInteractionService.isInitialized());
- return response;
- }
-
case TestProtocol.REQUEST_HOTSEAT_TOP: {
if (mLauncher == null) return null;
@@ -52,7 +46,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
case TestProtocol.REQUEST_OVERVIEW_LEFT_GESTURE_MARGIN: {
try {
- final int leftMargin = new MainThreadExecutor().submit(() ->
+ final int leftMargin = MAIN_EXECUTOR.submit(() ->
mLauncher.<RecentsView>getOverviewPanel().getLeftGestureMargin()).get();
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, leftMargin);
} catch (ExecutionException e) {
@@ -65,7 +59,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
case TestProtocol.REQUEST_OVERVIEW_RIGHT_GESTURE_MARGIN: {
try {
- final int rightMargin = new MainThreadExecutor().submit(() ->
+ final int rightMargin = MAIN_EXECUTOR.submit(() ->
mLauncher.<RecentsView>getOverviewPanel().getRightGestureMargin()).
get();
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, rightMargin);
@@ -80,4 +74,9 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
return super.call(method);
}
+
+ @Override
+ protected boolean isLauncherInitialized() {
+ return super.isLauncherInitialized() && TouchInteractionService.isInitialized();
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index f08ae4a82..9bdc98bf8 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
@@ -136,6 +136,12 @@ public final class RecentsActivity extends BaseRecentsActivity {
}
@Override
+ public void returnToHomescreen() {
+ super.returnToHomescreen();
+ // TODO(b/137318995) This should go home, but doing so removes freeform windows
+ }
+
+ @Override
public ActivityOptions getActivityLaunchOptions(final View v) {
if (!(v instanceof TaskView)) {
return null;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
index c55f656df..8783ee3cc 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
@@ -15,7 +15,7 @@
*/
package com.android.quickstep;
-import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.util.Log;
@@ -25,6 +25,7 @@ import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
+
import java.io.PrintWriter;
/**
@@ -44,6 +45,7 @@ public class SwipeSharedState implements SwipeAnimationListener {
public boolean goingToLauncher;
public boolean recentsAnimationFinishInterrupted;
public int nextRunningTaskId = -1;
+ private int mLogId;
public void setOverviewComponentObserver(OverviewComponentObserver observer) {
mOverviewComponentObserver = observer;
@@ -77,7 +79,7 @@ public class SwipeSharedState implements SwipeAnimationListener {
mRecentsAnimationListener.removeListener(this);
mRecentsAnimationListener.cancelListener();
if (mLastAnimationRunning && mLastAnimationTarget != null) {
- Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(),
+ Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(),
finishAnimation
? mLastAnimationTarget::finishAnimation
: mLastAnimationTarget::cancelAnimation);
@@ -155,5 +157,10 @@ public class SwipeSharedState implements SwipeAnimationListener {
pw.println(prefix + "nextRunningTaskId=" + nextRunningTaskId);
pw.println(prefix + "lastAnimationCancelled=" + mLastAnimationCancelled);
pw.println(prefix + "lastAnimationRunning=" + mLastAnimationRunning);
+ pw.println(prefix + "logTraceId=" + mLogId);
+ }
+
+ public void setLogTraceId(int logId) {
+ this.mLogId = logId;
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
index fd4592307..1af0db07d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
@@ -36,8 +36,6 @@ import android.view.View;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.ItemInfo;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
@@ -267,12 +265,16 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
@Override
protected ActivityOptions makeLaunchOptions(Activity activity) {
- return ActivityOptionsCompat.makeFreeformOptions();
+ ActivityOptions activityOptions = ActivityOptionsCompat.makeFreeformOptions();
+ // Arbitrary bounds only because freeform is in dev mode right now
+ Rect r = new Rect(50, 50, 200, 200);
+ activityOptions.setLaunchBounds(r);
+ return activityOptions;
}
@Override
protected boolean onActivityStarted(BaseDraggingActivity activity) {
- Launcher.getLauncher(activity).getStateManager().goToState(LauncherState.NORMAL);
+ activity.returnToHomescreen();
return true;
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 86ba85578..f32182600 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -23,6 +23,8 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_HINTS_IN_OVERVIEW
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.FAKE_LANDSCAPE_UI;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
@@ -40,7 +42,6 @@ import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
-import android.app.TaskInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -50,8 +51,6 @@ import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Region;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
@@ -61,29 +60,26 @@ import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import android.view.Choreographer;
-import android.view.Display;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.Surface;
-import android.view.WindowManager;
import androidx.annotation.BinderThread;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.config.BaseFlags;
import com.android.launcher3.logging.EventLogArray;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.util.LooperExecutor;
-import com.android.launcher3.util.UiThreadHelper;
+import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
@@ -96,6 +92,7 @@ import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
+import com.android.quickstep.util.AssistantUtilities;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -107,7 +104,6 @@ import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import com.android.systemui.shared.system.RecentsAnimationListener;
import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
-import com.android.systemui.shared.system.TaskInfoCompat;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -136,11 +132,14 @@ class ArgList extends LinkedList<String> {
*/
@TargetApi(Build.VERSION_CODES.Q)
public class TouchInteractionService extends Service implements
- NavigationModeChangeListener, DisplayListener {
+ NavigationModeChangeListener, DefaultDisplay.DisplayInfoChangeListener {
+
+ /**
+ * NOTE: This value should be kept same as
+ * ActivityTaskManagerService#INTENT_EXTRA_LOG_TRACE_ID in platform
+ */
+ public static final String INTENT_EXTRA_LOG_TRACE_ID = "INTENT_EXTRA_LOG_TRACE_ID";
- public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor();
- public static final LooperExecutor BACKGROUND_EXECUTOR =
- new LooperExecutor(UiThreadHelper.getBackgroundLooper());
public static final EventLogArray TOUCH_INTERACTION_LOG =
new EventLogArray("touch_interaction_log", 40);
@@ -161,9 +160,9 @@ public class TouchInteractionService extends Service implements
public void onInitialize(Bundle bundle) {
mISystemUiProxy = ISystemUiProxy.Stub
.asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
- MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
- MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
- MAIN_THREAD_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
+ MAIN_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
+ MAIN_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
+ MAIN_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
sIsInitialized = true;
}
@@ -198,7 +197,7 @@ public class TouchInteractionService extends Service implements
@Override
public void onAssistantVisibilityChanged(float visibility) {
mLastAssistantVisibility = visibility;
- MAIN_THREAD_EXECUTOR.execute(
+ MAIN_EXECUTOR.execute(
TouchInteractionService.this::onAssistantVisibilityChanged);
}
@@ -214,13 +213,13 @@ public class TouchInteractionService extends Service implements
isButton, gestureSwipeLeft, activityControl.getContainerType());
if (completed && !isButton && shouldNotifyBackGesture()) {
- BACKGROUND_EXECUTOR.execute(TouchInteractionService.this::tryNotifyBackGesture);
+ UI_HELPER_EXECUTOR.execute(TouchInteractionService.this::tryNotifyBackGesture);
}
}
public void onSystemUiStateChanged(int stateFlags) {
mSystemUiStateFlags = stateFlags;
- MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiFlagsChanged);
+ MAIN_EXECUTOR.execute(TouchInteractionService.this::onSystemUiFlagsChanged);
}
/** Deprecated methods **/
@@ -244,6 +243,7 @@ public class TouchInteractionService extends Service implements
private static boolean sConnected = false;
private static boolean sIsInitialized = false;
private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState();
+ private int mLogId;
public static boolean isConnected() {
return sConnected;
@@ -323,8 +323,7 @@ public class TouchInteractionService extends Service implements
registerReceiver(mUserUnlockedReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
}
- mDefaultDisplayId = getSystemService(WindowManager.class).getDefaultDisplay()
- .getDisplayId();
+ mDefaultDisplayId = DefaultDisplay.INSTANCE.get(this).getInfo().id;
String blockingActivity = getString(R.string.gesture_blocking_activity);
mGestureBlockingActivity = TextUtils.isEmpty(blockingActivity) ? null :
ComponentName.unflattenFromString(blockingActivity);
@@ -391,9 +390,8 @@ public class TouchInteractionService extends Service implements
return;
}
- Display defaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay();
- Point realSize = new Point();
- defaultDisplay.getRealSize(realSize);
+ DefaultDisplay.Info displayInfo = DefaultDisplay.INSTANCE.get(this).getInfo();
+ Point realSize = new Point(displayInfo.realSize);
mSwipeTouchRegion.set(0, 0, realSize.x, realSize.y);
if (mMode == Mode.NO_BUTTON) {
int touchHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
@@ -415,7 +413,7 @@ public class TouchInteractionService extends Service implements
} else {
mAssistantLeftRegion.setEmpty();
mAssistantRightRegion.setEmpty();
- switch (defaultDisplay.getRotation()) {
+ switch (displayInfo.rotation) {
case Surface.ROTATION_90:
mSwipeTouchRegion.left = mSwipeTouchRegion.right
- getNavbarSize(ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
@@ -438,10 +436,9 @@ public class TouchInteractionService extends Service implements
}
if (mMode.hasGestures != newMode.hasGestures) {
if (newMode.hasGestures) {
- getSystemService(DisplayManager.class).registerDisplayListener(
- this, MAIN_THREAD_EXECUTOR.getHandler());
+ DefaultDisplay.INSTANCE.get(this).addChangeListener(this);
} else {
- getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+ DefaultDisplay.INSTANCE.get(this).removeChangeListener(this);
}
}
mMode = newMode;
@@ -457,14 +454,8 @@ public class TouchInteractionService extends Service implements
}
@Override
- public void onDisplayAdded(int i) { }
-
- @Override
- public void onDisplayRemoved(int i) { }
-
- @Override
- public void onDisplayChanged(int displayId) {
- if (displayId != mDefaultDisplayId) {
+ public void onDisplayInfoChanged(DefaultDisplay.Info info, int flags) {
+ if (info.id != mDefaultDisplayId) {
return;
}
@@ -529,7 +520,7 @@ public class TouchInteractionService extends Service implements
}
disposeEventHandlers();
if (mMode.hasGestures) {
- getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+ DefaultDisplay.INSTANCE.get(this).removeChangeListener(this);
}
sConnected = false;
@@ -554,9 +545,12 @@ public class TouchInteractionService extends Service implements
Log.e(TAG, "Unknown event " + ev);
return;
}
+
MotionEvent event = (MotionEvent) ev;
- TOUCH_INTERACTION_LOG.addLog("onMotionEvent", event.getActionMasked());
if (event.getAction() == ACTION_DOWN) {
+ mLogId = TOUCH_INTERACTION_LOG.generateAndSetLogId();
+ sSwipeSharedState.setLogTraceId(mLogId);
+
if (mSwipeTouchRegion.contains(event.getX(), event.getY())) {
boolean useSharedState = mConsumer.useSharedSwipeState();
mConsumer.onConsumerAboutToBeSwitched();
@@ -576,6 +570,8 @@ public class TouchInteractionService extends Service implements
mUncheckedConsumer = InputConsumer.NO_OP;
}
}
+
+ TOUCH_INTERACTION_LOG.addLog("onMotionEvent", event.getActionMasked());
mUncheckedConsumer.onMotionEvent(event);
}
@@ -653,16 +649,14 @@ public class TouchInteractionService extends Service implements
mOverviewComponentObserver.getActivityControlHelper();
boolean forceOverviewInputConsumer = false;
- if (isExcludedAssistant(runningTaskInfo)) {
+ if (AssistantUtilities.isExcludedAssistant(runningTaskInfo)) {
// In the case where we are in the excluded assistant state, ignore it and treat the
// running activity as the task behind the assistant
- runningTaskInfo = mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT);
- if (!ActivityManagerWrapper.isHomeTask(runningTaskInfo)) {
- final ComponentName homeComponent =
- mOverviewComponentObserver.getHomeIntent().getComponent();
- forceOverviewInputConsumer =
- runningTaskInfo.baseIntent.getComponent().equals(homeComponent);
- }
+ runningTaskInfo = mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT /* ignoreActivityType */);
+ ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent();
+ ComponentName runningComponent = runningTaskInfo.baseIntent.getComponent();
+ forceOverviewInputConsumer =
+ runningComponent != null && runningComponent.equals(homeComponent);
}
if (runningTaskInfo == null && !sSwipeSharedState.goingToLauncher
@@ -676,9 +670,9 @@ public class TouchInteractionService extends Service implements
return createOtherActivityInputConsumer(event, info);
} else if (sSwipeSharedState.goingToLauncher || activityControl.isResumed()
|| forceOverviewInputConsumer) {
- return createOverviewInputConsumer(event);
+ return createOverviewInputConsumer(event, forceOverviewInputConsumer);
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityControl.isInLiveTileMode()) {
- return createOverviewInputConsumer(event);
+ return createOverviewInputConsumer(event, forceOverviewInputConsumer);
} else if (mGestureBlockingActivity != null && runningTaskInfo != null
&& mGestureBlockingActivity.equals(runningTaskInfo.topActivity)) {
return mResetGestureInputConsumer;
@@ -687,12 +681,6 @@ public class TouchInteractionService extends Service implements
}
}
- private boolean isExcludedAssistant(TaskInfo info) {
- return info != null
- && TaskInfoCompat.getActivityType(info) == ACTIVITY_TYPE_ASSISTANT
- && (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
- }
-
private boolean disableHorizontalSwipe(MotionEvent event) {
// mExclusionRegion can change on binder thread, use a local instance here.
Region exclusionRegion = mExclusionRegion;
@@ -718,19 +706,20 @@ public class TouchInteractionService extends Service implements
return new OtherActivityInputConsumer(this, runningTaskInfo,
shouldDefer, mOverviewCallbacks, this::onConsumerInactive,
sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
- disableHorizontalSwipe(event), factory);
+ disableHorizontalSwipe(event), factory, mLogId);
}
private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
if (mMode == Mode.NO_BUTTON && taskInfo != null) {
return new DeviceLockedInputConsumer(this, sSwipeSharedState, mInputMonitorCompat,
- mSwipeTouchRegion, taskInfo.taskId);
+ mSwipeTouchRegion, taskInfo.taskId, mLogId);
} else {
return mResetGestureInputConsumer;
}
}
- public InputConsumer createOverviewInputConsumer(MotionEvent event) {
+ public InputConsumer createOverviewInputConsumer(MotionEvent event,
+ boolean forceOverviewInputConsumer) {
final ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper();
BaseDraggingActivity activity = activityControl.getCreatedActivity();
@@ -738,7 +727,10 @@ public class TouchInteractionService extends Service implements
return mResetGestureInputConsumer;
}
- if (activity.getRootView().hasWindowFocus() || sSwipeSharedState.goingToLauncher) {
+ if (activity.getRootView().hasWindowFocus()
+ || sSwipeSharedState.goingToLauncher
+ || (BaseFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
+ && forceOverviewInputConsumer)) {
return new OverviewInputConsumer(activity, mInputMonitorCompat,
false /* startingInActivityBounds */);
} else {
@@ -788,7 +780,8 @@ public class TouchInteractionService extends Service implements
}
// Pass null animation handler to indicate this start is preload.
- startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(), null);
+ startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(),
+ null);
}
@Override
@@ -897,7 +890,7 @@ public class TouchInteractionService extends Service implements
}
public static void startRecentsActivityAsync(Intent intent, RecentsAnimationListener listener) {
- BACKGROUND_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
+ UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
.startRecentsActivity(intent, null, listener, null, null));
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index e1085e608..2fa4feb33 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -26,14 +26,14 @@ import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
-import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE;
-import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.HOME;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.LAST_TASK;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.NEW_TASK;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.RECENTS;
+import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
+import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@@ -74,13 +74,14 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
-import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState;
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.inputconsumers.InputConsumer;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.util.ClipAnimationHelper.TargetAlphaProvider;
import com.android.quickstep.util.RectFSpringAnim;
+import com.android.quickstep.util.ShelfPeekAnim;
+import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.views.LiveTileOverlay;
import com.android.quickstep.views.RecentsView;
@@ -192,7 +193,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
Math.min(1 / MIN_PROGRESS_FOR_OVERVIEW, 1 / (1 - MIN_PROGRESS_FOR_OVERVIEW));
private static final String SCREENSHOT_CAPTURED_EVT = "ScreenshotCaptured";
- private static final long SHELF_ANIM_DURATION = 240;
public static final long RECENTS_ATTACH_DURATION = 300;
/**
@@ -206,8 +206,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
private boolean mIsShelfPeeking;
private boolean mContinuingLastGesture;
- // To avoid UI jump when gesture is started, we offset the animation by the threshold.
- private float mShiftAtGestureStart = 0;
private ThumbnailData mTaskSnapshot;
@@ -442,7 +440,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
@Override
public void onMotionPauseChanged(boolean isPaused) {
- setShelfState(isPaused ? PEEK : HIDE, OVERSHOOT_1_2, SHELF_ANIM_DURATION);
+ setShelfState(isPaused ? PEEK : HIDE, ShelfPeekAnim.INTERPOLATOR, ShelfPeekAnim.DURATION);
}
public void maybeUpdateRecentsAttachedState() {
@@ -479,8 +477,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask;
if (animate) {
// Only animate if an adjacent task view is visible on screen.
- TaskView adjacentTask1 = mRecentsView.getTaskViewAt(runningTaskIndex + 1);
- TaskView adjacentTask2 = mRecentsView.getTaskViewAt(runningTaskIndex - 1);
+ TaskView adjacentTask1 = mRecentsView.getNextTaskView();
+ TaskView adjacentTask2 = mRecentsView.getPreviousTaskView();
float prevTranslationX = mRecentsView.getTranslationX();
mRecentsView.setTranslationX(0);
animate = (adjacentTask1 != null && adjacentTask1.getGlobalVisibleRect(TEMP_RECT))
@@ -580,9 +578,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
// Normalize the progress to 0 to 1, as the animation controller will clamp it to that
// anyway. The controller mimics the drag length factor by applying it to its interpolators.
float progress = mCurrentShift.value / mDragLengthFactor;
- mLauncherTransitionController.setPlayFraction(
- progress <= mShiftAtGestureStart || mShiftAtGestureStart >= 1
- ? 0 : (progress - mShiftAtGestureStart) / (1 - mShiftAtGestureStart));
+ mLauncherTransitionController.setPlayFraction(progress);
}
/**
@@ -590,8 +586,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
*/
private void updateSysUiFlags(float windowProgress) {
if (mRecentsView != null) {
- TaskView centermostTask = mRecentsView.getTaskViewAt(mRecentsView
- .getPageNearestToCenterOfScreen());
+ TaskView centermostTask = mRecentsView.getTaskViewNearestToCenterOfScreen();
int centermostTaskFlags = centermostTask == null ? 0
: centermostTask.getThumbnail().getSysUiStatusNavFlags();
boolean useHomeScreenFlags = windowProgress > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
@@ -623,7 +618,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
@Override
public void onGestureStarted() {
notifyGestureStartedAsync();
- mShiftAtGestureStart = mCurrentShift.value;
setStateOnUiThread(STATE_GESTURE_STARTED);
mGestureStarted = true;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 2e9c0a3c4..7f1aae5e2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -176,7 +176,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
protected void applyLoadPlan(ArrayList<Task> tasks) {
// When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher
// as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
- // track the index of the next task appropriately, as it we are switching on any other app.
+ // track the index of the next task appropriately, as if we are switching on any other app.
if (mRunningTaskInfo != null && mRunningTaskInfo.taskId == mRunningTaskId) {
// Check if the task list has running task
boolean found = false;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 3d763ab52..b24c78810 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -22,8 +22,9 @@ import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
-import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
+import static com.android.quickstep.TouchInteractionService.INTENT_EXTRA_LOG_TRACE_ID;
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
+import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
import android.content.ComponentName;
import android.content.Context;
@@ -35,10 +36,10 @@ import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
-import android.view.WindowManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.LockScreenRecentsActivity;
import com.android.quickstep.MultiStateCallback;
import com.android.quickstep.SwipeSharedState;
@@ -76,6 +77,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
private final PointF mTouchDown = new PointF();
private final ClipAnimationHelper mClipAnimationHelper;
+ private int mLogId;
private final ClipAnimationHelper.TransformParams mTransformParams;
private final Point mDisplaySize;
private final MultiStateCallback mStateCallback;
@@ -90,19 +92,20 @@ public class DeviceLockedInputConsumer implements InputConsumer,
private SwipeAnimationTargetSet mTargetSet;
public DeviceLockedInputConsumer(Context context, SwipeSharedState swipeSharedState,
- InputMonitorCompat inputMonitorCompat, RectF swipeTouchRegion, int runningTaskId) {
+ InputMonitorCompat inputMonitorCompat, RectF swipeTouchRegion, int runningTaskId,
+ int logId) {
mContext = context;
mTouchSlopSquared = squaredTouchSlop(context);
mSwipeSharedState = swipeSharedState;
mClipAnimationHelper = new ClipAnimationHelper(context);
+ mLogId = logId;
mTransformParams = new ClipAnimationHelper.TransformParams();
mInputMonitorCompat = inputMonitorCompat;
mSwipeTouchRegion = swipeTouchRegion;
mRunningTaskId = runningTaskId;
// Do not use DeviceProfile as the user data might be locked
- mDisplaySize = new Point();
- context.getSystemService(WindowManager.class).getDefaultDisplay().getRealSize(mDisplaySize);
+ mDisplaySize = DefaultDisplay.INSTANCE.get(context).getInfo().realSize;
// Init states
mStateCallback = new MultiStateCallback(STATE_NAMES);
@@ -205,7 +208,8 @@ public class DeviceLockedInputConsumer implements InputConsumer,
Intent intent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_DEFAULT)
.setComponent(new ComponentName(mContext, LockScreenRecentsActivity.class))
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ .putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
mInputMonitorCompat.pilferPointers();
startRecentsActivityAsync(intent, newListenerSet);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
index 6ec1da0c4..e0ff8afe6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
@@ -50,7 +50,6 @@ import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.ObjectWrapper;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.SwipeAnimationTargetSet;
-import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 86766d99f..e41880df5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -22,11 +22,11 @@ import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
-
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
+import static com.android.quickstep.TouchInteractionService.INTENT_EXTRA_LOG_TRACE_ID;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -35,6 +35,7 @@ import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.Intent;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Build;
@@ -43,12 +44,13 @@ import android.os.Looper;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
-
+import androidx.annotation.UiThread;
import com.android.launcher3.R;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.BaseSwipeUpHandler;
+import com.android.quickstep.BaseSwipeUpHandler.Factory;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.SwipeSharedState;
import com.android.quickstep.SysUINavigationMode;
@@ -59,11 +61,8 @@ import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
-
import java.util.function.Consumer;
-import androidx.annotation.UiThread;
-
/**
* Input consumer for handling events originating from an activity other than Launcher
*/
@@ -119,14 +118,16 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
true /* restoreHomeStackPosition */);
};
+ private int mLogId;
public OtherActivityInputConsumer(Context base, RunningTaskInfo runningTaskInfo,
boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
Consumer<OtherActivityInputConsumer> onCompleteCallback,
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
RectF swipeTouchRegion, boolean disableHorizontalSwipe,
- BaseSwipeUpHandler.Factory handlerFactory) {
+ Factory handlerFactory, int logId) {
super(base);
+ mLogId = logId;
mMainThreadHandler = new Handler(Looper.getMainLooper());
mRunningTask = runningTaskInfo;
@@ -341,7 +342,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
RecentsAnimationListenerSet newListenerSet =
mSwipeSharedState.newRecentsAnimationListenerSet();
newListenerSet.addListener(handler);
- startRecentsActivityAsync(handler.getLaunchIntent(), newListenerSet);
+ Intent intent = handler.getLaunchIntent();
+ intent.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
+ startRecentsActivityAsync(intent, newListenerSet);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
index 05cbb789d..f40d55263 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
@@ -22,9 +22,9 @@ import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
-import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.content.Context;
+import android.content.Intent;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
@@ -34,12 +34,9 @@ import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.Utilities;
import com.android.launcher3.logging.StatsLogUtils;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
-import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.util.NavBarPosition;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
public class OverviewWithoutFocusInputConsumer implements InputConsumer {
@@ -148,9 +145,9 @@ public class OverviewWithoutFocusInputConsumer implements InputConsumer {
}
if (triggerQuickstep) {
- OverviewCallbacks.get(mContext).closeAllWindows();
- ActivityManagerWrapper.getInstance()
- .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
+ mContext.startActivity(new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
TOUCH_INTERACTION_LOG.addLog("startQuickstep");
BaseActivity activity = BaseDraggingActivity.fromContext(mContext);
int pageIndex = -1; // This number doesn't reflect workspace page index.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java
new file mode 100644
index 000000000..b251f9e69
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 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.logging;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.appprediction.PredictionUiStateManager;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+
+/**
+ * This class handles AOSP MetricsLogger function calls and logging around
+ * quickstep interactions and app launches.
+ */
+@SuppressWarnings("unused")
+public class UserEventDispatcherAppPredictionExtension extends UserEventDispatcherExtension {
+
+ public static final int ALL_APPS_PREDICTION_TIPS = 2;
+
+ private static final String TAG = "UserEventDispatcher";
+
+ public UserEventDispatcherAppPredictionExtension(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onFillInLogContainerData(
+ @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target,
+ @NonNull LauncherLogProto.Target targetParent) {
+ PredictionUiStateManager.fillInPredictedRank(itemInfo, target);
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
index 90989feb4..a12ae7a45 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -37,6 +37,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.views.RecentsView;
@@ -50,8 +51,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.
import com.android.systemui.shared.system.TransactionCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import java.util.function.BiFunction;
-
/**
* Utility class to handle window clip animation
*/
@@ -213,6 +212,11 @@ public class ClipAnimationHelper {
}
mCurrentCornerRadius = cornerRadius;
}
+ // Fade out Assistant overlay.
+ if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT
+ && app.isNotInRecents) {
+ alpha = 1 - Interpolators.DEACCEL_2_5.getInterpolation(progress);
+ }
} else if (targetSet.hasRecents) {
// If home has a different target then recents, reverse anim the
// home target.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
index 3ce341d8c..bbb318a02 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
@@ -21,9 +21,9 @@ import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import android.content.Context;
import android.view.Surface;
-import android.view.WindowManager;
import com.android.launcher3.graphics.RotationMode;
+import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.SysUINavigationMode;
/**
@@ -36,8 +36,7 @@ public class NavBarPosition {
public NavBarPosition(Context context) {
mMode = SysUINavigationMode.getMode(context);
- mDisplayRotation = context.getSystemService(WindowManager.class)
- .getDefaultDisplay().getRotation();
+ mDisplayRotation = DefaultDisplay.INSTANCE.get(context).getInfo().rotation;
}
public boolean isRightEdge() {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
index 14083dd95..b1999d716 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
@@ -15,11 +15,13 @@
*/
package com.android.quickstep.util;
-import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.graphics.Rect;
import android.util.ArraySet;
+import androidx.annotation.UiThread;
+
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
@@ -31,8 +33,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.Set;
import java.util.function.Consumer;
-import androidx.annotation.UiThread;
-
/**
* Wrapper around {@link RecentsAnimationListener} which delegates callbacks to multiple listeners
* on the main thread
@@ -82,7 +82,7 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
if (mCancelled) {
targetSet.cancelAnimation();
} else {
- Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
+ Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationStart(targetSet);
}
@@ -92,14 +92,14 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
@Override
public final void onAnimationCanceled(ThumbnailData thumbnailData) {
- Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
+ Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationCanceled();
}
});
// TODO: handle the transition better instead of simply using a transition delay.
if (thumbnailData != null) {
- MAIN_THREAD_EXECUTOR.getHandler().postDelayed(() -> mController.cleanupScreenshot(),
+ MAIN_EXECUTOR.getHandler().postDelayed(() -> mController.cleanupScreenshot(),
TRANSITION_DELAY);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java
new file mode 100644
index 000000000..83bc41623
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_SHELF_ANIM;
+import static com.android.launcher3.LauncherState.BACKGROUND_APP;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.uioverrides.states.OverviewState;
+
+/**
+ * Animates the shelf between states HIDE, PEEK, and OVERVIEW.
+ */
+
+public class ShelfPeekAnim {
+
+ public static final Interpolator INTERPOLATOR = OVERSHOOT_1_2;
+ public static final long DURATION = 240;
+
+ private final Launcher mLauncher;
+
+ private ShelfAnimState mShelfState;
+ private boolean mIsPeeking;
+
+ public ShelfPeekAnim(Launcher launcher) {
+ mLauncher = launcher;
+ }
+
+ /**
+ * Animates to the given state, canceling the previous animation if it was still running.
+ */
+ public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) {
+ if (mShelfState == shelfState) {
+ return;
+ }
+ mLauncher.getStateManager().cancelStateElementAnimation(INDEX_SHELF_ANIM);
+ mShelfState = shelfState;
+ mIsPeeking = mShelfState == ShelfAnimState.PEEK || mShelfState == ShelfAnimState.HIDE;
+ if (mShelfState == ShelfAnimState.CANCEL) {
+ return;
+ }
+ float shelfHiddenProgress = BACKGROUND_APP.getVerticalProgress(mLauncher);
+ float shelfOverviewProgress = OVERVIEW.getVerticalProgress(mLauncher);
+ // Peek based on default overview progress so we can see hotseat if we're showing
+ // that instead of predictions in overview.
+ float defaultOverviewProgress = OverviewState.getDefaultVerticalProgress(mLauncher);
+ float shelfPeekingProgress = shelfHiddenProgress
+ - (shelfHiddenProgress - defaultOverviewProgress) * 0.25f;
+ float toProgress = mShelfState == ShelfAnimState.HIDE
+ ? shelfHiddenProgress
+ : mShelfState == ShelfAnimState.PEEK
+ ? shelfPeekingProgress
+ : shelfOverviewProgress;
+ Animator shelfAnim = mLauncher.getStateManager()
+ .createStateElementAnimation(INDEX_SHELF_ANIM, toProgress);
+ shelfAnim.setInterpolator(interpolator);
+ shelfAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mShelfState = ShelfAnimState.CANCEL;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ mIsPeeking = mShelfState == ShelfAnimState.PEEK;
+ }
+ });
+ shelfAnim.setDuration(duration).start();
+ }
+
+ /** @return Whether the shelf is currently peeking or animating to or from peeking. */
+ public boolean isPeeking() {
+ return mIsPeeking;
+ }
+
+ /** The various shelf states we can animate to. */
+ public enum ShelfAnimState {
+ HIDE(true), PEEK(true), OVERVIEW(false), CANCEL(false);
+
+ ShelfAnimState(boolean shouldPreformHaptic) {
+ this.shouldPreformHaptic = shouldPreformHaptic;
+ }
+
+ public final boolean shouldPreformHaptic;
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 1aa5365fd..958ef7d4f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -18,6 +18,7 @@ package com.android.quickstep.util;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import android.animation.Animator;
@@ -27,13 +28,11 @@ import android.animation.ObjectAnimator;
import android.view.View;
import android.view.ViewGroup;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BubbleTextView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
@@ -41,9 +40,8 @@ import com.android.launcher3.Workspace;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.anim.SpringObjectAnimator;
-import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.OverviewScrim;
-import com.android.launcher3.views.IconLabelDotView;
+import com.android.quickstep.views.RecentsView;
import java.util.ArrayList;
import java.util.List;
@@ -66,18 +64,12 @@ public class StaggeredWorkspaceAnim {
private final float mVelocity;
private final float mSpringTransY;
- // The original view of the {@link FloatingIconView}.
- private final View mOriginalView;
-
private final List<Animator> mAnimators = new ArrayList<>();
- /**
- * @param floatingViewOriginalView The FloatingIconView's original view.
- */
- public StaggeredWorkspaceAnim(Launcher launcher, @Nullable View floatingViewOriginalView,
- float velocity) {
+ public StaggeredWorkspaceAnim(Launcher launcher, float velocity, boolean animateOverviewScrim) {
+ prepareToAnimate(launcher);
+
mVelocity = velocity;
- mOriginalView = floatingViewOriginalView;
// Scale the translationY based on the initial velocity to better sync the workspace items
// with the floating view.
@@ -133,8 +125,10 @@ public class StaggeredWorkspaceAnim {
addStaggeredAnimationForView(qsb, grid.inv.numRows + 2, totalRows);
}
- addScrimAnimationForState(launcher, BACKGROUND_APP, 0);
- addScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
+ if (animateOverviewScrim) {
+ addScrimAnimationForState(launcher, BACKGROUND_APP, 0);
+ addScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
+ }
AnimatorListener resetClipListener = new AnimatorListenerAdapter() {
int numAnimations = mAnimators.size();
@@ -161,6 +155,21 @@ public class StaggeredWorkspaceAnim {
}
/**
+ * Setup workspace with 0 duration to prepare for our staggered animation.
+ */
+ private void prepareToAnimate(Launcher launcher) {
+ LauncherStateManager stateManager = launcher.getStateManager();
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ // setRecentsAttachedToAppWindow() will animate recents out.
+ builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW);
+ stateManager.createAtomicAnimation(BACKGROUND_APP, NORMAL, builder, ANIM_ALL, 0);
+ builder.build().start();
+
+ // Stop scrolling so that it doesn't interfere with the translation offscreen.
+ launcher.<RecentsView>getOverviewPanel().getScroller().forceFinished(true);
+ }
+
+ /**
* Starts the animation.
*/
public void start() {
@@ -192,35 +201,12 @@ public class StaggeredWorkspaceAnim {
springTransY.setStartDelay(startDelay);
mAnimators.add(springTransY);
- ObjectAnimator alpha = getAlphaAnimator(v, startDelay);
- if (v == mOriginalView) {
- // For IconLabelDotViews, we just want the label to fade in.
- // Icon, badge, and dots will animate in separately (controlled via FloatingIconView)
- if (v instanceof IconLabelDotView) {
- alpha.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- IconLabelDotView view = (IconLabelDotView) v;
- view.setIconVisible(false);
- view.setForceHideDot(true);
- }
- });
- } else {
- return;
- }
- }
-
v.setAlpha(0);
- mAnimators.add(alpha);
- }
-
- private ObjectAnimator getAlphaAnimator(View v, long startDelay) {
ObjectAnimator alpha = ObjectAnimator.ofFloat(v, View.ALPHA, 0f, 1f);
alpha.setInterpolator(LINEAR);
alpha.setDuration(ALPHA_DURATION_MS);
alpha.setStartDelay(startDelay);
- return alpha;
-
+ mAnimators.add(alpha);
}
private void addScrimAnimationForState(Launcher launcher, LauncherState state, long duration) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
index 381c27a28..3619d3a0e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
@@ -15,8 +15,8 @@
*/
package com.android.quickstep.util;
-import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
-import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.graphics.Rect;
@@ -68,25 +68,25 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet {
public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) {
mOnFinishListener.accept(this);
- BACKGROUND_EXECUTOR.execute(() -> {
+ UI_HELPER_EXECUTOR.execute(() -> {
controller.setInputConsumerEnabled(false);
controller.finish(toRecents, sendUserLeaveHint);
if (callback != null) {
- MAIN_THREAD_EXECUTOR.execute(callback);
+ MAIN_EXECUTOR.execute(callback);
}
});
}
public void enableInputConsumer() {
- BACKGROUND_EXECUTOR.submit(() -> {
+ UI_HELPER_EXECUTOR.submit(() -> {
controller.hideCurrentInputMethod();
controller.setInputConsumerEnabled(true);
});
}
public void setWindowThresholdCrossed(boolean thresholdCrossed) {
- BACKGROUND_EXECUTOR.execute(() -> {
+ UI_HELPER_EXECUTOR.execute(() -> {
controller.setAnimationTargetsBehindSystemBars(!thresholdCrossed);
if (mShouldMinimizeSplitScreen && thresholdCrossed) {
// NOTE: As a workaround for conflicting animations (Launcher animating the task
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 7fac81385..b06d4bc35 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -19,6 +19,7 @@ package com.android.quickstep.views;
import static android.provider.Settings.ACTION_APP_USAGE_SETTINGS;
import static com.android.launcher3.Utilities.prefixTextWithIcon;
+import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
import android.annotation.TargetApi;
import android.app.ActivityOptions;
@@ -41,7 +42,6 @@ import androidx.annotation.StringRes;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.systemui.shared.recents.model.Task;
@@ -117,7 +117,7 @@ public final class DigitalWellBeingToast {
return;
}
- Utilities.THREAD_POOL_EXECUTOR.execute(() -> {
+ THREAD_POOL_EXECUTOR.execute(() -> {
final AppUsageLimit usageLimit = mLauncherApps.getAppUsageLimit(
task.getTopComponent().getPackageName(),
UserHandle.of(task.key.userId));
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index 03441c87e..c2cb720ae 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -35,6 +35,7 @@ import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
+import android.widget.FrameLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Hotseat;
@@ -45,11 +46,14 @@ import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.appprediction.PredictionUiStateManager;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
+import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
import com.android.quickstep.util.LayoutUtils;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.RecentsExtraCard;
/**
* {@link RecentsView} used in Launcher activity
@@ -57,8 +61,29 @@ import com.android.quickstep.util.LayoutUtils;
@TargetApi(Build.VERSION_CODES.O)
public class LauncherRecentsView extends RecentsView<Launcher> implements StateListener {
+ private static final Rect sTempRect = new Rect();
+
private final TransformParams mTransformParams = new TransformParams();
+ private RecentsExtraCard mRecentsExtraCardPlugin;
+ private RecentsExtraViewContainer mRecentsExtraViewContainer;
+ private PluginListener<RecentsExtraCard> mRecentsExtraCardPluginListener =
+ new PluginListener<RecentsExtraCard>() {
+ @Override
+ public void onPluginConnected(RecentsExtraCard recentsExtraCard, Context context) {
+ createRecentsExtraCard();
+ mRecentsExtraCardPlugin = recentsExtraCard;
+ mRecentsExtraCardPlugin.setupView(context, mRecentsExtraViewContainer, mActivity);
+ }
+
+ @Override
+ public void onPluginDisconnected(RecentsExtraCard plugin) {
+ removeView(mRecentsExtraViewContainer);
+ mRecentsExtraCardPlugin = null;
+ mRecentsExtraViewContainer = null;
+ }
+ };
+
public LauncherRecentsView(Context context) {
this(context, null);
}
@@ -144,6 +169,25 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements StateL
LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect);
}
+ /**
+ * @return The translationX to apply to this view so that the first task is just offscreen.
+ */
+ public float getOffscreenTranslationX(float recentsScale) {
+ float offscreenX = NORMAL.getOverviewScaleAndTranslation(mActivity).translationX;
+ // Offset since scale pushes tasks outwards.
+ getTaskSize(sTempRect);
+ int taskWidth = sTempRect.width();
+ offscreenX += taskWidth * (recentsScale - 1) / 2;
+ if (mRunningTaskTileHidden) {
+ // The first task is hidden, so offset by its width.
+ offscreenX -= (taskWidth + getPageSpacing()) * recentsScale;
+ }
+ if (isRtl()) {
+ offscreenX = -offscreenX;
+ }
+ return offscreenX;
+ }
+
@Override
protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
@@ -264,4 +308,66 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements StateL
}
return super.shouldStealTouchFromSiblingsBelow(ev);
}
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ PluginManagerWrapper.INSTANCE.get(getContext())
+ .addPluginListener(mRecentsExtraCardPluginListener, RecentsExtraCard.class);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ PluginManagerWrapper.INSTANCE.get(getContext()).removePluginListener(
+ mRecentsExtraCardPluginListener);
+ }
+
+ @Override
+ protected int computeMinScrollX() {
+ if (canComputeScrollX() && !mIsRtl) {
+ return computeScrollX();
+ }
+ return super.computeMinScrollX();
+ }
+
+ @Override
+ protected int computeMaxScrollX() {
+ if (canComputeScrollX() && mIsRtl) {
+ return computeScrollX();
+ }
+ return super.computeMaxScrollX();
+ }
+
+ private boolean canComputeScrollX() {
+ return mRecentsExtraCardPlugin != null && getTaskViewCount() > 0
+ && !mDisallowScrollToClearAll;
+ }
+
+ private int computeScrollX() {
+ int scrollIndex = getTaskViewStartIndex() - 1;
+ while (scrollIndex >= 0 && getChildAt(scrollIndex) instanceof RecentsExtraViewContainer
+ && ((RecentsExtraViewContainer) getChildAt(scrollIndex)).isScrollable()) {
+ scrollIndex--;
+ }
+ return getScrollForPage(scrollIndex + 1);
+ }
+
+ private void createRecentsExtraCard() {
+ mRecentsExtraViewContainer = new RecentsExtraViewContainer(getContext());
+ FrameLayout.LayoutParams helpCardParams =
+ new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.MATCH_PARENT);
+ mRecentsExtraViewContainer.setLayoutParams(helpCardParams);
+ mRecentsExtraViewContainer.setScrollable(true);
+ addView(mRecentsExtraViewContainer, 0);
+ }
+
+ @Override
+ public void resetTaskVisuals() {
+ super.resetTaskVisuals();
+ if (mRecentsExtraViewContainer != null) {
+ mRecentsExtraViewContainer.setAlpha(mContentAlpha);
+ }
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsExtraViewContainer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsExtraViewContainer.java
new file mode 100644
index 000000000..1ea6d4a24
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsExtraViewContainer.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/**
+ * Empty view to house recents overview extra card
+ */
+public class RecentsExtraViewContainer extends FrameLayout implements RecentsView.PageCallbacks {
+
+ private boolean mScrollable = false;
+
+ public RecentsExtraViewContainer(Context context) {
+ super(context);
+ }
+
+ public RecentsExtraViewContainer(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public RecentsExtraViewContainer(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ /**
+ * Determine whether the view should be scrolled to in the recents overview, similar to the
+ * taskviews.
+ * @return true if viewed should be scrolled to, false if not
+ */
+ public boolean isScrollable() {
+ return mScrollable;
+ }
+
+ public void setScrollable(boolean scrollable) {
+ this.mScrollable = scrollable;
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index ef54d3f89..ca3b92aa7 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -34,9 +34,9 @@ import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
-import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -186,7 +186,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private final ViewPool<TaskView> mTaskViewPool;
private boolean mDwbToastShown;
- private boolean mDisallowScrollToClearAll;
+ protected boolean mDisallowScrollToClearAll;
private boolean mOverlayEnabled;
private boolean mFreezeViewVisibility;
@@ -227,7 +227,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return;
}
- BACKGROUND_EXECUTOR.execute(() -> {
+ UI_HELPER_EXECUTOR.execute(() -> {
TaskView taskView = getTaskView(taskId);
if (taskView == null) {
return;
@@ -271,7 +271,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
// Only valid until the launcher state changes to NORMAL
protected int mRunningTaskId = -1;
- private boolean mRunningTaskTileHidden;
+ protected boolean mRunningTaskTileHidden;
private Task mTmpRunningTask;
private boolean mRunningTaskIconScaledDown = false;
@@ -288,7 +288,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private LayoutTransition mLayoutTransition;
@ViewDebug.ExportedProperty(category = "launcher")
- private float mContentAlpha = 1;
+ protected float mContentAlpha = 1;
@ViewDebug.ExportedProperty(category = "launcher")
protected float mFullscreenProgress = 0;
@@ -305,6 +305,9 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private Layout mEmptyTextLayout;
private LiveTileOverlay mLiveTileOverlay;
+ // Keeps track of the index where the first TaskView should be
+ private int mTaskViewStartIndex = 0;
+
private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener =
(inMultiWindowMode) -> {
if (!inMultiWindowMode && mOverviewStateEnabled) {
@@ -328,7 +331,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
mClearAllButton = (ClearAllButton) LayoutInflater.from(context)
.inflate(R.layout.overview_clear_all_button, this, false);
mClearAllButton.setOnClickListener(this::dismissAllTasks);
-
mTaskViewPool = new ViewPool<>(context, this, R.layout.task, 20 /* max size */,
10 /* initial size */);
@@ -429,7 +431,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
super.onViewRemoved(child);
// Clear the task data for the removed child if it was visible
- if (child != mClearAllButton) {
+ if (child instanceof TaskView) {
TaskView taskView = (TaskView) child;
mHasVisibleTaskData.delete(taskView.getTask().key.id);
mTaskViewPool.recycle(taskView);
@@ -443,7 +445,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
public TaskView getTaskView(int taskId) {
for (int i = 0; i < getTaskViewCount(); i++) {
- TaskView tv = (TaskView) getChildAt(i);
+ TaskView tv = getTaskViewAt(i);
if (tv.getTask() != null && tv.getTask().key != null && tv.getTask().key.id == taskId) {
return tv;
}
@@ -535,28 +537,26 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
if (tasks == null || tasks.isEmpty()) {
- removeAllViews();
+ removeTasksViewsAndClearAllButton();
onTaskStackUpdated();
return;
}
- int oldChildCount = getChildCount();
-
// Unload existing visible task data
unloadVisibleTaskData();
- TaskView ignoreRestTaskView =
+ TaskView ignoreResetTaskView =
mIgnoreResetTaskId == -1 ? null : getTaskView(mIgnoreResetTaskId);
final int requiredTaskCount = tasks.size();
if (getTaskViewCount() != requiredTaskCount) {
- if (oldChildCount > 0) {
+ if (indexOfChild(mClearAllButton) != -1) {
removeView(mClearAllButton);
}
- for (int i = getChildCount(); i < requiredTaskCount; i++) {
+ for (int i = getTaskViewCount(); i < requiredTaskCount; i++) {
addView(mTaskViewPool.getView());
}
- while (getChildCount() > requiredTaskCount) {
+ while (getTaskViewCount() > requiredTaskCount) {
removeView(getChildAt(getChildCount() - 1));
}
if (requiredTaskCount > 0) {
@@ -566,7 +566,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
// Rebind and reset all task views
for (int i = requiredTaskCount - 1; i >= 0; i--) {
- final int pageIndex = requiredTaskCount - i - 1;
+ final int pageIndex = requiredTaskCount - i - 1 + mTaskViewStartIndex;
final Task task = tasks.get(i);
final TaskView taskView = (TaskView) getChildAt(pageIndex);
taskView.bind(task);
@@ -577,10 +577,12 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
TaskView runningTaskView = getRunningTaskView();
if (runningTaskView != null) {
setCurrentPage(indexOfChild(runningTaskView));
+ } else if (getTaskViewCount() > 0) {
+ setCurrentPage(indexOfChild(getTaskViewAt(0)));
}
}
- if (mIgnoreResetTaskId != -1 && getTaskView(mIgnoreResetTaskId) != ignoreRestTaskView) {
+ if (mIgnoreResetTaskId != -1 && getTaskView(mIgnoreResetTaskId) != ignoreResetTaskView) {
// If the taskView mapping is changing, do not preserve the visuals. Since we are
// mostly preserving the first task, and new taskViews are added to the end, it should
// generally map to the same task.
@@ -591,17 +593,28 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
updateEnabledOverlays();
}
+ private void removeTasksViewsAndClearAllButton() {
+ for (int i = getTaskViewCount() - 1; i >= 0; i--) {
+ removeView(getTaskViewAt(i));
+ }
+ if (indexOfChild(mClearAllButton) != -1) {
+ removeView(mClearAllButton);
+ }
+ }
+
public int getTaskViewCount() {
- // Account for the clear all button.
- int childCount = getChildCount();
- return childCount == 0 ? 0 : childCount - 1;
+ int taskViewCount = getChildCount() - mTaskViewStartIndex;
+ if (indexOfChild(mClearAllButton) != -1) {
+ taskViewCount--;
+ }
+ return taskViewCount;
}
protected void onTaskStackUpdated() { }
public void resetTaskVisuals() {
for (int i = getTaskViewCount() - 1; i >= 0; i--) {
- TaskView taskView = (TaskView) getChildAt(i);
+ TaskView taskView = getTaskViewAt(i);
if (mIgnoreResetTaskId != taskView.getTask().key.id) {
taskView.resetVisualProperties();
taskView.setStableAlpha(mContentAlpha);
@@ -707,7 +720,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
/**
- * Iterates through all thet asks, and loads the associated task data for newly visible tasks,
+ * Iterates through all the tasks, and loads the associated task data for newly visible tasks,
* and unloads the associated task data for tasks that are no longer visible.
*/
public void loadVisibleTaskData() {
@@ -718,15 +731,16 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
int centerPageIndex = getPageNearestToCenterOfScreen();
- int numChildren = getTaskViewCount();
+ int numChildren = getChildCount();
int lower = Math.max(0, centerPageIndex - 2);
int upper = Math.min(centerPageIndex + 2, numChildren - 1);
// Update the task data for the in/visible children
- for (int i = 0; i < numChildren; i++) {
- TaskView taskView = (TaskView) getChildAt(i);
+ for (int i = 0; i < getTaskViewCount(); i++) {
+ TaskView taskView = getTaskViewAt(i);
Task task = taskView.getTask();
- boolean visible = lower <= i && i <= upper;
+ int index = indexOfChild(taskView);
+ boolean visible = lower <= index && index <= upper;
if (visible) {
if (task == mTmpRunningTask) {
// Skip loading if this is the task that we are animating into
@@ -801,6 +815,10 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return tv == null ? -1 : indexOfChild(tv);
}
+ public int getTaskViewStartIndex() {
+ return mTaskViewStartIndex;
+ }
+
/**
* Reloads the view if anything in recents changed.
*/
@@ -856,10 +874,10 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
*/
public void showCurrentTask(int runningTaskId) {
if (getTaskView(runningTaskId) == null) {
- boolean wasEmpty = getChildCount() == 0;
+ boolean wasEmpty = getTaskViewCount() == 0;
// Add an empty view for now until the task plan is loaded and applied
final TaskView taskView = mTaskViewPool.getView();
- addView(taskView, 0);
+ addView(taskView, mTaskViewStartIndex);
if (wasEmpty) {
addView(mClearAllButton);
}
@@ -925,14 +943,13 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
if (runningTaskView == null) {
// Launch the first task
if (getTaskViewCount() > 0) {
- getTaskViewAt(0).launchTask(true /* animate */);
+ getTaskViewAt(0).launchTask(true);
}
} else {
- TaskView nextTaskView = getNextTaskView();
- if (nextTaskView != null) {
- nextTaskView.launchTask(true /* animate */);
+ if (getNextTaskView() != null) {
+ getNextTaskView().launchTask(true);
} else {
- runningTaskView.launchTask(true /* animate */);
+ runningTaskView.launchTask(true);
}
}
}
@@ -1196,7 +1213,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
int count = getTaskViewCount();
for (int i = 0; i < count; i++) {
- addDismissedTaskAnimations(getChildAt(i), anim, duration);
+ addDismissedTaskAnimations(getTaskViewAt(i), anim, duration);
}
mPendingAnimation = pendingAnimation;
@@ -1204,7 +1221,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
if (onEndListener.isSuccess) {
// Remove all the task views now
ActivityManagerWrapper.getInstance().removeAllRecentTasks();
- removeAllViews();
+ removeTasksViewsAndClearAllButton();
startHome();
}
mPendingAnimation = null;
@@ -1351,26 +1368,50 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
child.setAlpha(mContentAlpha);
}
- /**
- * @return The most recent task that is older than the currently running task. If there is
- * currently no running task or there is no task older than it, then return null.
- */
@Nullable
public TaskView getNextTaskView() {
- TaskView runningTaskView = getRunningTaskView();
- if (runningTaskView == null) {
- return null;
- }
- return getTaskViewAt(indexOfChild(runningTaskView) + 1);
+ return getTaskViewAtByAbsoluteIndex(getRunningTaskIndex() + 1);
+ }
+
+ @Nullable
+ public TaskView getPreviousTaskView() {
+ return getTaskViewAtByAbsoluteIndex(getRunningTaskIndex() - 1);
+ }
+
+ @Nullable
+ public TaskView getCurrentPageTaskView() {
+ return getTaskViewAtByAbsoluteIndex(getCurrentPage());
+ }
+
+ @Nullable
+ public TaskView getNextPageTaskView() {
+ return getTaskViewAtByAbsoluteIndex(getNextPage());
+ }
+
+ @Nullable
+ public TaskView getTaskViewNearestToCenterOfScreen() {
+ return getTaskViewAtByAbsoluteIndex(getPageNearestToCenterOfScreen());
}
+ /**
+ * Returns null instead of indexOutOfBoundsError when index is not in range
+ */
+ @Nullable
public TaskView getTaskViewAt(int index) {
- View child = getChildAt(index);
- return child == mClearAllButton ? null : (TaskView) child;
+ return getTaskViewAtByAbsoluteIndex(index + mTaskViewStartIndex);
+ }
+
+ @Nullable
+ private TaskView getTaskViewAtByAbsoluteIndex(int index) {
+ if (index < getChildCount() && index >= 0) {
+ View child = getChildAt(index);
+ return child instanceof TaskView ? (TaskView) child : null;
+ }
+ return null;
}
public void updateEmptyMessage() {
- boolean isEmpty = getChildCount() == 0;
+ boolean isEmpty = getTaskViewCount() == 0;
boolean hasSizeChanged = mLastMeasureSize.x != getWidth()
|| mLastMeasureSize.y != getHeight();
if (isEmpty == mShowEmptyMessage && !hasSizeChanged) {
@@ -1504,7 +1545,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
throw new IllegalStateException("Another pending animation is still running");
}
- int count = getChildCount();
+ int count = getTaskViewCount();
if (count == 0) {
return new PendingAnimation(new AnimatorSet());
}
@@ -1677,18 +1718,38 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
@Override
protected int computeMinScrollX() {
- if (mIsRtl && mDisallowScrollToClearAll) {
- // We aren't showing the clear all button, so use the leftmost task as the min scroll.
- return getScrollForPage(getTaskViewCount() - 1);
+ if (getTaskViewCount() > 0) {
+ if (mDisallowScrollToClearAll) {
+ // We aren't showing the clear all button,
+ // so use the leftmost task as the min scroll.
+ if (mIsRtl) {
+ return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
+ }
+ return getScrollForPage(mTaskViewStartIndex);
+ }
+ if (mIsRtl) {
+ return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
+ }
+ return getScrollForPage(mTaskViewStartIndex);
}
return super.computeMinScrollX();
}
@Override
protected int computeMaxScrollX() {
- if (!mIsRtl && mDisallowScrollToClearAll) {
- // We aren't showing the clear all button, so use the rightmost task as the max scroll.
- return getScrollForPage(getTaskViewCount() - 1);
+ if (getTaskViewCount() > 0) {
+ if (mDisallowScrollToClearAll) {
+ // We aren't showing the clear all button,
+ // so use the rightmost task as the min scroll.
+ if (mIsRtl) {
+ return getScrollForPage(mTaskViewStartIndex);
+ }
+ return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
+ }
+ if (mIsRtl) {
+ return getScrollForPage(mTaskViewStartIndex);
+ }
+ return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
}
return super.computeMaxScrollX();
}
@@ -1740,7 +1801,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
int overlayEnabledPage = mOverlayEnabled ? getNextPage() : -1;
int taskCount = getTaskViewCount();
for (int i = 0; i < taskCount; i++) {
- ((TaskView) getChildAt(i)).setOverlayEnabled(i == overlayEnabledPage);
+ getTaskViewAt(i).setOverlayEnabled(i == overlayEnabledPage);
}
}
@@ -1760,4 +1821,25 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
final WindowInsets insets = getRootWindowInsets();
return Math.max(insets.getSystemGestureInsets().right, insets.getSystemWindowInsetRight());
}
+
+ @Override
+ public void addView(View child, int index) {
+ super.addView(child, index);
+ if (isExtraCardView(child, index)) {
+ mTaskViewStartIndex++;
+ }
+ }
+
+ @Override
+ public void removeView(View view) {
+ if (isExtraCardView(view, indexOfChild(view))) {
+ mTaskViewStartIndex--;
+ }
+ super.removeView(view);
+ }
+
+ private boolean isExtraCardView(View view, int index) {
+ return !(view instanceof TaskView) && !(view instanceof ClearAllButton)
+ && index <= mTaskViewStartIndex;
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
index c1f6b82ec..07d079664 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
@@ -26,6 +26,7 @@ import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
@@ -40,6 +41,7 @@ import com.android.launcher3.R;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.TaskOverlayFactory;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index 7f1e8980b..044292aa6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -39,24 +39,28 @@ import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Property;
import android.view.View;
+import android.view.ViewGroup;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskOverlayFactory.TaskOverlay;
import com.android.quickstep.util.TaskCornerRadius;
+import com.android.systemui.plugins.OverviewScreenshotActions;
+import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
/**
* A task in the Recents view.
*/
-public class TaskThumbnailView extends View {
+public class TaskThumbnailView extends View implements PluginListener<OverviewScreenshotActions> {
private final static ColorMatrix COLOR_MATRIX = new ColorMatrix();
private final static ColorMatrix SATURATION_COLOR_MATRIX = new ColorMatrix();
@@ -100,6 +104,7 @@ public class TaskThumbnailView extends View {
private boolean mOverlayEnabled;
private boolean mRotated;
+ private OverviewScreenshotActions mOverviewScreenshotActionsPlugin;
public TaskThumbnailView(Context context) {
this(context, null);
@@ -147,6 +152,11 @@ public class TaskThumbnailView extends View {
mPaint.setShader(null);
mOverlay.reset();
}
+
+ if (mOverviewScreenshotActionsPlugin != null) {
+ mOverviewScreenshotActionsPlugin
+ .setupActions((ViewGroup) getTaskView(), getThumbnail(), mActivity);
+ }
updateThumbnailPaintFilter();
}
@@ -211,6 +221,33 @@ public class TaskThumbnailView extends View {
canvas.restore();
}
+ @Override
+ public void onPluginConnected(OverviewScreenshotActions overviewScreenshotActions,
+ Context context) {
+ mOverviewScreenshotActionsPlugin = overviewScreenshotActions;
+ mOverviewScreenshotActionsPlugin.setupActions(getTaskView(), getThumbnail(), mActivity);
+ }
+
+ @Override
+ public void onPluginDisconnected(OverviewScreenshotActions plugin) {
+ if (mOverviewScreenshotActionsPlugin != null) {
+ mOverviewScreenshotActionsPlugin = null;
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ PluginManagerWrapper.INSTANCE.get(getContext())
+ .addPluginListener(this, OverviewScreenshotActions.class);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ PluginManagerWrapper.INSTANCE.get(getContext()).removePluginListener(this);
+ }
+
public RectF getInsetsToDrawInFullscreen(boolean isMultiWindowMode) {
// Don't show insets in multi window mode.
return isMultiWindowMode ? EMPTY_RECT_F : mClippedInsets;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index bfb961320..51802dffd 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -53,6 +53,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;