Revert "Removing AM.getTasks call on UI thread during touch down"
This reverts commit 013a8a75abb9e940163dfafceb0c1fefc218652f.
Reason for revert: Broke builds
Bug: 229619753
Change-Id: Idb1aecf1d43db50aa4f11dbb88079c37e401d694
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 7bfb76a..4d3b057 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -48,8 +48,8 @@
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.TaskUtils;
-import com.android.quickstep.TopTaskTracker;
import com.android.quickstep.util.AnimatorControllerWithResistance;
+import com.android.quickstep.util.AssistantUtilities;
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
@@ -112,8 +112,7 @@
return true;
}
if (FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
- && TopTaskTracker.INSTANCE.get(mLauncher).getCachedTopTask(false)
- .isExcludedAssistant()) {
+ && AssistantUtilities.isExcludedAssistantRunning()) {
return true;
}
return false;
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 2ae0646..6e80402 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -102,6 +102,7 @@
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.InputConsumerProxy;
import com.android.quickstep.util.InputProxyHandlerFactory;
+import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.RecentsOrientedState;
@@ -113,7 +114,6 @@
import com.android.quickstep.util.VibratorWrapper;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
-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.InputConsumerController;
@@ -564,12 +564,24 @@
}
protected void notifyGestureAnimationStartToRecents() {
- Task[] runningTasks;
+ ActivityManager.RunningTaskInfo[] runningTasks;
if (mIsSwipeForStagedSplit) {
- int[] splitTaskIds = TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds();
- runningTasks = mGestureState.getRunningTask().getPlaceholderTasks(splitTaskIds);
+ int[] splitTaskIds =
+ LauncherSplitScreenListener.INSTANCE.getNoCreate().getRunningSplitTaskIds();
+ runningTasks = new ActivityManager.RunningTaskInfo[splitTaskIds.length];
+ for (int i = 0; i < splitTaskIds.length; i++) {
+ int taskId = splitTaskIds[i];
+ // Order matters here, we want first indexed RunningTaskInfo to be leftTop task
+ for (ActivityManager.RunningTaskInfo rti : mGestureState.getRunningTasks()) {
+ if (taskId == rti.taskId) {
+ runningTasks[i] = rti;
+ break;
+ }
+
+ }
+ }
} else {
- runningTasks = mGestureState.getRunningTask().getPlaceholderTasks();
+ runningTasks = new ActivityManager.RunningTaskInfo[]{mGestureState.getRunningTask()};
}
mRecentsView.onGestureAnimationStart(runningTasks, mDeviceState.getRotationTouchHelper());
}
@@ -789,7 +801,7 @@
RecentsAnimationTargets targets) {
super.onRecentsAnimationStart(controller, targets);
ActiveGestureLog.INSTANCE.addLog("startRecentsAnimationCallback", targets.apps.length);
- mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(mContext, targets);
+ mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(targets);
mRecentsAnimationController = controller;
mRecentsAnimationTargets = targets;
@@ -1368,7 +1380,7 @@
private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory,
RemoteAnimationTargetCompat runningTaskTarget, float startProgress) {
// Directly animate the app to PiP (picture-in-picture) mode
- final ActivityManager.RunningTaskInfo taskInfo = runningTaskTarget.taskInfo;
+ final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask();
final RecentsOrientedState orientationState = mRemoteTargetHandles[0].getTaskViewSimulator()
.getOrientationState();
final int windowRotation = calculateWindowRotation(runningTaskTarget, orientationState);
@@ -1770,7 +1782,8 @@
new PictureInPictureSurfaceTransaction.Builder()
.setAlpha(0f)
.build();
- int[] taskIds = TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds();
+ int[] taskIds =
+ LauncherSplitScreenListener.INSTANCE.getNoCreate().getRunningSplitTaskIds();
for (int taskId : taskIds) {
mRecentsAnimationController.setFinishTaskTransaction(taskId,
tx, null /* overlay */);
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index ee5bb44..9828467 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -30,7 +30,7 @@
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
-import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -69,6 +69,7 @@
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.util.TransformParams.BuilderProxy;
import com.android.systemui.shared.recents.model.Task.TaskKey;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
@@ -108,7 +109,7 @@
super(context, deviceState, taskAnimationManager, gestureState, touchTimeMs,
continuingLastGesture, inputConsumer);
- mRunningOverHome = mGestureState.getRunningTask().isHomeTask();
+ mRunningOverHome = ActivityManagerWrapper.isHomeTask(mGestureState.getRunningTask());
if (mRunningOverHome) {
runActionOnRemoteHandles(remoteTargetHandle ->
remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
@@ -149,17 +150,16 @@
return new FallbackPipToHomeAnimationFactory();
}
mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration);
- startHomeIntent(mActiveAnimationFactory, runningTaskTarget);
+ startHomeIntent(mActiveAnimationFactory);
return mActiveAnimationFactory;
}
private void startHomeIntent(
- @Nullable FallbackHomeAnimationFactory gestureContractAnimationFactory,
- @Nullable RemoteAnimationTargetCompat runningTaskTarget) {
+ @Nullable FallbackHomeAnimationFactory gestureContractAnimationFactory) {
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
Intent intent = new Intent(mGestureState.getHomeIntent());
- if (gestureContractAnimationFactory != null && runningTaskTarget != null) {
- gestureContractAnimationFactory.addGestureContract(intent, runningTaskTarget.taskInfo);
+ if (gestureContractAnimationFactory != null) {
+ gestureContractAnimationFactory.addGestureContract(intent);
}
try {
mContext.startActivity(intent, options.toBundle());
@@ -187,8 +187,7 @@
// the PiP task appearing.
recentsCallback = () -> {
callback.run();
- startHomeIntent(
- null /* gestureContractAnimationFactory */, null /* runningTaskTarget */);
+ startHomeIntent(null /* gestureContractAnimationFactory */);
};
} else {
recentsCallback = callback;
@@ -213,7 +212,7 @@
if (mRunningOverHome) {
if (DisplayController.getNavigationMode(mContext).hasGestures) {
mRecentsView.onGestureAnimationStartOnHome(
- mGestureState.getRunningTask().getPlaceholderTasks(),
+ new ActivityManager.RunningTaskInfo[]{mGestureState.getRunningTask()},
mDeviceState.getRotationTouchHelper());
}
} else {
@@ -397,12 +396,12 @@
}
}
- private void addGestureContract(Intent intent, RunningTaskInfo runningTaskInfo) {
- if (mRunningOverHome || runningTaskInfo == null) {
+ private void addGestureContract(Intent intent) {
+ if (mRunningOverHome || mGestureState.getRunningTask() == null) {
return;
}
- TaskKey key = new TaskKey(runningTaskInfo);
+ TaskKey key = new TaskKey(mGestureState.getRunningTask());
if (key.getComponent() != null) {
if (sMessageReceiver == null) {
sMessageReceiver = new StaticMessageReceiver();
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 3b52e91..ed0623d 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.annotation.TargetApi;
+import android.app.ActivityManager;
import android.content.Intent;
import android.os.Build;
@@ -29,7 +30,6 @@
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.tracing.GestureStateProto;
import com.android.launcher3.tracing.SwipeHandlerProto;
-import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -135,7 +135,8 @@
private final MultiStateCallback mStateCallback;
private final int mGestureId;
- private CachedTaskInfo mRunningTask;
+ private ActivityManager.RunningTaskInfo mRunningTask;
+ private ActivityManager.RunningTaskInfo[] mRunningTasks;
private GestureEndTarget mEndTarget;
private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
private Set<Integer> mPreviouslyAppearedTaskIds = new HashSet<>();
@@ -231,25 +232,42 @@
/**
* @return the running task for this gesture.
*/
- public CachedTaskInfo getRunningTask() {
+ public ActivityManager.RunningTaskInfo getRunningTask() {
return mRunningTask;
}
/**
+ * This will array will contain the task returned by {@link #getRunningTask()}
+ * @return the running tasks for this gesture.
+ */
+ public ActivityManager.RunningTaskInfo[] getRunningTasks() {
+ return mRunningTasks;
+ }
+
+ /**
* @return the running task id for this gesture.
*/
public int getRunningTaskId() {
- return mRunningTask != null ? mRunningTask.getTaskId() : -1;
+ return mRunningTask != null ? mRunningTask.taskId : -1;
}
/**
* Updates the running task for the gesture to be the given {@param runningTask}.
*/
- public void updateRunningTask(CachedTaskInfo runningTask) {
+ public void updateRunningTask(ActivityManager.RunningTaskInfo runningTask) {
mRunningTask = runningTask;
}
/**
+ * TODO(b/210903248) refactor to consolidate w/ method above
+ * Updates the running task for the gesture to be the given {@param runningTask}.
+ */
+ public void updateRunningTasks(ActivityManager.RunningTaskInfo[] runningTasks) {
+ mRunningTasks = runningTasks;
+ updateRunningTask(runningTasks[0]);
+ }
+
+ /**
* Updates the last task that appeared during this gesture.
*/
public void updateLastAppearedTaskTarget(RemoteAnimationTargetCompat lastAppearedTaskTarget) {
@@ -321,7 +339,7 @@
* user controlled gesture.
*/
public void setHandlingAtomicEvent(boolean handlingAtomicEvent) {
- mHandlingAtomicEvent = handlingAtomicEvent;
+ mHandlingAtomicEvent = true;
}
/**
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 920ed71..7ad60bb 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -45,11 +45,14 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
+import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.graphics.Region;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
@@ -58,17 +61,18 @@
import android.os.SystemProperties;
import android.os.UserManager;
import android.provider.Settings;
+import android.text.TextUtils;
import android.view.MotionEvent;
import androidx.annotation.BinderThread;
+import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.SettingsCache;
-import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -79,6 +83,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
/**
* Manages the state of the system during a swipe up gesture.
@@ -92,6 +97,7 @@
private final int mDisplayId;
private final RotationTouchHelper mRotationTouchHelper;
private final TaskStackChangeListener mPipListener;
+ private final List<ComponentName> mGestureBlockedActivities;
// Cache for better performance since it doesn't change at runtime.
private final boolean mCanImeRenderGesturalNavButtons =
InputMethodService.canImeRenderGesturalNavButtons();
@@ -123,7 +129,6 @@
}
};
- private int mGestureBlockingTaskId = -1;
private Region mExclusionRegion;
private SystemGestureExclusionListenerCompat mExclusionListener;
@@ -173,6 +178,22 @@
onDisplayInfoChanged(context, mDisplayController.getInfo(), CHANGE_ALL);
runOnDestroy(() -> mDisplayController.removeChangeListener(this));
+ // Add any blocked activities
+ String[] blockingActivities;
+ try {
+ blockingActivities =
+ context.getResources().getStringArray(R.array.gesture_blocking_activities);
+ } catch (Resources.NotFoundException e) {
+ blockingActivities = new String[0];
+ }
+ mGestureBlockedActivities = new ArrayList<>(blockingActivities.length);
+ for (String blockingActivity : blockingActivities) {
+ if (!TextUtils.isEmpty(blockingActivity)) {
+ mGestureBlockedActivities.add(
+ ComponentName.unflattenFromString(blockingActivity));
+ }
+ }
+
SettingsCache settingsCache = SettingsCache.INSTANCE.get(mContext);
if (mIsOneHandedModeSupported) {
Uri oneHandedUri = Settings.Secure.getUriFor(ONE_HANDED_ENABLED);
@@ -346,17 +367,11 @@
}
/**
- * Sets the task id where gestures should be blocked
+ * @return whether the given running task info matches the gesture-blocked activity.
*/
- public void setGestureBlockingTaskId(int taskId) {
- mGestureBlockingTaskId = taskId;
- }
-
- /**
- * @return whether the given running task info matches the gesture-blocked task.
- */
- public boolean isGestureBlockedTask(CachedTaskInfo taskInfo) {
- return taskInfo != null && taskInfo.getTaskId() == mGestureBlockingTaskId;
+ public boolean isGestureBlockedActivity(ActivityManager.RunningTaskInfo runningTaskInfo) {
+ return runningTaskInfo != null
+ && mGestureBlockedActivities.contains(runningTaskInfo.topActivity);
}
/**
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index c3ea256..afb4d4d 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -22,6 +22,7 @@
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.quickstep.util.AnimatorControllerWithResistance;
+import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -49,7 +50,8 @@
* running tasks
*/
public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy) {
- int[] splitIds = TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds();
+ int[] splitIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
+ .getRunningSplitTaskIds();
mRemoteTargetHandles = createHandles(context, sizingStrategy, splitIds.length == 2 ? 2 : 1);
}
@@ -71,7 +73,7 @@
* Length of targets.apps should match that of {@link #mRemoteTargetHandles}.
*
* If split screen may be active when this is called, you might want to use
- * {@link #assignTargetsForSplitScreen(Context, RemoteAnimationTargets)}
+ * {@link #assignTargetsForSplitScreen(RemoteAnimationTargets)}
*/
public RemoteTargetHandle[] assignTargets(RemoteAnimationTargets targets) {
for (int i = 0; i < mRemoteTargetHandles.length; i++) {
@@ -88,9 +90,9 @@
* apps in targets.apps to that of the _active_ split screened tasks.
* See {@link #assignTargetsForSplitScreen(RemoteAnimationTargets, int[])}
*/
- public RemoteTargetHandle[] assignTargetsForSplitScreen(
- Context context, RemoteAnimationTargets targets) {
- int[] splitIds = TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds();
+ public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets) {
+ int[] splitIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
+ .getRunningSplitTaskIds();
return assignTargetsForSplitScreen(targets, splitIds);
}
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index 088e1cf..8862073 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -37,6 +37,7 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.util.AnimatorControllerWithResistance;
+import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
@@ -81,7 +82,8 @@
mGestureState = gestureState;
mIsSwipeForStagedSplit = ENABLE_SPLIT_SELECT.get() &&
- TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds().length > 1;
+ LauncherSplitScreenListener.INSTANCE.getNoCreate()
+ .getRunningSplitTaskIds().length > 1;
mTargetGluer = new RemoteTargetGluer(mContext, mGestureState.getActivityInterface());
mRemoteTargetHandles = mTargetGluer.getRemoteTargetHandles();
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index b8334a9..4bb2400 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -35,7 +35,6 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
-import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -235,8 +234,9 @@
// Allowing to pause Home if Home is top activity and Recents is not Home. So when user
// start home when recents animation is playing, the home activity can be resumed again
// to let the transition controller collect Home activity.
- CachedTaskInfo cti = gestureState.getRunningTask();
- boolean homeIsOnTop = cti != null && cti.isHomeTask();
+ ActivityManager.RunningTaskInfo rti = gestureState.getRunningTask();
+ boolean homeIsOnTop = rti != null && rti.topActivity != null
+ && rti.topActivity.equals(gestureState.getHomeIntent().getComponent());
if (!homeIsOnTop) {
options.setTransientLaunch();
}
diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java
deleted file mode 100644
index 80bc329..0000000
--- a/quickstep/src/com/android/quickstep/TopTaskTracker.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2022 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.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.content.Intent.ACTION_CHOOSER;
-import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
-
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.content.Context;
-
-import androidx.annotation.UiThread;
-
-import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.launcher3.util.SplitConfigurationOptions;
-import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
-import com.android.launcher3.util.SplitConfigurationOptions.StageType;
-import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitTaskPosition;
-import com.android.launcher3.util.TraceHelper;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.Task.TaskKey;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.TaskStackChangeListener;
-import com.android.systemui.shared.system.TaskStackChangeListeners;
-import com.android.wm.shell.splitscreen.ISplitScreenListener;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * This class tracked the top-most task and some 'approximate' task history to allow faster
- * system state estimation during touch interaction
- */
-public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskStackChangeListener {
-
- public static MainThreadInitializedObject<TopTaskTracker> INSTANCE =
- new MainThreadInitializedObject<>(TopTaskTracker::new);
-
- private static final int HISTORY_SIZE = 5;
-
- // Ordered list with first item being the most recent task.
- private final LinkedList<RunningTaskInfo> mOrderedTaskList = new LinkedList<>();
-
- private final StagedSplitTaskPosition mMainStagePosition = new StagedSplitTaskPosition();
- private final StagedSplitTaskPosition mSideStagePosition = new StagedSplitTaskPosition();
-
- private TopTaskTracker(Context context) {
- mMainStagePosition.stageType = SplitConfigurationOptions.STAGE_TYPE_MAIN;
- mSideStagePosition.stageType = SplitConfigurationOptions.STAGE_TYPE_SIDE;
-
- TaskStackChangeListeners.getInstance().registerTaskStackListener(this);
- SystemUiProxy.INSTANCE.get(context).registerSplitScreenListener(this);
- }
-
- @Override
- public void onTaskRemoved(int taskId) {
- mOrderedTaskList.removeIf(rto -> rto.taskId == taskId);
- }
-
- @Override
- public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
- mOrderedTaskList.removeIf(rto -> rto.taskId == taskInfo.taskId);
- mOrderedTaskList.addFirst(taskInfo);
- if (mOrderedTaskList.size() >= HISTORY_SIZE) {
- // If we grow in size, remove the last taskInfo which is not part of the split task.
- Iterator<RunningTaskInfo> itr = mOrderedTaskList.descendingIterator();
- while (itr.hasNext()) {
- RunningTaskInfo info = itr.next();
- if (info.taskId != taskInfo.taskId
- && info.taskId != mMainStagePosition.taskId
- && info.taskId != mSideStagePosition.taskId) {
- itr.remove();
- return;
- }
- }
- }
- }
-
- @Override
- public void onStagePositionChanged(@StageType int stage, @StagePosition int position) {
- if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) {
- mMainStagePosition.stagePosition = position;
- } else {
- mSideStagePosition.stagePosition = position;
- }
- }
-
- @Override
- public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {
- // If task is not visible but we are tracking it, stop tracking it
- if (!visible) {
- if (mMainStagePosition.taskId == taskId) {
- resetTaskId(mMainStagePosition);
- } else if (mSideStagePosition.taskId == taskId) {
- resetTaskId(mSideStagePosition);
- } // else it's an un-tracked child
- return;
- }
-
- // If stage has moved to undefined, stop tracking the task
- if (stage == SplitConfigurationOptions.STAGE_TYPE_UNDEFINED) {
- resetTaskId(taskId == mMainStagePosition.taskId
- ? mMainStagePosition : mSideStagePosition);
- return;
- }
-
- if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) {
- mMainStagePosition.taskId = taskId;
- } else {
- mSideStagePosition.taskId = taskId;
- }
- }
-
- private void resetTaskId(StagedSplitTaskPosition taskPosition) {
- taskPosition.taskId = -1;
- }
-
- /**
- * @return index 0 will be task in left/top position, index 1 in right/bottom position.
- * Will return empty array if device is not in staged split
- */
- public int[] getRunningSplitTaskIds() {
- if (mMainStagePosition.taskId == -1 || mSideStagePosition.taskId == -1) {
- return new int[]{};
- }
- int[] out = new int[2];
- if (mMainStagePosition.stagePosition == STAGE_POSITION_TOP_OR_LEFT) {
- out[0] = mMainStagePosition.taskId;
- out[1] = mSideStagePosition.taskId;
- } else {
- out[1] = mMainStagePosition.taskId;
- out[0] = mSideStagePosition.taskId;
- }
- return out;
- }
-
-
- /**
- * Returns the CachedTaskInfo for the top most task
- */
- @UiThread
- public CachedTaskInfo getCachedTopTask(boolean filterOnlyVisibleRecents) {
- if (filterOnlyVisibleRecents) {
- // Since we only know about the top most task, any filtering may not be applied on the
- // cache. The second to top task may change while the top task is still the same.
- RunningTaskInfo[] tasks = TraceHelper.allowIpcs("getCachedTopTask.true", () ->
- ActivityManagerWrapper.getInstance().getRunningTasks(true));
- return new CachedTaskInfo(Arrays.asList(tasks));
- }
-
- if (mOrderedTaskList.isEmpty()) {
- RunningTaskInfo[] tasks = TraceHelper.allowIpcs("getCachedTopTask.false", () ->
- ActivityManagerWrapper.getInstance().getRunningTasks(
- false /* filterOnlyVisibleRecents */));
- Collections.addAll(mOrderedTaskList, tasks);
- }
- return new CachedTaskInfo(new ArrayList<>(mOrderedTaskList));
- }
-
- /**
- * Class to provide information about a task which can be safely cached and do not change
- * during the lifecycle of the task.
- */
- public static class CachedTaskInfo {
-
- private final RunningTaskInfo mTopTask;
- private final List<RunningTaskInfo> mAllCachedTasks;
-
- CachedTaskInfo(List<RunningTaskInfo> allCachedTasks) {
- mAllCachedTasks = allCachedTasks;
- mTopTask = allCachedTasks.get(0);
- }
-
- public int getTaskId() {
- return mTopTask.taskId;
- }
-
- /**
- * Returns true if the root of the task chooser activity
- */
- public boolean isRootChooseActivity() {
- return ACTION_CHOOSER.equals(mTopTask.baseIntent.getAction());
- }
-
- /**
- * Returns true if the given task holds an Assistant activity that is excluded from recents
- */
- public boolean isExcludedAssistant() {
- return mTopTask.configuration.windowConfiguration
- .getActivityType() == ACTIVITY_TYPE_ASSISTANT
- && (mTopTask.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
- }
-
- /**
- * Returns true if this represents the HOME task
- */
- public boolean isHomeTask() {
- return mTopTask.configuration.windowConfiguration
- .getActivityType() == ACTIVITY_TYPE_HOME;
- }
-
- /**
- * Returns {@link Task} array which can be used as a placeholder until the true object
- * is loaded by the model
- */
- public Task[] getPlaceholderTasks() {
- return new Task[] {Task.from(new TaskKey(mTopTask), mTopTask, false)};
- }
-
- /**
- * Returns {@link Task} array corresponding to the provided task ids which can be used as a
- * placeholder until the true object is loaded by the model
- */
- public Task[] getPlaceholderTasks(int[] taskIds) {
- Task[] result = new Task[taskIds.length];
- for (int i = 0; i < taskIds.length; i++) {
- final int index = i;
- int taskId = taskIds[i];
- mAllCachedTasks.forEach(rti -> {
- if (rti.taskId == taskId) {
- result[index] = Task.from(new TaskKey(rti), rti, false);
- }
- });
- }
- return result;
- }
- }
-}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 0078d55..3206825 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep;
+import static android.content.Intent.ACTION_CHOOSER;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
@@ -40,6 +41,7 @@
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.Service;
+import android.content.ComponentName;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@@ -93,6 +95,8 @@
import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer;
import com.android.quickstep.inputconsumers.TaskbarStashInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
+import com.android.quickstep.util.AssistantUtilities;
+import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.ProxyScreenStatusProvider;
import com.android.quickstep.util.SplitScreenBounds;
@@ -310,13 +314,6 @@
public void setSwipeUpProxy(Function<GestureState, AnimatedFloat> proxy) {
mSwipeUpProxyProvider = proxy != null ? proxy : (i -> null);
}
-
- /**
- * Sets the task id where gestures should be blocked
- */
- public void setGestureBlockedTaskId(int taskId) {
- mDeviceState.setGestureBlockingTaskId(taskId);
- }
}
private static boolean sConnected = false;
@@ -372,6 +369,7 @@
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
ProtoTracer.INSTANCE.get(this).add(this);
+ LauncherSplitScreenListener.INSTANCE.get(this).init();
sConnected = true;
}
@@ -421,9 +419,6 @@
onSystemUiFlagsChanged(mDeviceState.getSystemUiStateFlags());
onAssistantVisibilityChanged();
- // Initialize the task tracker
- TopTaskTracker.INSTANCE.get(this);
-
// Temporarily disable model preload
// new ModelPreload().start(this);
mBackGestureNotificationCounter = Math.max(0, Utilities.getDevicePrefs(this)
@@ -536,6 +531,7 @@
getSystemService(AccessibilityManager.class)
.unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
+ LauncherSplitScreenListener.INSTANCE.get(this).destroy();
mTaskbarManager.destroy();
sConnected = false;
super.onDestroy();
@@ -637,7 +633,7 @@
private InputConsumer tryCreateAssistantInputConsumer(InputConsumer base,
GestureState gestureState, MotionEvent motionEvent) {
- return mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())
+ return mDeviceState.isGestureBlockedActivity(gestureState.getRunningTask())
? base
: new AssistantInputConsumer(this, gestureState, base, mInputMonitorCompat,
mDeviceState, motionEvent);
@@ -652,8 +648,8 @@
gestureState.updatePreviouslyAppearedTaskIds(
previousGestureState.getPreviouslyAppearedTaskIds());
} else {
- gestureState.updateRunningTask(
- TopTaskTracker.INSTANCE.get(this).getCachedTopTask(false));
+ gestureState.updateRunningTasks(TraceHelper.allowIpcs("getRunningTask.0",
+ () -> mAM.getRunningTasks(false /* filterOnlyVisibleRecents */)));
}
return gestureState;
}
@@ -747,14 +743,17 @@
// Use overview input consumer for sharesheets on top of home.
boolean forceOverviewInputConsumer = gestureState.getActivityInterface().isStarted()
&& gestureState.getRunningTask() != null
- && gestureState.getRunningTask().isRootChooseActivity();
- if (gestureState.getRunningTask() != null
- && gestureState.getRunningTask().isExcludedAssistant()) {
+ && ACTION_CHOOSER.equals(gestureState.getRunningTask().baseIntent.getAction());
+ if (AssistantUtilities.isExcludedAssistant(gestureState.getRunningTask())) {
// In the case where we are in the excluded assistant state, ignore it and treat the
// running activity as the task behind the assistant
- gestureState.updateRunningTask(TopTaskTracker.INSTANCE.get(this)
- .getCachedTopTask(true /* filterOnlyVisibleRecents */));
- forceOverviewInputConsumer = gestureState.getRunningTask().isHomeTask();
+ gestureState.updateRunningTask(TraceHelper.allowIpcs("getRunningTask.assistant",
+ () -> mAM.getRunningTask(true /* filterOnlyVisibleRecents */)));
+ ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent();
+ ComponentName runningComponent =
+ gestureState.getRunningTask().baseIntent.getComponent();
+ forceOverviewInputConsumer =
+ runningComponent != null && runningComponent.equals(homeComponent);
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get()
@@ -771,7 +770,7 @@
|| forceOverviewInputConsumer) {
return createOverviewInputConsumer(
previousGestureState, gestureState, event, forceOverviewInputConsumer);
- } else if (mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())) {
+ } else if (mDeviceState.isGestureBlockedActivity(gestureState.getRunningTask())) {
return getDefaultInputConsumer();
} else {
return createOtherActivityInputConsumer(gestureState, event);
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index c9ee2db..48af802 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -24,6 +24,7 @@
import android.animation.AnimatorSet;
import android.annotation.TargetApi;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
@@ -49,6 +50,7 @@
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.Task.TaskKey;
import java.util.ArrayList;
@@ -56,7 +58,7 @@
public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsState>
implements StateListener<RecentsState> {
- private Task mHomeTask;
+ private RunningTaskInfo mHomeTaskInfo;
public FallbackRecentsView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -85,12 +87,12 @@
* to the home task. This allows us to handle quick-switch similarly to a quick-switching
* from a foreground task.
*/
- public void onGestureAnimationStartOnHome(Task[] homeTask,
+ public void onGestureAnimationStartOnHome(RunningTaskInfo[] homeTaskInfo,
RotationTouchHelper rotationTouchHelper) {
// TODO(b/195607777) General fallback love, but this might be correct
// Home task should be defined as the front-most task info I think?
- mHomeTask = homeTask[0];
- onGestureAnimationStart(homeTask, rotationTouchHelper);
+ mHomeTaskInfo = homeTaskInfo[0];
+ onGestureAnimationStart(homeTaskInfo, rotationTouchHelper);
}
/**
@@ -103,8 +105,8 @@
@Nullable AnimatorSet animatorSet, GestureState.GestureEndTarget endTarget,
TaskViewSimulator[] taskViewSimulators) {
super.onPrepareGestureEndAnimation(animatorSet, endTarget, taskViewSimulators);
- if (mHomeTask != null && endTarget == RECENTS && animatorSet != null) {
- TaskView tv = getTaskViewByTaskId(mHomeTask.key.id);
+ if (mHomeTaskInfo != null && endTarget == RECENTS && animatorSet != null) {
+ TaskView tv = getTaskViewByTaskId(mHomeTaskInfo.taskId);
if (tv != null) {
PendingAnimation pa = createTaskDismissAnimation(tv, true, false, 150,
false /* dismissingForSplitSelection*/);
@@ -129,8 +131,8 @@
public void setCurrentTask(int runningTaskViewId) {
super.setCurrentTask(runningTaskViewId);
int runningTaskId = getTaskIdsForRunningTaskView()[0];
- if (mHomeTask != null && mHomeTask.key.id != runningTaskId) {
- mHomeTask = null;
+ if (mHomeTaskInfo != null && mHomeTaskInfo.taskId != runningTaskId) {
+ mHomeTaskInfo = null;
setRunningTaskHidden(false);
}
}
@@ -138,26 +140,26 @@
@Nullable
@Override
protected TaskView getHomeTaskView() {
- return mHomeTask != null ? getTaskViewByTaskId(mHomeTask.key.id) : null;
+ return mHomeTaskInfo != null ? getTaskViewByTaskId(mHomeTaskInfo.taskId) : null;
}
@Override
- protected boolean shouldAddStubTaskView(Task[] runningTasks) {
- if (runningTasks.length > 1) {
+ protected boolean shouldAddStubTaskView(RunningTaskInfo[] runningTaskInfos) {
+ if (runningTaskInfos.length > 1) {
// can't be in split screen w/ home task
- return super.shouldAddStubTaskView(runningTasks);
+ return super.shouldAddStubTaskView(runningTaskInfos);
}
- Task runningTask = runningTasks[0];
- if (mHomeTask != null && runningTask != null
- && mHomeTask.key.id == runningTask.key.id
+ RunningTaskInfo runningTaskInfo = runningTaskInfos[0];
+ if (mHomeTaskInfo != null && runningTaskInfo != null &&
+ mHomeTaskInfo.taskId == runningTaskInfo.taskId
&& getTaskViewCount() == 0 && mLoadPlanEverApplied) {
// Do not add a stub task if we are running over home with empty recents, so that we
// show the empty recents message instead of showing a stub task and later removing it.
// Ignore empty task signal if applyLoadPlan has never run.
return false;
}
- return super.shouldAddStubTaskView(runningTasks);
+ return super.shouldAddStubTaskView(runningTaskInfos);
}
@Override
@@ -167,7 +169,7 @@
// track the index of the next task appropriately, as if we are switching on any other app.
// TODO(b/195607777) Confirm home task info is front-most task and not mixed in with others
int runningTaskId = getTaskIdsForRunningTaskView()[0];
- if (mHomeTask != null && mHomeTask.key.id == runningTaskId
+ if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == runningTaskId
&& !taskGroups.isEmpty()) {
// Check if the task list has running task
boolean found = false;
@@ -180,7 +182,9 @@
if (!found) {
ArrayList<GroupTask> newList = new ArrayList<>(taskGroups.size() + 1);
newList.addAll(taskGroups);
- newList.add(new GroupTask(mHomeTask, null, null));
+ newList.add(new GroupTask(
+ Task.from(new TaskKey(mHomeTaskInfo), mHomeTaskInfo, false),
+ null, null));
taskGroups = newList;
}
}
@@ -189,7 +193,7 @@
@Override
public void setRunningTaskHidden(boolean isHidden) {
- if (mHomeTask != null) {
+ if (mHomeTaskInfo != null) {
// Always keep the home task hidden
isHidden = true;
}
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index db19c45..5ef9a9b 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -21,6 +21,7 @@
import android.animation.Animator;
import android.app.Activity;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@@ -223,7 +224,8 @@
if (!state.getHomeIntent().getComponent().getPackageName().equals(getPackageName())) {
return null;
}
- if (state.getRunningTaskId() != getTaskId()) {
+ RunningTaskInfo rti = state.getRunningTask();
+ if (rti == null || !rti.topActivity.equals(getComponentName())) {
return null;
}
mSwipeProgress.updateValue(0);
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index bf7023c..7daac81 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -31,11 +31,9 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.logging.StatsLogManager;
-import com.android.quickstep.TouchInteractionService.TISBinder;
import com.android.quickstep.interaction.TutorialController.TutorialType;
-import com.android.quickstep.util.TISBindHelper;
-import java.util.Arrays;
+import java.util.List;
/** Shows the gesture interactive sandbox in full screen mode. */
public class GestureSandboxActivity extends FragmentActivity {
@@ -54,9 +52,6 @@
private SharedPreferences mSharedPrefs;
private StatsLogManager mStatsLogManager;
- private TISBindHelper mTISBindHelper;
- private TISBinder mBinder;
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -74,8 +69,6 @@
getSupportFragmentManager().beginTransaction()
.add(R.id.gesture_tutorial_fragment_container, mFragment)
.commit();
-
- mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
}
@Override
@@ -213,37 +206,7 @@
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
getWindow().setSystemGestureExclusionRects(
- Arrays.asList(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)));
+ List.of(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)));
}
}
-
- @Override
- protected void onResume() {
- super.onResume();
- updateServiceState(true);
- }
-
- private void onTISConnected(TISBinder binder) {
- mBinder = binder;
- updateServiceState(isResumed());
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- updateServiceState(false);
- }
-
- private void updateServiceState(boolean isEnabled) {
- if (mBinder != null) {
- mBinder.setGestureBlockedTaskId(isEnabled ? getTaskId() : -1);
- }
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mTISBindHelper.onDestroy();
- updateServiceState(false);
- }
}
diff --git a/quickstep/src/com/android/quickstep/util/AssistantUtilities.java b/quickstep/src/com/android/quickstep/util/AssistantUtilities.java
new file mode 100644
index 0000000..336f7d1
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/AssistantUtilities.java
@@ -0,0 +1,46 @@
+/*
+ * 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.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
+
+import android.annotation.TargetApi;
+import android.app.TaskInfo;
+import android.content.Intent;
+import android.os.Build;
+
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+
+/**
+ * Utility class for interacting with the Assistant.
+ */
+@TargetApi(Build.VERSION_CODES.Q)
+public final class AssistantUtilities {
+
+ /** Returns true if an Assistant activity that is excluded from recents is running. */
+ public static boolean isExcludedAssistantRunning() {
+ return isExcludedAssistant(ActivityManagerWrapper.getInstance().getRunningTask());
+ }
+
+ /** Returns true if the given task holds an Assistant activity that is excluded from recents. */
+ public static boolean isExcludedAssistant(TaskInfo info) {
+ return info != null
+ && info.configuration.windowConfiguration.getActivityType() == ACTIVITY_TYPE_ASSISTANT
+ && (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
+ }
+
+ private AssistantUtilities() {}
+}
diff --git a/quickstep/src/com/android/quickstep/util/LauncherSplitScreenListener.java b/quickstep/src/com/android/quickstep/util/LauncherSplitScreenListener.java
new file mode 100644
index 0000000..affe625
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/LauncherSplitScreenListener.java
@@ -0,0 +1,119 @@
+package com.android.quickstep.util;
+
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
+
+import android.content.Context;
+import android.os.IBinder;
+
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.SplitConfigurationOptions;
+import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
+import com.android.launcher3.util.SplitConfigurationOptions.StageType;
+import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitTaskPosition;
+import com.android.quickstep.SystemUiProxy;
+import com.android.wm.shell.splitscreen.ISplitScreenListener;
+
+/**
+ * Listeners for system wide split screen position and stage changes.
+ *
+ * Use {@link #getRunningSplitTaskIds()} to determine which tasks, if any, are actively in
+ * staged split.
+ */
+public class LauncherSplitScreenListener extends ISplitScreenListener.Stub {
+
+ public static final MainThreadInitializedObject<LauncherSplitScreenListener> INSTANCE =
+ new MainThreadInitializedObject<>(LauncherSplitScreenListener::new);
+
+ private static final int[] EMPTY_ARRAY = {};
+
+ private final StagedSplitTaskPosition mMainStagePosition = new StagedSplitTaskPosition();
+ private final StagedSplitTaskPosition mSideStagePosition = new StagedSplitTaskPosition();
+
+ /**
+ * Gets set to current split taskIDs whenever the task list is frozen, and set to empty array
+ * whenever task list unfreezes. This also gets set to empty array whenever the user swipes to
+ * home - in that case the task list does not unfreeze immediately after the gesture, so it's
+ * done via {@link #notifySwipingToHome()}.
+ *
+ * When not empty, this indicates that we need to load a GroupedTaskView as the most recent
+ * page, so user can quickswitch back to a grouped task.
+ */
+ private int[] mPersistentGroupedIds;
+
+ public LauncherSplitScreenListener(Context context) {
+ mMainStagePosition.stageType = SplitConfigurationOptions.STAGE_TYPE_MAIN;
+ mSideStagePosition.stageType = SplitConfigurationOptions.STAGE_TYPE_SIDE;
+ }
+
+ /** Also call {@link #destroy()} when done. */
+ public void init() {
+ SystemUiProxy.INSTANCE.getNoCreate().registerSplitScreenListener(this);
+ }
+
+ public void destroy() {
+ SystemUiProxy.INSTANCE.getNoCreate().unregisterSplitScreenListener(this);
+ }
+
+ /**
+ * @return index 0 will be task in left/top position, index 1 in right/bottom position.
+ * Will return empty array if device is not in staged split
+ */
+ public int[] getRunningSplitTaskIds() {
+ if (mMainStagePosition.taskId == -1 || mSideStagePosition.taskId == -1) {
+ return new int[]{};
+ }
+ int[] out = new int[2];
+ if (mMainStagePosition.stagePosition == STAGE_POSITION_TOP_OR_LEFT) {
+ out[0] = mMainStagePosition.taskId;
+ out[1] = mSideStagePosition.taskId;
+ } else {
+ out[1] = mMainStagePosition.taskId;
+ out[0] = mSideStagePosition.taskId;
+ }
+ return out;
+ }
+
+ @Override
+ public void onStagePositionChanged(@StageType int stage, @StagePosition int position) {
+ if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) {
+ mMainStagePosition.stagePosition = position;
+ } else {
+ mSideStagePosition.stagePosition = position;
+ }
+ }
+
+ @Override
+ public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {
+ // If task is not visible but we are tracking it, stop tracking it
+ if (!visible) {
+ if (mMainStagePosition.taskId == taskId) {
+ resetTaskId(mMainStagePosition);
+ } else if (mSideStagePosition.taskId == taskId) {
+ resetTaskId(mSideStagePosition);
+ } // else it's an un-tracked child
+ return;
+ }
+
+ // If stage has moved to undefined, stop tracking the task
+ if (stage == SplitConfigurationOptions.STAGE_TYPE_UNDEFINED) {
+ resetTaskId(taskId == mMainStagePosition.taskId ?
+ mMainStagePosition : mSideStagePosition);
+ return;
+ }
+
+ if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) {
+ mMainStagePosition.taskId = taskId;
+ } else {
+ mSideStagePosition.taskId = taskId;
+ }
+ }
+
+ private void resetTaskId(StagedSplitTaskPosition taskPosition) {
+ taskPosition.taskId = -1;
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return this;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 10da83f..ed00b8e 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -64,8 +64,8 @@
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
-import android.annotation.SuppressLint;
import android.annotation.TargetApi;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.LocusId;
import android.content.res.Configuration;
@@ -171,6 +171,7 @@
import com.android.quickstep.util.VibratorWrapper;
import com.android.systemui.plugins.ResourceProvider;
import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
@@ -2079,8 +2080,8 @@
/**
* Called when a gesture from an app is starting.
*/
- public void onGestureAnimationStart(
- Task[] runningTasks, RotationTouchHelper rotationTouchHelper) {
+ public void onGestureAnimationStart(RunningTaskInfo[] runningTaskInfo,
+ RotationTouchHelper rotationTouchHelper) {
mGestureActive = true;
// This needs to be called before the other states are set since it can create the task view
if (mOrientationState.setGestureActive(true)) {
@@ -2091,7 +2092,7 @@
updateSizeAndPadding();
}
- showCurrentTask(runningTasks);
+ showCurrentTask(runningTaskInfo);
setEnableFreeScroll(false);
setEnableDrawingLiveTile(false);
setRunningTaskHidden(true);
@@ -2207,10 +2208,10 @@
/**
* Returns true if we should add a stub taskView for the running task id
*/
- protected boolean shouldAddStubTaskView(Task[] runningTasks) {
- if (runningTasks.length > 1) {
- TaskView primaryTaskView = getTaskViewByTaskId(runningTasks[0].key.id);
- TaskView secondaryTaskView = getTaskViewByTaskId(runningTasks[1].key.id);
+ protected boolean shouldAddStubTaskView(RunningTaskInfo[] runningTaskInfos) {
+ if (runningTaskInfos.length > 1) {
+ TaskView primaryTaskView = getTaskViewByTaskId(runningTaskInfos[0].taskId);
+ TaskView secondaryTaskView = getTaskViewByTaskId(runningTaskInfos[1].taskId);
int leftTopTaskViewId =
(primaryTaskView == null) ? -1 : primaryTaskView.getTaskViewId();
int rightBottomTaskViewId =
@@ -2218,8 +2219,8 @@
// Add a new stub view if both taskIds don't match any taskViews
return leftTopTaskViewId != rightBottomTaskViewId || leftTopTaskViewId == -1;
}
- Task runningTaskInfo = runningTasks[0];
- return runningTaskInfo != null && getTaskViewByTaskId(runningTaskInfo.key.id) == null;
+ RunningTaskInfo runningTaskInfo = runningTaskInfos[0];
+ return runningTaskInfo != null && getTaskViewByTaskId(runningTaskInfo.taskId) == null;
}
/**
@@ -2228,16 +2229,21 @@
* All subsequent calls to reload will keep the task as the first item until {@link #reset()}
* is called. Also scrolls the view to this task.
*/
- private void showCurrentTask(Task[] runningTasks) {
+ private void showCurrentTask(RunningTaskInfo[] runningTaskInfo) {
int runningTaskViewId = -1;
- boolean needGroupTaskView = runningTasks.length > 1;
- if (shouldAddStubTaskView(runningTasks)) {
+ boolean needGroupTaskView = runningTaskInfo.length > 1;
+ RunningTaskInfo taskInfo = runningTaskInfo[0];
+ if (shouldAddStubTaskView(runningTaskInfo)) {
boolean wasEmpty = getChildCount() == 0;
// Add an empty view for now until the task plan is loaded and applied
final TaskView taskView;
if (needGroupTaskView) {
taskView = getTaskViewFromPool(true);
- mTmpRunningTasks = new Task[]{runningTasks[0], runningTasks[1]};
+ RunningTaskInfo secondaryTaskInfo = runningTaskInfo[1];
+ mTmpRunningTasks = new Task[]{
+ Task.from(new TaskKey(taskInfo), taskInfo, false),
+ Task.from(new TaskKey(secondaryTaskInfo), secondaryTaskInfo, false)
+ };
addView(taskView, 0);
// When we create a placeholder task view mSplitBoundsConfig will be null, but with
// the actual app running we won't need to show the thumbnail until all the tasks
@@ -2249,7 +2255,7 @@
addView(taskView, 0);
// The temporary running task is only used for the duration between the start of the
// gesture and the task list is loaded and applied
- mTmpRunningTasks = new Task[]{runningTasks[0]};
+ mTmpRunningTasks = new Task[]{Task.from(new TaskKey(taskInfo), taskInfo, false)};
taskView.bind(mTmpRunningTasks[0], mOrientationState);
}
runningTaskViewId = taskView.getTaskViewId();
@@ -2262,8 +2268,8 @@
measure(makeMeasureSpec(getMeasuredWidth(), EXACTLY),
makeMeasureSpec(getMeasuredHeight(), EXACTLY));
layout(getLeft(), getTop(), getRight(), getBottom());
- } else if (getTaskViewByTaskId(runningTasks[0].key.id) != null) {
- runningTaskViewId = getTaskViewByTaskId(runningTasks[0].key.id).getTaskViewId();
+ } else if (getTaskViewByTaskId(taskInfo.taskId) != null) {
+ runningTaskViewId = getTaskViewByTaskId(taskInfo.taskId).getTaskViewId();
}
boolean runningTaskTileHidden = mRunningTaskTileHidden;
@@ -4053,7 +4059,6 @@
}
/** TODO(b/181707736) More gracefully handle exiting split selection state */
- @SuppressLint("WrongCall")
protected void resetFromSplitSelectionState() {
if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1) {
if (mFirstFloatingTaskView != null) {
@@ -4428,8 +4433,7 @@
}
RemoteTargetGluer gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
- mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(
- getContext(), recentsAnimationTargets);
+ mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
mSplitBoundsConfig = gluer.getStagedSplitBounds();
// Add release check to the targets from the RemoteTargetGluer and not the targets
// passed in because in the event we're in split screen, we use the passed in targets
@@ -4540,7 +4544,6 @@
/**
* Updates page scroll synchronously after measure and layout child views.
*/
- @SuppressLint("WrongCall")
public void updateScrollSynchronously() {
// onMeasure is needed to update child's measured width which is used in scroll calculation,
// in case TaskView sizes has changed when being focused/unfocused.