Revert "Removing AM.getTasks call on UI thread during touch down"

This reverts commit 013a8a75ab.

Reason for revert: Broke builds

Bug: 229619753
Change-Id: Idb1aecf1d43db50aa4f11dbb88079c37e401d694
This commit is contained in:
Sam Dubey
2022-04-18 16:47:24 +00:00
parent 013a8a75ab
commit f9042d32ae
16 changed files with 335 additions and 399 deletions

View File

@@ -48,8 +48,8 @@ import com.android.launcher3.states.StateAnimationConfig;
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 @@ public class NavBarToHomeTouchController implements TouchController,
return true;
}
if (FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
&& TopTaskTracker.INSTANCE.get(mLauncher).getCachedTopTask(false)
.isExcludedAssistant()) {
&& AssistantUtilities.isExcludedAssistantRunning()) {
return true;
}
return false;

View File

@@ -102,6 +102,7 @@ import com.android.quickstep.util.ActivityInitListener;
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.TaskViewSimulator;
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 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
}
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 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
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 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
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 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
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 */);

View File

@@ -30,7 +30,7 @@ import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACT
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.RectFSpringAnim;
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 @@ public class FallbackSwipeHandler extends
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 @@ public class FallbackSwipeHandler extends
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 @@ public class FallbackSwipeHandler extends
// the PiP task appearing.
recentsCallback = () -> {
callback.run();
startHomeIntent(
null /* gestureContractAnimationFactory */, null /* runningTaskTarget */);
startHomeIntent(null /* gestureContractAnimationFactory */);
};
} else {
recentsCallback = callback;
@@ -213,7 +212,7 @@ public class FallbackSwipeHandler extends
if (mRunningOverHome) {
if (DisplayController.getNavigationMode(mContext).hasGestures) {
mRecentsView.onGestureAnimationStartOnHome(
mGestureState.getRunningTask().getPlaceholderTasks(),
new ActivityManager.RunningTaskInfo[]{mGestureState.getRunningTask()},
mDeviceState.getRotationTouchHelper());
}
} else {
@@ -397,12 +396,12 @@ public class FallbackSwipeHandler extends
}
}
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();

View File

@@ -22,6 +22,7 @@ import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
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.BaseState;
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 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
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,24 +232,41 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
/**
* @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.
*/
@@ -321,7 +339,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
* user controlled gesture.
*/
public void setHandlingAtomicEvent(boolean handlingAtomicEvent) {
mHandlingAtomicEvent = handlingAtomicEvent;
mHandlingAtomicEvent = true;
}
/**

View File

@@ -45,11 +45,14 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_Q
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.RemoteException;
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 com.android.systemui.shared.system.TaskStackChangeListeners;
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 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
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 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
}
};
private int mGestureBlockingTaskId = -1;
private Region mExclusionRegion;
private SystemGestureExclusionListenerCompat mExclusionListener;
@@ -173,6 +178,22 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
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 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
}
/**
* 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);
}
/**

View File

@@ -22,6 +22,7 @@ import androidx.annotation.Nullable;
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 @@ public class RemoteTargetGluer {
* 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 @@ public class RemoteTargetGluer {
* 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 @@ public class RemoteTargetGluer {
* 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);
}

View File

@@ -37,6 +37,7 @@ import com.android.launcher3.anim.PendingAnimation;
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 @@ public abstract class SwipeUpAnimationLogic implements
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();

View File

@@ -35,7 +35,6 @@ import androidx.annotation.UiThread;
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 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
// 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();
}

View File

@@ -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;
}
}
}

View File

@@ -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.annotation.TargetApi;
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.ScreenPinnedInputConsumer;
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 class TouchInteractionService extends Service
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 @@ public class TouchInteractionService extends Service
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
ProtoTracer.INSTANCE.get(this).add(this);
LauncherSplitScreenListener.INSTANCE.get(this).init();
sConnected = true;
}
@@ -421,9 +419,6 @@ public class TouchInteractionService extends Service
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 @@ public class TouchInteractionService extends Service
getSystemService(AccessibilityManager.class)
.unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
LauncherSplitScreenListener.INSTANCE.get(this).destroy();
mTaskbarManager.destroy();
sConnected = false;
super.onDestroy();
@@ -637,7 +633,7 @@ public class TouchInteractionService extends Service
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 @@ public class TouchInteractionService extends Service
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 @@ public class TouchInteractionService extends Service
// 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 @@ public class TouchInteractionService extends Service
|| 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);

View File

@@ -24,6 +24,7 @@ import static com.android.quickstep.fallback.RecentsState.OVERVIEW_SPLIT_SELECT;
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.OverviewActionsView;
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 @@ import java.util.ArrayList;
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 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
* 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 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
@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 class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
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 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
@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 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
// 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 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
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 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
@Override
public void setRunningTaskHidden(boolean isHidden) {
if (mHomeTask != null) {
if (mHomeTaskInfo != null) {
// Always keep the home task hidden
isHidden = true;
}

View File

@@ -21,6 +21,7 @@ import static com.android.launcher3.anim.Interpolators.LINEAR;
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 @@ public class AllSetActivity extends Activity {
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);

View File

@@ -31,11 +31,9 @@ import androidx.fragment.app.FragmentActivity;
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 @@ public class GestureSandboxActivity extends FragmentActivity {
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 @@ public class GestureSandboxActivity extends FragmentActivity {
getSupportFragmentManager().beginTransaction()
.add(R.id.gesture_tutorial_fragment_container, mFragment)
.commit();
mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
}
@Override
@@ -213,37 +206,7 @@ public class GestureSandboxActivity extends FragmentActivity {
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);
}
}

View File

@@ -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() {}
}

View File

@@ -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;
}
}

View File

@@ -64,8 +64,8 @@ import android.animation.LayoutTransition.TransitionListener;
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.TransformParams;
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 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
/**
* 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 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
updateSizeAndPadding();
}
showCurrentTask(runningTasks);
showCurrentTask(runningTaskInfo);
setEnableFreeScroll(false);
setEnableDrawingLiveTile(false);
setRunningTaskHidden(true);
@@ -2207,10 +2208,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
/**
* 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 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// 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 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* 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 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
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 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
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 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
/** 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 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
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 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
/**
* 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.