Merge "Removing support for capturing assist structure on swipe up" into ub-launcher3-master
diff --git a/go/quickstep/res/layout/fallback_recents_activity.xml b/go/quickstep/res/layout/fallback_recents_activity.xml
new file mode 100644
index 0000000..653f463
--- /dev/null
+++ b/go/quickstep/res/layout/fallback_recents_activity.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ 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.
+-->
+<com.android.quickstep.fallback.GoRecentsActivityRootView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/drag_layer"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true">
+
+ <include
+ android:id="@+id/overview_panel"
+ layout="@layout/overview_panel"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:outlineProvider="none"
+ android:theme="@style/HomeScreenElementTheme" />
+</com.android.quickstep.fallback.GoRecentsActivityRootView>
diff --git a/go/quickstep/src/com/android/quickstep/RecentsActivity.java b/go/quickstep/src/com/android/quickstep/RecentsActivity.java
new file mode 100644
index 0000000..a186aaa
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+import android.app.ActivityOptions;
+import android.view.View;
+
+import com.android.launcher3.R;
+import com.android.launcher3.views.BaseDragLayer;
+import com.android.quickstep.fallback.GoRecentsActivityRootView;
+import com.android.quickstep.views.IconRecentsView;
+
+/**
+ * A recents activity that displays recent tasks with an icon and small snapshot.
+ */
+public final class RecentsActivity extends BaseRecentsActivity {
+
+ private GoRecentsActivityRootView mRecentsRootView;
+ private IconRecentsView mIconRecentsView;
+
+ @Override
+ protected void initViews() {
+ setContentView(R.layout.fallback_recents_activity);
+ mRecentsRootView = findViewById(R.id.drag_layer);
+ mIconRecentsView = findViewById(R.id.overview_panel);
+ }
+
+ @Override
+ protected void reapplyUi() {
+ //TODO: Implement this depending on how insets will affect the view.
+ }
+
+ @Override
+ public BaseDragLayer getDragLayer() {
+ return mRecentsRootView;
+ }
+
+ @Override
+ public View getRootView() {
+ return mRecentsRootView;
+ }
+
+ @Override
+ public <T extends View> T getOverviewPanel() {
+ return (T) mIconRecentsView;
+ }
+
+ @Override
+ public ActivityOptions getActivityLaunchOptions(View v) {
+ //TODO: Hook into recents launch animation
+ return null;
+ }
+
+ @Override
+ protected void onStart() {
+ // Set the alpha to 1 before calling super, as it may get set back to 0 due to
+ // onActivityStart callback.
+ mIconRecentsView.setAlpha(0);
+ super.onStart();
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/fallback/GoRecentsActivityRootView.java b/go/quickstep/src/com/android/quickstep/fallback/GoRecentsActivityRootView.java
new file mode 100644
index 0000000..d748e89
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/fallback/GoRecentsActivityRootView.java
@@ -0,0 +1,31 @@
+/*
+ * 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.fallback;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import com.android.launcher3.views.BaseDragLayer;
+import com.android.quickstep.RecentsActivity;
+
+/**
+ * Minimal implementation of {@link BaseDragLayer} for Go's fallback recents activity.
+ */
+public final class GoRecentsActivityRootView extends BaseDragLayer<RecentsActivity> {
+ public GoRecentsActivityRootView(Context context, AttributeSet attrs) {
+ super(context, attrs, 1 /* alphaChannelCount */);
+ }
+}
diff --git a/quickstep/res/layout/fallback_recents_activity.xml b/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml
similarity index 100%
rename from quickstep/res/layout/fallback_recents_activity.xml
rename to quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
similarity index 63%
rename from quickstep/src/com/android/quickstep/RecentsActivity.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index b76a1ab..8d7039e 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -15,12 +15,11 @@
*/
package com.android.quickstep;
-import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
-import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
-
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
-import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_DURATION;
-import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_PRE_DELAY;
+import static com.android.launcher3.QuickstepAppTransitionManagerImpl
+ .STATUS_BAR_TRANSITION_DURATION;
+import static com.android.launcher3.QuickstepAppTransitionManagerImpl
+ .STATUS_BAR_TRANSITION_PRE_DELAY;
import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator;
import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
@@ -29,23 +28,16 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.app.ActivityOptions;
-import android.content.Intent;
import android.content.res.Configuration;
-import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
-import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAnimationRunner;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.uioverrides.UiFactory;
-import com.android.launcher3.util.SystemUiController;
-import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsRootView;
@@ -56,46 +48,22 @@
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
/**
- * A simple activity to show the recently launched tasks
+ * A recents activity that shows the recently launched tasks as swipable task cards.
+ * See {@link com.android.quickstep.views.RecentsView}.
*/
-public class RecentsActivity extends BaseDraggingActivity {
+public final class RecentsActivity extends BaseRecentsActivity {
private Handler mUiHandler = new Handler(Looper.getMainLooper());
private RecentsRootView mRecentsRootView;
private FallbackRecentsView mFallbackRecentsView;
- private Configuration mOldConfig;
-
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mOldConfig = new Configuration(getResources().getConfiguration());
- initDeviceProfile();
-
+ protected void initViews() {
setContentView(R.layout.fallback_recents_activity);
mRecentsRootView = findViewById(R.id.drag_layer);
mFallbackRecentsView = findViewById(R.id.overview_panel);
-
mRecentsRootView.setup();
-
- getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
- Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
- RecentsActivityTracker.onRecentsActivityCreate(this);
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- int diff = newConfig.diff(mOldConfig);
- if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
- onHandleConfigChanged();
- }
- mOldConfig.setTo(newConfig);
- super.onConfigurationChanged(newConfig);
}
@Override
@@ -110,16 +78,10 @@
}
}
- private void onHandleConfigChanged() {
- mUserEventDispatcher = null;
- initDeviceProfile();
-
- AbstractFloatingView.closeOpenViews(this, true,
- AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
- dispatchDeviceProfileChanged();
-
+ @Override
+ protected void onHandleConfigChanged() {
+ super.onHandleConfigChanged();
mRecentsRootView.setup();
- reapplyUi();
}
@Override
@@ -127,15 +89,12 @@
mRecentsRootView.dispatchInsets();
}
- private void initDeviceProfile() {
+ @Override
+ protected DeviceProfile createDeviceProfile() {
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
-
- // In case we are reusing IDP, create a copy so that we don't conflict with Launcher
- // activity.
- mDeviceProfile = (mRecentsRootView != null) && isInMultiWindowMode()
+ return (mRecentsRootView != null) && isInMultiWindowMode()
? dp.getMultiWindowProfile(this, mRecentsRootView.getLastKnownSize())
- : dp.copy(this);
- onDeviceProfileInitiated();
+ : super.createDeviceProfile();
}
@Override
@@ -211,55 +170,4 @@
super.onStart();
mFallbackRecentsView.resetTaskVisuals();
}
-
- @Override
- protected void onStop() {
- super.onStop();
-
- // Workaround for b/78520668, explicitly trim memory once UI is hidden
- onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
- }
-
- @Override
- public void onEnterAnimationComplete() {
- super.onEnterAnimationComplete();
- UiFactory.onEnterAnimationComplete(this);
- }
-
- @Override
- public void onTrimMemory(int level) {
- super.onTrimMemory(level);
- UiFactory.onTrimMemory(this, level);
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- RecentsActivityTracker.onRecentsActivityNewIntent(this);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- RecentsActivityTracker.onRecentsActivityDestroy(this);
- }
-
- @Override
- public void onBackPressed() {
- // TODO: Launch the task we came from
- startHome();
- }
-
- public void startHome() {
- startActivity(new Intent(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_HOME)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
- }
-
- @Override
- public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
- super.dump(prefix, fd, writer, args);
- writer.println(prefix + "Misc:");
- dumpMisc(writer);
- }
}
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/fallback/RecentsRootView.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java
diff --git a/quickstep/src/com/android/quickstep/BaseRecentsActivity.java b/quickstep/src/com/android/quickstep/BaseRecentsActivity.java
new file mode 100644
index 0000000..c840132
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/BaseRecentsActivity.java
@@ -0,0 +1,162 @@
+/*
+ * 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;
+
+import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
+import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
+
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Bundle;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.R;
+import com.android.launcher3.uioverrides.UiFactory;
+import com.android.launcher3.util.SystemUiController;
+import com.android.launcher3.util.Themes;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * A base fallback recents activity that provides support for device profile changes, activity
+ * lifecycle tracking, and basic input handling from recents.
+ *
+ * This class is only used as a fallback in case the default launcher does not have a recents
+ * implementation.
+ */
+public abstract class BaseRecentsActivity extends BaseDraggingActivity {
+
+ private Configuration mOldConfig;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mOldConfig = new Configuration(getResources().getConfiguration());
+ initDeviceProfile();
+ initViews();
+
+ getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
+ Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
+ RecentsActivityTracker.onRecentsActivityCreate(this);
+ }
+
+ /**
+ * Init drag layer and overview panel views.
+ */
+ abstract protected void initViews();
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ int diff = newConfig.diff(mOldConfig);
+ if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
+ onHandleConfigChanged();
+ }
+ mOldConfig.setTo(newConfig);
+ super.onConfigurationChanged(newConfig);
+ }
+
+ /**
+ * Logic for when device configuration changes (rotation, screen size change, multi-window,
+ * etc.)
+ */
+ protected void onHandleConfigChanged() {
+ mUserEventDispatcher = null;
+ initDeviceProfile();
+
+ AbstractFloatingView.closeOpenViews(this, true,
+ AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
+ dispatchDeviceProfileChanged();
+
+ reapplyUi();
+ }
+
+ /**
+ * Initialize/update the device profile.
+ */
+ private void initDeviceProfile() {
+ mDeviceProfile = createDeviceProfile();
+ onDeviceProfileInitiated();
+ }
+
+ /**
+ * Generate the device profile to use in this activity.
+ * @return device profile
+ */
+ protected DeviceProfile createDeviceProfile() {
+ DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
+
+ // In case we are reusing IDP, create a copy so that we don't conflict with Launcher
+ // activity.
+ return dp.copy(this);
+ }
+
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+
+ // Workaround for b/78520668, explicitly trim memory once UI is hidden
+ onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
+ }
+
+ @Override
+ public void onEnterAnimationComplete() {
+ super.onEnterAnimationComplete();
+ UiFactory.onEnterAnimationComplete(this);
+ }
+
+ @Override
+ public void onTrimMemory(int level) {
+ super.onTrimMemory(level);
+ UiFactory.onTrimMemory(this, level);
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ RecentsActivityTracker.onRecentsActivityNewIntent(this);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ RecentsActivityTracker.onRecentsActivityDestroy(this);
+ }
+
+ @Override
+ public void onBackPressed() {
+ // TODO: Launch the task we came from
+ startHome();
+ }
+
+ public void startHome() {
+ startActivity(new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ }
+
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ super.dump(prefix, fd, writer, args);
+ writer.println(prefix + "Misc:");
+ dumpMisc(writer);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index 30b0c02..0c20bd1 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -292,8 +292,6 @@
mMotionPauseDetector.setOnMotionPauseListener(handler::onMotionPauseChanged);
handler.initWhenReady();
- TraceHelper.beginSection("RecentsController");
-
if (listenerSet != null) {
listenerSet.addListener(handler);
mSwipeSharedState.applyActiveRecentsAnimationState(handler);
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index cedd952..00b3e90 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -73,6 +73,14 @@
});
}
+ public void startStabilizationSession() {
+ mStabilizer.startStabilizationSession();
+ }
+
+ public void endStabilizationSession() {
+ mStabilizer.endStabilizationSession();
+ }
+
/**
* Asynchronously fetches the list of recent tasks, reusing cached list if available.
*
diff --git a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
index fb6090e..0822e61 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
@@ -30,17 +30,18 @@
import java.util.function.BiPredicate;
/**
- * Utility class to track create/destroy for RecentsActivity
+ * Utility class to track create/destroy for some {@link BaseRecentsActivity}.
*/
@TargetApi(Build.VERSION_CODES.P)
-public class RecentsActivityTracker implements ActivityInitListener {
+public class RecentsActivityTracker<T extends BaseRecentsActivity> implements ActivityInitListener {
- private static WeakReference<RecentsActivity> sCurrentActivity = new WeakReference<>(null);
+ private static WeakReference<BaseRecentsActivity> sCurrentActivity =
+ new WeakReference<>(null);
private static final Scheduler sScheduler = new Scheduler();
- private final BiPredicate<RecentsActivity, Boolean> mOnInitListener;
+ private final BiPredicate<T, Boolean> mOnInitListener;
- public RecentsActivityTracker(BiPredicate<RecentsActivity, Boolean> onInitListener) {
+ public RecentsActivityTracker(BiPredicate<T, Boolean> onInitListener) {
mOnInitListener = onInitListener;
}
@@ -54,12 +55,12 @@
sScheduler.clearReference(this);
}
- private boolean init(RecentsActivity activity, boolean visible) {
+ private boolean init(T activity, boolean visible) {
return mOnInitListener.test(activity, visible);
}
- public static RecentsActivity getCurrentActivity() {
- return sCurrentActivity.get();
+ public static <T extends BaseRecentsActivity> T getCurrentActivity() {
+ return (T) sCurrentActivity.get();
}
@Override
@@ -71,17 +72,17 @@
context.startActivity(intent, options);
}
- public static void onRecentsActivityCreate(RecentsActivity activity) {
+ public static void onRecentsActivityCreate(BaseRecentsActivity activity) {
sCurrentActivity = new WeakReference<>(activity);
sScheduler.initIfPending(activity, false);
}
- public static void onRecentsActivityNewIntent(RecentsActivity activity) {
+ public static void onRecentsActivityNewIntent(BaseRecentsActivity activity) {
sScheduler.initIfPending(activity, activity.isStarted());
}
- public static void onRecentsActivityDestroy(RecentsActivity activity) {
+ public static void onRecentsActivityDestroy(BaseRecentsActivity activity) {
if (sCurrentActivity.get() == activity) {
sCurrentActivity.clear();
}
@@ -103,13 +104,14 @@
@Override
public void run() {
- RecentsActivity activity = sCurrentActivity.get();
+ BaseRecentsActivity activity = sCurrentActivity.get();
if (activity != null) {
initIfPending(activity, activity.isStarted());
}
}
- public synchronized boolean initIfPending(RecentsActivity activity, boolean alreadyOnHome) {
+ public synchronized boolean initIfPending(BaseRecentsActivity activity,
+ boolean alreadyOnHome) {
RecentsActivityTracker tracker = mPendingTracker.get();
if (tracker != null) {
if (!tracker.init(activity, alreadyOnHome)) {
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
index c2d4d80..5e7c1a1 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
@@ -21,17 +21,11 @@
import android.view.MotionEvent;
-import com.android.launcher3.MainThreadExecutor;
-import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.Preconditions;
-import com.android.launcher3.util.TraceHelper;
-import com.android.launcher3.util.UiThreadHelper;
-import com.android.quickstep.util.RemoteAnimationTargetSet;
+import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.systemui.shared.system.InputConsumerController;
-import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import java.util.ArrayList;
-import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
import androidx.annotation.UiThread;
@@ -45,17 +39,10 @@
// than the state callbacks as these run on the current worker thread.
private final ArrayList<Runnable> mCallbacks = new ArrayList<>();
- public RemoteAnimationTargetSet targetSet;
+ public SwipeAnimationTargetSet targetSet;
- private RecentsAnimationControllerCompat mController;
- private boolean mInputConsumerEnabled = false;
- private boolean mBehindSystemBars = true;
- private boolean mSplitScreenMinimized = false;
+ private boolean mWindowThresholdCrossed = false;
- private final ExecutorService mExecutorService =
- new LooperExecutor(UiThreadHelper.getBackgroundLooper());
-
- private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
private final InputConsumerController mInputConsumer;
private final Supplier<TouchConsumer> mTouchProxySupplier;
@@ -71,19 +58,14 @@
}
@UiThread
- public synchronized void setController(
- RecentsAnimationControllerCompat controller, RemoteAnimationTargetSet targetSet) {
+ public synchronized void setController(SwipeAnimationTargetSet targetSet) {
Preconditions.assertUIThread();
- TraceHelper.partitionSection("RecentsController", "Set controller " + controller);
- this.mController = controller;
this.targetSet = targetSet;
- if (controller == null) {
+ if (targetSet == null) {
return;
}
- if (mInputConsumerEnabled) {
- enableInputConsumer();
- }
+ targetSet.setWindowThresholdCrossed(mWindowThresholdCrossed);
if (!mCallbacks.isEmpty()) {
for (Runnable action : new ArrayList<>(mCallbacks)) {
@@ -105,13 +87,12 @@
* @param onFinishComplete A callback that runs on the main thread after the animation
* controller has finished on the background thread.
*/
+ @UiThread
public void finish(boolean toRecents, Runnable onFinishComplete) {
+ Preconditions.assertUIThread();
if (!toRecents) {
- mExecutorService.submit(() -> finishBg(false, onFinishComplete));
- return;
- }
-
- mMainThreadExecutor.execute(() -> {
+ finishAndClear(false, onFinishComplete);
+ } else {
if (mTouchInProgress) {
mFinishPending = true;
// Execute the callback
@@ -119,45 +100,39 @@
onFinishComplete.run();
}
} else {
- mExecutorService.submit(() -> finishBg(true, onFinishComplete));
+ finishAndClear(true, onFinishComplete);
}
- });
+ }
}
- protected void finishBg(boolean toRecents, Runnable onFinishComplete) {
- RecentsAnimationControllerCompat controller = mController;
- mController = null;
- TraceHelper.endSection("RecentsController", "Finish " + controller
- + ", toRecents=" + toRecents);
+ private void finishAndClear(boolean toRecents, Runnable onFinishComplete) {
+ SwipeAnimationTargetSet controller = targetSet;
+ targetSet = null;
if (controller != null) {
- controller.setInputConsumerEnabled(false);
- controller.finish(toRecents);
-
- if (onFinishComplete != null) {
- mMainThreadExecutor.execute(onFinishComplete);
- }
+ controller.finishController(toRecents, onFinishComplete);
}
}
public void enableInputConsumer() {
- mInputConsumerEnabled = true;
- if (mInputConsumerEnabled) {
- mExecutorService.submit(() -> {
- RecentsAnimationControllerCompat controller = mController;
- TraceHelper.partitionSection("RecentsController",
- "Enabling consumer on " + controller);
- if (controller != null) {
- controller.setInputConsumerEnabled(true);
- }
- });
+ if (targetSet != null) {
+ targetSet.enableInputConsumer();
+ }
+ }
+
+ /**
+ * Indicates that the gesture has crossed the window boundary threshold and system UI can be
+ * update the represent the window behind
+ */
+ public void setWindowThresholdCrossed(boolean windowThresholdCrossed) {
+ if (mWindowThresholdCrossed != windowThresholdCrossed) {
+ mWindowThresholdCrossed = windowThresholdCrossed;
+ if (targetSet != null) {
+ targetSet.setWindowThresholdCrossed(windowThresholdCrossed);
+ }
}
}
public void enableTouchProxy() {
- mMainThreadExecutor.execute(this::enableTouchProxyUi);
- }
-
- private void enableTouchProxyUi() {
mInputConsumer.setTouchListener(this::onInputConsumerTouch);
}
@@ -171,7 +146,7 @@
mTouchInProgress = false;
if (mFinishPending) {
mFinishPending = false;
- mExecutorService.submit(() -> finishBg(true, null));
+ finishAndClear(true /* toRecents */, null);
}
}
if (mTouchConsumer != null) {
@@ -181,54 +156,7 @@
return true;
}
- public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
- if (mBehindSystemBars == behindSystemBars) {
- return;
- }
- mBehindSystemBars = behindSystemBars;
- mExecutorService.submit(() -> {
- RecentsAnimationControllerCompat controller = mController;
- TraceHelper.partitionSection("RecentsController",
- "Setting behind system bars on " + controller);
- if (controller != null) {
- controller.setAnimationTargetsBehindSystemBars(behindSystemBars);
- }
- });
- }
-
- /**
- * NOTE: As a workaround for conflicting animations (Launcher animating the task leash, and
- * SystemUI resizing the docked stack, which resizes the task), we currently only set the
- * minimized mode, and not the inverse.
- * TODO: Synchronize the minimize animation with the launcher animation
- */
- public void setSplitScreenMinimizedForTransaction(boolean minimized) {
- if (mSplitScreenMinimized || !minimized) {
- return;
- }
- mSplitScreenMinimized = minimized;
- mExecutorService.submit(() -> {
- RecentsAnimationControllerCompat controller = mController;
- TraceHelper.partitionSection("RecentsController",
- "Setting minimize dock on " + controller);
- if (controller != null) {
- controller.setSplitScreenMinimized(minimized);
- }
- });
- }
-
- public void hideCurrentInputMethod() {
- mExecutorService.submit(() -> {
- RecentsAnimationControllerCompat controller = mController;
- TraceHelper.partitionSection("RecentsController",
- "Hiding currentinput method on " + controller);
- if (controller != null) {
- controller.hideCurrentInputMethod();
- }
- });
- }
-
- public RecentsAnimationControllerCompat getController() {
- return mController;
+ public SwipeAnimationTargetSet getController() {
+ return targetSet;
}
}
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 02deef1..f3e1545 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -15,8 +15,6 @@
*/
package com.android.quickstep;
-import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
-
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
@@ -28,6 +26,7 @@
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
+
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Preconditions;
@@ -35,11 +34,14 @@
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
+
import java.util.ArrayList;
import java.util.function.Consumer;
import androidx.annotation.WorkerThread;
+import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
+
/**
* Singleton class to load and manage recents model.
*/
@@ -86,6 +88,14 @@
return mThumbnailCache;
}
+ public void startStabilizationSession() {
+ mTaskList.startStabilizationSession();
+ }
+
+ public void endStabilizationSession() {
+ mTaskList.endStabilizationSession();
+ }
+
/**
* Fetches the list of recent tasks.
*
diff --git a/quickstep/src/com/android/quickstep/SwipeSharedState.java b/quickstep/src/com/android/quickstep/SwipeSharedState.java
index 15914ba..7c6638a 100644
--- a/quickstep/src/com/android/quickstep/SwipeSharedState.java
+++ b/quickstep/src/com/android/quickstep/SwipeSharedState.java
@@ -15,6 +15,9 @@
*/
package com.android.quickstep;
+import android.util.Log;
+
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
@@ -25,23 +28,35 @@
*/
public class SwipeSharedState implements SwipeAnimationListener {
+ private final OverviewComponentObserver mOverviewComponentObserver;
+
private RecentsAnimationListenerSet mRecentsAnimationListener;
private SwipeAnimationTargetSet mLastAnimationTarget;
+
private boolean mLastAnimationCancelled = false;
+ private boolean mLastAnimationRunning = false;
public boolean canGestureBeContinued;
public boolean goingToLauncher;
+ public SwipeSharedState(OverviewComponentObserver overviewComponentObserver) {
+ mOverviewComponentObserver = overviewComponentObserver;
+ }
+
@Override
public final void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
mLastAnimationTarget = targetSet;
+
mLastAnimationCancelled = false;
+ mLastAnimationRunning = true;
}
@Override
public final void onRecentsAnimationCanceled() {
mLastAnimationTarget = null;
+
mLastAnimationCancelled = true;
+ mLastAnimationRunning = false;
}
private void clearListenerState() {
@@ -51,12 +66,31 @@
mRecentsAnimationListener = null;
mLastAnimationTarget = null;
mLastAnimationCancelled = false;
+ mLastAnimationRunning = false;
+ }
+
+ private void onSwipeAnimationFinished(SwipeAnimationTargetSet targetSet) {
+ if (mLastAnimationTarget == targetSet) {
+ mLastAnimationRunning = false;
+ }
}
public RecentsAnimationListenerSet newRecentsAnimationListenerSet() {
Preconditions.assertUIThread();
+
+ if (mLastAnimationRunning) {
+ String msg = "New animation started before completing old animation";
+ if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ throw new IllegalArgumentException(msg);
+ } else {
+ Log.e("SwipeSharedState", msg, new Exception());
+ }
+ }
+
clearListenerState();
- mRecentsAnimationListener = new RecentsAnimationListenerSet();
+ mRecentsAnimationListener = new RecentsAnimationListenerSet(mOverviewComponentObserver
+ .getActivityControlHelper().shouldMinimizeSplitScreen(),
+ this::onSwipeAnimationFinished);
mRecentsAnimationListener.addListener(this);
return mRecentsAnimationListener;
}
diff --git a/quickstep/src/com/android/quickstep/TaskListStabilizer.java b/quickstep/src/com/android/quickstep/TaskListStabilizer.java
index 3eb26b4..4c63f81 100644
--- a/quickstep/src/com/android/quickstep/TaskListStabilizer.java
+++ b/quickstep/src/com/android/quickstep/TaskListStabilizer.java
@@ -15,13 +15,10 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_TASK_STABILIZER;
-
import android.app.ActivityManager.RecentTaskInfo;
import android.content.ComponentName;
import android.os.Process;
import android.os.SystemClock;
-import android.util.Log;
import com.android.launcher3.util.IntArray;
import com.android.systemui.shared.recents.model.Task;
@@ -33,98 +30,77 @@
import java.util.Collections;
import java.util.List;
+/**
+ * Keeps the task list stable during quick switch gestures. So if you swipe right to switch from app
+ * A to B, you can then swipe right again to get to app C or left to get back to A.
+ */
public class TaskListStabilizer {
private static final long TASK_CACHE_TIMEOUT_MS = 5000;
- private static final int INVALID_TASK_ID = -1;
-
private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onTaskCreated(int taskId, ComponentName componentName) {
- onTaskCreatedInternal(taskId);
- }
-
- @Override
- public void onTaskMovedToFront(int taskId) {
- onTaskMovedToFrontInternal(taskId);
+ endStabilizationSession();
}
@Override
public void onTaskRemoved(int taskId) {
- onTaskRemovedInternal(taskId);
+ endStabilizationSession();
}
};
- // Task ids ordered based on recency, 0th index is the latest task
- private final IntArray mOrderedTaskIds;
+ // Task ids ordered based on recency, 0th index is the least recent task
+ private final IntArray mSystemOrder;
+ private final IntArray mStabilizedOrder;
// Wrapper objects used for sorting tasks
private final ArrayList<TaskWrapper> mTaskWrappers = new ArrayList<>();
- // Information about recent task re-order which has not been applied yet
- private int mScheduledMoveTaskId = INVALID_TASK_ID;
- private long mScheduledMoveTime = 0;
+ private boolean mInStabilizationSession;
+ private long mSessionStartTime;
public TaskListStabilizer() {
- if (ENABLE_TASK_STABILIZER.get()) {
- // Initialize the task ids map
- List<RecentTaskInfo> rawTasks = ActivityManagerWrapper.getInstance().getRecentTasks(
- Integer.MAX_VALUE, Process.myUserHandle().getIdentifier());
- mOrderedTaskIds = new IntArray(rawTasks.size());
- for (RecentTaskInfo info : rawTasks) {
- mOrderedTaskIds.add(new TaskKey(info).id);
- }
-
- ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
- } else {
- mOrderedTaskIds = null;
+ // Initialize the task ids map
+ List<RecentTaskInfo> rawTasks = ActivityManagerWrapper.getInstance().getRecentTasks(
+ Integer.MAX_VALUE, Process.myUserHandle().getIdentifier());
+ mSystemOrder = new IntArray(rawTasks.size());
+ for (RecentTaskInfo info : rawTasks) {
+ mSystemOrder.add(new TaskKey(info).id);
}
+ // We will lazily copy the task id's from mSystemOrder when a stabilization session starts.
+ mStabilizedOrder = new IntArray(rawTasks.size());
+
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
}
- private synchronized void onTaskCreatedInternal(int taskId) {
- applyScheduledMoveUnchecked();
- mOrderedTaskIds.add(taskId);
- }
-
- private synchronized void onTaskRemovedInternal(int taskId) {
- applyScheduledMoveUnchecked();
- mOrderedTaskIds.removeValue(taskId);
- }
-
- private void applyScheduledMoveUnchecked() {
- if (mScheduledMoveTaskId != INVALID_TASK_ID) {
- // Mode the scheduled task to front
- mOrderedTaskIds.removeValue(mScheduledMoveTaskId);
- mOrderedTaskIds.add(mScheduledMoveTaskId);
- mScheduledMoveTaskId = INVALID_TASK_ID;
+ public synchronized void startStabilizationSession() {
+ if (!mInStabilizationSession) {
+ mStabilizedOrder.clear();
+ mStabilizedOrder.addAll(mSystemOrder);
}
+ mInStabilizationSession = true;
+ mSessionStartTime = SystemClock.uptimeMillis();
}
- /**
- * Checks if the scheduled move has timed out and moves the task to front accordingly.
- */
- private void applyScheduledMoveIfTime() {
- if (mScheduledMoveTaskId != INVALID_TASK_ID
- && (SystemClock.uptimeMillis() - mScheduledMoveTime) > TASK_CACHE_TIMEOUT_MS) {
- applyScheduledMoveUnchecked();
- }
+ public synchronized void endStabilizationSession() {
+ mInStabilizationSession = false;
}
- private synchronized void onTaskMovedToFrontInternal(int taskId) {
- applyScheduledMoveIfTime();
- mScheduledMoveTaskId = taskId;
- mScheduledMoveTime = SystemClock.uptimeMillis();
- }
-
-
public synchronized ArrayList<Task> reorder(ArrayList<Task> tasks) {
- if (!ENABLE_TASK_STABILIZER.get()) {
- return tasks;
+ mSystemOrder.clear();
+ for (Task task : tasks) {
+ mSystemOrder.add(task.key.id);
}
- applyScheduledMoveIfTime();
+ if ((SystemClock.uptimeMillis() - mSessionStartTime) > TASK_CACHE_TIMEOUT_MS) {
+ endStabilizationSession();
+ }
+
+ if (!mInStabilizationSession) {
+ return tasks;
+ }
// Ensure that we have enough wrappers
int taskCount = tasks.size();
@@ -139,7 +115,7 @@
for (int i = 0; i < taskCount; i++){
TaskWrapper wrapper = listToSort.get(i);
wrapper.task = tasks.get(i);
- wrapper.index = mOrderedTaskIds.indexOf(wrapper.task.key.id);
+ wrapper.index = mStabilizedOrder.indexOf(wrapper.task.key.id);
// Ensure that missing tasks are put in the front, in the order they appear in the
// original list
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 74ac1c6..0ccd141 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -37,6 +37,8 @@
import android.view.MotionEvent;
import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.util.LooperExecutor;
+import com.android.launcher3.util.UiThreadHelper;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -55,6 +57,9 @@
public class TouchInteractionService extends Service {
public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor();
+ public static final LooperExecutor BACKGROUND_EXECUTOR =
+ new LooperExecutor(UiThreadHelper.getBackgroundLooper());
+
public static final TouchInteractionLog TOUCH_INTERACTION_LOG = new TouchInteractionLog();
public static final int EDGE_NAV_BAR = 1 << 8;
@@ -174,7 +179,7 @@
mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this);
mOverviewCallbacks = OverviewCallbacks.get(this);
mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this);
- mSwipeSharedState = new SwipeSharedState();
+ mSwipeSharedState = new SwipeSharedState(mOverviewComponentObserver);
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
mInputConsumer.registerInputConsumer();
@@ -249,10 +254,8 @@
mOverviewComponentObserver.getActivityControlHelper();
boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event);
return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel,
- mOverviewComponentObserver.getOverviewIntent(),
- mOverviewComponentObserver.getActivityControlHelper(),
- shouldDefer, mOverviewCallbacks,
- mTaskOverlayFactory, mInputConsumer,
+ mOverviewComponentObserver.getOverviewIntent(), activityControl,
+ shouldDefer, mOverviewCallbacks, mTaskOverlayFactory, mInputConsumer,
this::onConsumerInactive, mSwipeSharedState);
}
}
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 84d70d9..8d90813 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -98,7 +98,6 @@
import com.android.systemui.shared.recents.utilities.RectFEvaluator;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.LatencyTrackerCompat;
-import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.WindowCallbacksCompat;
@@ -190,11 +189,15 @@
this.containerType = containerType;
}
- // 0 is app, 1 is overview
+ /** 0 is app, 1 is overview */
public final float endShift;
+ /** The state to apply when we reach this final target */
public final int endState;
+ /** Whether the target is in the launcher activity */
public final boolean isLauncher;
+ /** Whether the user can start a new gesture while this one is finishing */
public final boolean canBeContinued;
+ /** Used to log where the user ended up after the gesture ends */
public final int containerType;
}
@@ -337,6 +340,9 @@
| STATE_SCALED_CONTROLLER_LAST_TASK,
this::notifyTransitionCancelled);
+ mStateCallback.addCallback(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
+ mRecentsAnimationWrapper::enableInputConsumer);
+
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
mStateCallback.addChangeHandler(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT
| STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT,
@@ -585,7 +591,7 @@
private void updateFinalShift() {
float shift = mCurrentShift.value;
- RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
+ SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
float offsetX = 0;
if (mRecentsView != null) {
@@ -600,12 +606,8 @@
.setSyncTransactionApplier(mSyncTransactionApplier);
mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
mTransformParams);
-
- boolean passedThreshold = shift > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
- mRecentsAnimationWrapper.setAnimationTargetsBehindSystemBars(!passedThreshold);
- if (mActivityControlHelper.shouldMinimizeSplitScreen()) {
- mRecentsAnimationWrapper.setSplitScreenMinimizedForTransaction(passedThreshold);
- }
+ mRecentsAnimationWrapper.setWindowThresholdCrossed(
+ shift > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD);
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
@@ -684,7 +686,7 @@
mClipAnimationHelper.prepareAnimation(false /* isOpening */);
initTransitionEndpoints(dp);
- mRecentsAnimationWrapper.setController(targetSet.controller, targetSet);
+ mRecentsAnimationWrapper.setController(targetSet);
TOUCH_INTERACTION_LOG.startRecentsAnimationCallback(targetSet.apps.length);
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
@@ -693,7 +695,7 @@
@Override
public void onRecentsAnimationCanceled() {
- mRecentsAnimationWrapper.setController(null, null);
+ mRecentsAnimationWrapper.setController(null);
mActivityInitListener.unregister();
setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
TOUCH_INTERACTION_LOG.cancelRecentsAnimation();
@@ -705,8 +707,6 @@
mShiftAtGestureStart = mCurrentShift.value;
setStateOnUiThread(STATE_GESTURE_STARTED);
mGestureStarted = true;
- mRecentsAnimationWrapper.hideCurrentInputMethod();
- mRecentsAnimationWrapper.enableInputConsumer();
}
/**
@@ -888,6 +888,17 @@
private void animateToProgressInternal(float start, float end, long duration,
Interpolator interpolator, GestureEndTarget target, float velocityPxPerMs) {
mGestureEndTarget = target;
+
+ if (mGestureEndTarget.canBeContinued) {
+ // Because we might continue this gesture, e.g. for consecutive quick switch, we need to
+ // stabilize the task list so that tasks don't rearrange in the middle of the gesture.
+ RecentsModel.INSTANCE.get(mContext).startStabilizationSession();
+ } else if (mGestureEndTarget.isLauncher) {
+ // Otherwise, if we're going to home or overview,
+ // we reset the tasks to a consistent start state.
+ RecentsModel.INSTANCE.get(mContext).endStabilizationSession();
+ }
+
HomeAnimationFactory homeAnimFactory;
Animator windowAnim;
if (mGestureEndTarget == HOME) {
@@ -1097,7 +1108,7 @@
setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
} else {
boolean finishTransitionPosted = false;
- RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
+ SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
// Update the screenshot of the task
if (mTaskSnapshot == null) {
diff --git a/quickstep/src/com/android/quickstep/util/RecentsAnimationListenerSet.java b/quickstep/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
index 686e74d..62f2183 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
@@ -28,6 +28,7 @@
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.Set;
+import java.util.function.Consumer;
import androidx.annotation.UiThread;
@@ -38,6 +39,14 @@
public class RecentsAnimationListenerSet implements RecentsAnimationListener {
private final Set<SwipeAnimationListener> mListeners = new ArraySet<>();
+ private final boolean mShouldMinimizeSplitScreen;
+ private final Consumer<SwipeAnimationTargetSet> mOnFinishListener;
+
+ public RecentsAnimationListenerSet(boolean shouldMinimizeSplitScreen,
+ Consumer<SwipeAnimationTargetSet> onFinishListener) {
+ mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen;
+ mOnFinishListener = onFinishListener;
+ }
@UiThread
public void addListener(SwipeAnimationListener listener) {
@@ -56,7 +65,8 @@
RemoteAnimationTargetCompat[] targets, Rect homeContentInsets,
Rect minimizedHomeBounds) {
SwipeAnimationTargetSet targetSet = new SwipeAnimationTargetSet(controller, targets,
- homeContentInsets, minimizedHomeBounds);
+ homeContentInsets, minimizedHomeBounds, mShouldMinimizeSplitScreen,
+ mOnFinishListener);
Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationStart(targetSet);
diff --git a/quickstep/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
index 4f02acf..b682481 100644
--- a/quickstep/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
+++ b/quickstep/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
@@ -15,32 +15,79 @@
*/
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.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.graphics.Rect;
+import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import java.util.function.Consumer;
+
/**
* Extension of {@link RemoteAnimationTargetSet} with additional information about swipe
* up animation
*/
public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet {
+ private final boolean mShouldMinimizeSplitScreen;
+ private final Consumer<SwipeAnimationTargetSet> mOnFinishListener;
+
+
public final RecentsAnimationControllerCompat controller;
public final Rect homeContentInsets;
public final Rect minimizedHomeBounds;
public SwipeAnimationTargetSet(RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] targets, Rect homeContentInsets,
- Rect minimizedHomeBounds) {
+ Rect minimizedHomeBounds, boolean shouldMinimizeSplitScreen,
+ Consumer<SwipeAnimationTargetSet> onFinishListener) {
super(targets, MODE_CLOSING);
this.controller = controller;
this.homeContentInsets = homeContentInsets;
this.minimizedHomeBounds = minimizedHomeBounds;
+ this.mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen;
+ this.mOnFinishListener = onFinishListener;
}
+ public void finishController(boolean toRecents, Runnable callback) {
+ mOnFinishListener.accept(this);
+ BACKGROUND_EXECUTOR.execute(() -> {
+ controller.setInputConsumerEnabled(false);
+ controller.finish(toRecents);
+
+ if (callback != null) {
+ MAIN_THREAD_EXECUTOR.execute(callback);
+ }
+ });
+ }
+
+ public void enableInputConsumer() {
+ BACKGROUND_EXECUTOR.submit(() -> {
+ controller.hideCurrentInputMethod();
+ controller.setInputConsumerEnabled(true);
+ });
+ }
+
+ public void setWindowThresholdCrossed(boolean thresholdCrossed) {
+ BACKGROUND_EXECUTOR.execute(() -> {
+ controller.setAnimationTargetsBehindSystemBars(!thresholdCrossed);
+ if (mShouldMinimizeSplitScreen && thresholdCrossed) {
+ // NOTE: As a workaround for conflicting animations (Launcher animating the task
+ // leash, and SystemUI resizing the docked stack, which resizes the task), we
+ // currently only set the minimized mode, and not the inverse.
+ // TODO: Synchronize the minimize animation with the launcher animation
+ controller.setSplitScreenMinimized(thresholdCrossed);
+ }
+ });
+ }
+
+ public ThumbnailData screenshotTask(int taskId) {
+ return controller != null ? controller.screenshotTask(taskId) : null;
+ }
public interface SwipeAnimationListener {
@@ -48,4 +95,9 @@
void onRecentsAnimationCanceled();
}
+
+ public interface SwipeAnimationFinishListener {
+
+ void onSwipeAnimationFinished(SwipeAnimationTargetSet targetSet);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 0c1867d..5465a0c 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -93,13 +93,13 @@
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.ClipAnimationHelper;
+import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.TaskViewDrawable;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.PackageManagerWrapper;
-import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowCallbacksCompat;
@@ -1590,7 +1590,7 @@
return;
}
- RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
+ SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
// Update the screenshot of the task
ThumbnailData taskSnapshot = controller.screenshotTask(mRunningTaskId);
diff --git a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java
index 54038d2..656d55c 100644
--- a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java
+++ b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java
@@ -26,7 +26,6 @@
@Test
public void withFlagOn() {
assertTrue(FeatureFlags.EXAMPLE_FLAG.get());
- assertFalse(FeatureFlags.QUICK_SWITCH.get());
assertFalse(FeatureFlags.STYLE_WALLPAPER.get());
}
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index b921d29..61467e0 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -88,10 +88,6 @@
// trying to make them fit the orientation the device is in.
public static final boolean OVERVIEW_USE_SCREENSHOT_ORIENTATION = true;
- public static final ToggleableGlobalSettingsFlag QUICK_SWITCH
- = new ToggleableGlobalSettingsFlag("QUICK_SWITCH", false,
- "Swiping right on the nav bar while in an app switches to the previous app");
-
public static final ToggleableGlobalSettingsFlag STYLE_WALLPAPER
= new ToggleableGlobalSettingsFlag("STYLE_WALLPAPER", false,
"Direct users to the new ThemePicker based WallpaperPicker");
@@ -102,10 +98,6 @@
public static final TogglableFlag APPLY_CONFIG_AT_RUNTIME = new TogglableFlag(
"APPLY_CONFIG_AT_RUNTIME", true, "Apply display changes dynamically");
- public static final ToggleableGlobalSettingsFlag ENABLE_TASK_STABILIZER
- = new ToggleableGlobalSettingsFlag("ENABLE_TASK_STABILIZER", false,
- "Stable task list across fast task switches");
-
public static final TogglableFlag QUICKSTEP_SPRINGS = new TogglableFlag("QUICKSTEP_SPRINGS",
false, "Enable springs for quickstep animations");