mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-03-04 09:56:49 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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 */);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user