Save and pass last snapshot data with recents task info
- Adds task & snapshot sizing info to RecentTaskInfo so that SysUI can stably layout overview when there are tasks of different sizes - Removing some unused code Bug: 179466077 Test: atest WmTests:RecentTasksTest Change-Id: Idf4c27e2d04380328413459fc537ff8bcc111a14
This commit is contained in:
@@ -50,7 +50,9 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
@@ -76,6 +78,7 @@ import android.util.Singleton;
|
||||
import android.util.Size;
|
||||
import android.util.TypedXmlPullParser;
|
||||
import android.util.TypedXmlSerializer;
|
||||
import android.window.TaskSnapshot;
|
||||
|
||||
import com.android.internal.app.LocalePicker;
|
||||
import com.android.internal.app.procstats.ProcessStats;
|
||||
@@ -1739,6 +1742,62 @@ public class ActivityManager {
|
||||
* started or visited.
|
||||
*/
|
||||
public static class RecentTaskInfo extends TaskInfo implements Parcelable {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static class PersistedTaskSnapshotData {
|
||||
/**
|
||||
* The bounds of the task when the last snapshot was taken, may be null if the task is
|
||||
* not yet attached to the hierarchy.
|
||||
* @see {@link android.window.TaskSnapshot#mTaskSize}.
|
||||
* @hide
|
||||
*/
|
||||
public @Nullable Point taskSize;
|
||||
|
||||
/**
|
||||
* The content insets of the task when the task snapshot was taken.
|
||||
* @see {@link android.window.TaskSnapshot#mContentInsets}.
|
||||
* @hide
|
||||
*/
|
||||
public @Nullable Rect contentInsets;
|
||||
|
||||
/**
|
||||
* The size of the last snapshot taken, may be null if there is no associated snapshot.
|
||||
* @see {@link android.window.TaskSnapshot#mSnapshot}.
|
||||
* @hide
|
||||
*/
|
||||
public @Nullable Point bufferSize;
|
||||
|
||||
/**
|
||||
* Sets the data from the other data.
|
||||
* @hide
|
||||
*/
|
||||
public void set(PersistedTaskSnapshotData other) {
|
||||
taskSize = other.taskSize;
|
||||
contentInsets = other.contentInsets;
|
||||
bufferSize = other.bufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data from the provided {@param snapshot}.
|
||||
* @hide
|
||||
*/
|
||||
public void set(TaskSnapshot snapshot) {
|
||||
if (snapshot == null) {
|
||||
taskSize = null;
|
||||
contentInsets = null;
|
||||
bufferSize = null;
|
||||
return;
|
||||
}
|
||||
final HardwareBuffer buffer = snapshot.getHardwareBuffer();
|
||||
taskSize = new Point(snapshot.getTaskSize());
|
||||
contentInsets = new Rect(snapshot.getContentInsets());
|
||||
bufferSize = buffer != null
|
||||
? new Point(buffer.getWidth(), buffer.getHeight())
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this task is currently running, this is the identifier for it.
|
||||
* If it is not running, this will be -1.
|
||||
@@ -1782,6 +1841,12 @@ public class ActivityManager {
|
||||
*/
|
||||
public ArrayList<RecentTaskInfo> childrenTaskInfos = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Information about the last snapshot taken for this task.
|
||||
* @hide
|
||||
*/
|
||||
public PersistedTaskSnapshotData lastSnapshotData = new PersistedTaskSnapshotData();
|
||||
|
||||
public RecentTaskInfo() {
|
||||
}
|
||||
|
||||
@@ -1798,6 +1863,9 @@ public class ActivityManager {
|
||||
id = source.readInt();
|
||||
persistentId = source.readInt();
|
||||
childrenTaskInfos = source.readArrayList(RecentTaskInfo.class.getClassLoader());
|
||||
lastSnapshotData.taskSize = source.readTypedObject(Point.CREATOR);
|
||||
lastSnapshotData.contentInsets = source.readTypedObject(Rect.CREATOR);
|
||||
lastSnapshotData.bufferSize = source.readTypedObject(Point.CREATOR);
|
||||
super.readFromParcel(source);
|
||||
}
|
||||
|
||||
@@ -1806,6 +1874,9 @@ public class ActivityManager {
|
||||
dest.writeInt(id);
|
||||
dest.writeInt(persistentId);
|
||||
dest.writeList(childrenTaskInfos);
|
||||
dest.writeTypedObject(lastSnapshotData.taskSize, flags);
|
||||
dest.writeTypedObject(lastSnapshotData.contentInsets, flags);
|
||||
dest.writeTypedObject(lastSnapshotData.bufferSize, flags);
|
||||
super.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
@@ -1825,7 +1896,6 @@ public class ActivityManager {
|
||||
public void dump(PrintWriter pw, String indent) {
|
||||
pw.println(); pw.print(" ");
|
||||
pw.print(" id="); pw.print(persistentId);
|
||||
pw.print(" stackId="); pw.print(stackId);
|
||||
pw.print(" userId="); pw.print(userId);
|
||||
pw.print(" hasTask="); pw.print((id != -1));
|
||||
pw.print(" lastActiveTime="); pw.println(lastActiveTime);
|
||||
@@ -1872,6 +1942,12 @@ public class ActivityManager {
|
||||
pw.print(Integer.toHexString(td.getBackgroundColorFloating()));
|
||||
pw.println(" }");
|
||||
}
|
||||
pw.print(" ");
|
||||
pw.print(" lastSnapshotData {");
|
||||
pw.print(" taskSize=" + lastSnapshotData.taskSize);
|
||||
pw.print(" contentInsets=" + lastSnapshotData.contentInsets);
|
||||
pw.print(" bufferSize=" + lastSnapshotData.bufferSize);
|
||||
pw.println(" }");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,13 +52,6 @@ public class TaskInfo {
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
public int userId;
|
||||
|
||||
/**
|
||||
* The id of the ActivityStack that currently contains this task.
|
||||
* @hide
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
public int stackId;
|
||||
|
||||
/**
|
||||
* The identifier for this task.
|
||||
*/
|
||||
@@ -358,7 +351,6 @@ public class TaskInfo {
|
||||
*/
|
||||
void readFromParcel(Parcel source) {
|
||||
userId = source.readInt();
|
||||
stackId = source.readInt();
|
||||
taskId = source.readInt();
|
||||
displayId = source.readInt();
|
||||
isRunning = source.readBoolean();
|
||||
@@ -394,7 +386,6 @@ public class TaskInfo {
|
||||
*/
|
||||
void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(userId);
|
||||
dest.writeInt(stackId);
|
||||
dest.writeInt(taskId);
|
||||
dest.writeInt(displayId);
|
||||
dest.writeBoolean(isRunning);
|
||||
@@ -428,7 +419,7 @@ public class TaskInfo {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TaskInfo{userId=" + userId + " stackId=" + stackId + " taskId=" + taskId
|
||||
return "TaskInfo{userId=" + userId + " taskId=" + taskId
|
||||
+ " displayId=" + displayId
|
||||
+ " isRunning=" + isRunning
|
||||
+ " baseIntent=" + baseIntent + " baseActivity=" + baseActivity
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.graphics;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
@@ -95,6 +96,27 @@ public class Point implements Parcelable {
|
||||
return "Point(" + x + ", " + y + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns a {@link String} that represents this point which can be parsed with
|
||||
* {@link #unflattenFromString(String)}.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public String flattenToString() {
|
||||
return x + "x" + y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns a {@link Point} from a short string created from {@link #flattenToString()}.
|
||||
* @hide
|
||||
*/
|
||||
@Nullable
|
||||
public static Point unflattenFromString(String s) throws NumberFormatException {
|
||||
final int sep_ix = s.indexOf("x");
|
||||
return new Point(Integer.parseInt(s.substring(0, sep_ix)),
|
||||
Integer.parseInt(s.substring(sep_ix + 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable interface methods
|
||||
*/
|
||||
|
||||
@@ -43,17 +43,6 @@ public class Task {
|
||||
|
||||
public static final String TAG = "Task";
|
||||
|
||||
/* Task callbacks */
|
||||
@Deprecated
|
||||
public interface TaskCallbacks {
|
||||
/* Notifies when a task has been bound */
|
||||
void onTaskDataLoaded(Task task, ThumbnailData thumbnailData);
|
||||
/* Notifies when a task has been unbound */
|
||||
void onTaskDataUnloaded();
|
||||
/* Notifies when a task's windowing mode has changed. */
|
||||
void onTaskWindowingModeChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* The Task Key represents the unique primary key for the task
|
||||
*/
|
||||
@@ -208,12 +197,6 @@ public class Task {
|
||||
@ViewDebug.ExportedProperty(deepExport=true, prefix="key_")
|
||||
public TaskKey key;
|
||||
|
||||
/**
|
||||
* The temporary sort index in the stack, used when ordering the stack.
|
||||
*/
|
||||
@Deprecated
|
||||
public int temporarySortIndexInStack;
|
||||
|
||||
/**
|
||||
* The icon is the task description icon (if provided), which falls back to the activity icon,
|
||||
* which can then fall back to the application icon.
|
||||
@@ -229,45 +212,24 @@ public class Task {
|
||||
public int colorPrimary;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public int colorBackground;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Deprecated
|
||||
public boolean useLightOnPrimaryColor;
|
||||
|
||||
/**
|
||||
* The task description for this task, only used to reload task icons.
|
||||
*/
|
||||
public TaskDescription taskDescription;
|
||||
|
||||
/**
|
||||
* The state isLaunchTarget will be set for the correct task upon launching Recents.
|
||||
*/
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Deprecated
|
||||
public boolean isLaunchTarget;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Deprecated
|
||||
public boolean isStackTask;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Deprecated
|
||||
public boolean isSystemApp;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public boolean isDockable;
|
||||
|
||||
/**
|
||||
* Resize mode. See {@link ActivityInfo#resizeMode}.
|
||||
*/
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Deprecated
|
||||
public int resizeMode;
|
||||
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public ComponentName topActivity;
|
||||
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public boolean isLocked;
|
||||
|
||||
@Deprecated
|
||||
private ArrayList<TaskCallbacks> mCallbacks = new ArrayList<>();
|
||||
// Last snapshot data, only used for recent tasks
|
||||
public ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData lastSnapshotData =
|
||||
new ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData();
|
||||
|
||||
public Task() {
|
||||
// Do nothing
|
||||
@@ -289,6 +251,15 @@ public class Task {
|
||||
this.taskDescription = new TaskDescription();
|
||||
}
|
||||
|
||||
public Task(Task other) {
|
||||
this(other.key, other.colorPrimary, other.colorBackground, other.isDockable,
|
||||
other.isLocked, other.taskDescription, other.topActivity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use {@link Task#Task(Task)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public Task(TaskKey key, int colorPrimary, int colorBackground,
|
||||
boolean isDockable, boolean isLocked, TaskDescription taskDescription,
|
||||
ComponentName topActivity) {
|
||||
@@ -301,103 +272,6 @@ public class Task {
|
||||
this.topActivity = topActivity;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Task(TaskKey key, Drawable icon, ThumbnailData thumbnail, String title,
|
||||
String titleDescription, int colorPrimary, int colorBackground, boolean isLaunchTarget,
|
||||
boolean isStackTask, boolean isSystemApp, boolean isDockable,
|
||||
TaskDescription taskDescription, int resizeMode, ComponentName topActivity,
|
||||
boolean isLocked) {
|
||||
this.key = key;
|
||||
this.icon = icon;
|
||||
this.thumbnail = thumbnail;
|
||||
this.title = title;
|
||||
this.titleDescription = titleDescription;
|
||||
this.colorPrimary = colorPrimary;
|
||||
this.colorBackground = colorBackground;
|
||||
this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary,
|
||||
Color.WHITE) > 3f;
|
||||
this.taskDescription = taskDescription;
|
||||
this.isLaunchTarget = isLaunchTarget;
|
||||
this.isStackTask = isStackTask;
|
||||
this.isSystemApp = isSystemApp;
|
||||
this.isDockable = isDockable;
|
||||
this.resizeMode = resizeMode;
|
||||
this.topActivity = topActivity;
|
||||
this.isLocked = isLocked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the metadata from another task, but retains the current callbacks.
|
||||
*/
|
||||
@Deprecated
|
||||
public void copyFrom(Task o) {
|
||||
this.key = o.key;
|
||||
this.icon = o.icon;
|
||||
this.thumbnail = o.thumbnail;
|
||||
this.title = o.title;
|
||||
this.titleDescription = o.titleDescription;
|
||||
this.colorPrimary = o.colorPrimary;
|
||||
this.colorBackground = o.colorBackground;
|
||||
this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
|
||||
this.taskDescription = o.taskDescription;
|
||||
this.isLaunchTarget = o.isLaunchTarget;
|
||||
this.isStackTask = o.isStackTask;
|
||||
this.isSystemApp = o.isSystemApp;
|
||||
this.isDockable = o.isDockable;
|
||||
this.resizeMode = o.resizeMode;
|
||||
this.isLocked = o.isLocked;
|
||||
this.topActivity = o.topActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a callback.
|
||||
*/
|
||||
@Deprecated
|
||||
public void addCallback(TaskCallbacks cb) {
|
||||
if (!mCallbacks.contains(cb)) {
|
||||
mCallbacks.add(cb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a callback.
|
||||
*/
|
||||
@Deprecated
|
||||
public void removeCallback(TaskCallbacks cb) {
|
||||
mCallbacks.remove(cb);
|
||||
}
|
||||
|
||||
/** Updates the task's windowing mode. */
|
||||
@Deprecated
|
||||
public void setWindowingMode(int windowingMode) {
|
||||
key.setWindowingMode(windowingMode);
|
||||
int callbackCount = mCallbacks.size();
|
||||
for (int i = 0; i < callbackCount; i++) {
|
||||
mCallbacks.get(i).onTaskWindowingModeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/** Notifies the callback listeners that this task has been loaded */
|
||||
@Deprecated
|
||||
public void notifyTaskDataLoaded(ThumbnailData thumbnailData, Drawable applicationIcon) {
|
||||
this.icon = applicationIcon;
|
||||
this.thumbnail = thumbnailData;
|
||||
int callbackCount = mCallbacks.size();
|
||||
for (int i = 0; i < callbackCount; i++) {
|
||||
mCallbacks.get(i).onTaskDataLoaded(this, thumbnailData);
|
||||
}
|
||||
}
|
||||
|
||||
/** Notifies the callback listeners that this task has been unloaded */
|
||||
@Deprecated
|
||||
public void notifyTaskDataUnloaded(Drawable defaultApplicationIcon) {
|
||||
icon = defaultApplicationIcon;
|
||||
thumbnail = null;
|
||||
for (int i = mCallbacks.size() - 1; i >= 0; i--) {
|
||||
mCallbacks.get(i).onTaskDataUnloaded();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top activity component.
|
||||
*/
|
||||
@@ -424,9 +298,6 @@ public class Task {
|
||||
if (!isDockable) {
|
||||
writer.print(" dockable=N");
|
||||
}
|
||||
if (isLaunchTarget) {
|
||||
writer.print(" launchTarget=Y");
|
||||
}
|
||||
if (isLocked) {
|
||||
writer.print(" locked=Y");
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Environment;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -1886,6 +1888,7 @@ class RecentTasks {
|
||||
// Fill in some deprecated values.
|
||||
rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID;
|
||||
rti.persistentId = rti.taskId;
|
||||
rti.lastSnapshotData.set(tr.mLastTaskSnapshotData);
|
||||
|
||||
// Fill in organized child task info for the task created by organizer.
|
||||
if (tr.mCreatedByOrganizer) {
|
||||
|
||||
@@ -158,6 +158,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData;
|
||||
import android.app.ActivityManager.TaskDescription;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.ActivityTaskManager;
|
||||
@@ -293,6 +294,9 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
private static final String ATTR_MIN_HEIGHT = "min_height";
|
||||
private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
|
||||
private static final String ATTR_WINDOW_LAYOUT_AFFINITY = "window_layout_affinity";
|
||||
private static final String ATTR_LAST_SNAPSHOT_TASK_SIZE = "last_snapshot_task_size";
|
||||
private static final String ATTR_LAST_SNAPSHOT_CONTENT_INSETS = "last_snapshot_content_insets";
|
||||
private static final String ATTR_LAST_SNAPSHOT_BUFFER_SIZE = "last_snapshot_buffer_size";
|
||||
|
||||
// Set to false to disable the preview that is shown while a new activity
|
||||
// is being started.
|
||||
@@ -540,6 +544,10 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
// NOTE: This value needs to be persisted with each task
|
||||
private TaskDescription mTaskDescription;
|
||||
|
||||
// Information about the last snapshot that should be persisted with the task to allow SystemUI
|
||||
// to layout without loading all the task snapshots
|
||||
final PersistedTaskSnapshotData mLastTaskSnapshotData;
|
||||
|
||||
// If set to true, the task will report that it is not in the floating
|
||||
// state regardless of it's root task affiliation. As the floating state drives
|
||||
// production of content insets this can be used to preserve them across
|
||||
@@ -613,8 +621,6 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
SurfaceControl.Transaction mMainWindowSizeChangeTransaction;
|
||||
Task mMainWindowSizeChangeTask;
|
||||
|
||||
Rect mPreAnimationBounds = new Rect();
|
||||
|
||||
private final AnimatingActivityRegistry mAnimatingActivityRegistry =
|
||||
new AnimatingActivityRegistry();
|
||||
|
||||
@@ -839,13 +845,13 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
|
||||
boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId, int _effectiveUid,
|
||||
String _lastDescription, long lastTimeMoved, boolean neverRelinquishIdentity,
|
||||
TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
|
||||
int nextTaskId, int callingUid, String callingPackage,
|
||||
@Nullable String callingFeatureId, int resizeMode, boolean supportsPictureInPicture,
|
||||
boolean _realActivitySuspended, boolean userSetupComplete, int minWidth, int minHeight,
|
||||
ActivityInfo info, IVoiceInteractionSession _voiceSession,
|
||||
IVoiceInteractor _voiceInteractor, boolean _createdByOrganizer,
|
||||
IBinder _launchCookie, boolean _deferTaskAppear) {
|
||||
TaskDescription _lastTaskDescription, PersistedTaskSnapshotData _lastSnapshotData,
|
||||
int taskAffiliation, int prevTaskId, int nextTaskId, int callingUid,
|
||||
String callingPackage, @Nullable String callingFeatureId, int resizeMode,
|
||||
boolean supportsPictureInPicture, boolean _realActivitySuspended,
|
||||
boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info,
|
||||
IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
|
||||
boolean _createdByOrganizer, IBinder _launchCookie, boolean _deferTaskAppear) {
|
||||
super(atmService.mWindowManager);
|
||||
|
||||
mAtmService = atmService;
|
||||
@@ -855,7 +861,12 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
mUserId = _userId;
|
||||
mResizeMode = resizeMode;
|
||||
mSupportsPictureInPicture = supportsPictureInPicture;
|
||||
mTaskDescription = _lastTaskDescription;
|
||||
mTaskDescription = _lastTaskDescription != null
|
||||
? _lastTaskDescription
|
||||
: new TaskDescription();
|
||||
mLastTaskSnapshotData = _lastSnapshotData != null
|
||||
? _lastSnapshotData
|
||||
: new PersistedTaskSnapshotData();
|
||||
// Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
|
||||
setOrientation(SCREEN_ORIENTATION_UNSET);
|
||||
mRemoteToken = new RemoteToken(this);
|
||||
@@ -3899,6 +3910,7 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
}
|
||||
|
||||
void onSnapshotChanged(TaskSnapshot snapshot) {
|
||||
mLastTaskSnapshotData.set(snapshot);
|
||||
mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
|
||||
mTaskId, snapshot);
|
||||
}
|
||||
@@ -4157,7 +4169,6 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
void fillTaskInfo(TaskInfo info, boolean stripExtras) {
|
||||
getNumRunningActivities(mReuseActivitiesReport);
|
||||
info.userId = isLeafTask() ? mUserId : mCurrentUser;
|
||||
info.stackId = getRootTaskId();
|
||||
info.taskId = mTaskId;
|
||||
info.displayId = getDisplayId();
|
||||
info.isRunning = getTopNonFinishingActivity() != null;
|
||||
@@ -4707,6 +4718,19 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
out.attributeInt(null, ATTR_MIN_HEIGHT, mMinHeight);
|
||||
out.attributeInt(null, ATTR_PERSIST_TASK_VERSION, PERSIST_TASK_VERSION);
|
||||
|
||||
if (mLastTaskSnapshotData.taskSize != null) {
|
||||
out.attribute(null, ATTR_LAST_SNAPSHOT_TASK_SIZE,
|
||||
mLastTaskSnapshotData.taskSize.flattenToString());
|
||||
}
|
||||
if (mLastTaskSnapshotData.contentInsets != null) {
|
||||
out.attribute(null, ATTR_LAST_SNAPSHOT_CONTENT_INSETS,
|
||||
mLastTaskSnapshotData.contentInsets.flattenToString());
|
||||
}
|
||||
if (mLastTaskSnapshotData.bufferSize != null) {
|
||||
out.attribute(null, ATTR_LAST_SNAPSHOT_BUFFER_SIZE,
|
||||
mLastTaskSnapshotData.bufferSize.flattenToString());
|
||||
}
|
||||
|
||||
if (affinityIntent != null) {
|
||||
out.startTag(null, TAG_AFFINITYINTENT);
|
||||
affinityIntent.saveToXml(out);
|
||||
@@ -4774,6 +4798,7 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
int taskId = INVALID_TASK_ID;
|
||||
final int outerDepth = in.getDepth();
|
||||
TaskDescription taskDescription = new TaskDescription();
|
||||
PersistedTaskSnapshotData lastSnapshotData = new PersistedTaskSnapshotData();
|
||||
int taskAffiliation = INVALID_TASK_ID;
|
||||
int prevTaskId = INVALID_TASK_ID;
|
||||
int nextTaskId = INVALID_TASK_ID;
|
||||
@@ -4883,6 +4908,15 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
case ATTR_PERSIST_TASK_VERSION:
|
||||
persistTaskVersion = Integer.parseInt(attrValue);
|
||||
break;
|
||||
case ATTR_LAST_SNAPSHOT_TASK_SIZE:
|
||||
lastSnapshotData.taskSize = Point.unflattenFromString(attrValue);
|
||||
break;
|
||||
case ATTR_LAST_SNAPSHOT_CONTENT_INSETS:
|
||||
lastSnapshotData.contentInsets = Rect.unflattenFromString(attrValue);
|
||||
break;
|
||||
case ATTR_LAST_SNAPSHOT_BUFFER_SIZE:
|
||||
lastSnapshotData.bufferSize = Point.unflattenFromString(attrValue);
|
||||
break;
|
||||
default:
|
||||
if (!attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
|
||||
Slog.w(TAG, "Task: Unknown attribute=" + attrName);
|
||||
@@ -4977,6 +5011,7 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
.setLastTimeMoved(lastTimeOnTop)
|
||||
.setNeverRelinquishIdentity(neverRelinquishIdentity)
|
||||
.setLastTaskDescription(taskDescription)
|
||||
.setLastSnapshotData(lastSnapshotData)
|
||||
.setTaskAffiliation(taskAffiliation)
|
||||
.setPrevAffiliateTaskId(prevTaskId)
|
||||
.setNextAffiliateTaskId(nextTaskId)
|
||||
@@ -7904,6 +7939,7 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
private long mLastTimeMoved;
|
||||
private boolean mNeverRelinquishIdentity;
|
||||
private TaskDescription mLastTaskDescription;
|
||||
private PersistedTaskSnapshotData mLastSnapshotData;
|
||||
private int mTaskAffiliation;
|
||||
private int mPrevAffiliateTaskId = INVALID_TASK_ID;
|
||||
private int mNextAffiliateTaskId = INVALID_TASK_ID;
|
||||
@@ -8104,6 +8140,11 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
return this;
|
||||
}
|
||||
|
||||
private Builder setLastSnapshotData(PersistedTaskSnapshotData lastSnapshotData) {
|
||||
mLastSnapshotData = lastSnapshotData;
|
||||
return this;
|
||||
}
|
||||
|
||||
private Builder setOrigActivity(ComponentName origActivity) {
|
||||
mOrigActivity = origActivity;
|
||||
return this;
|
||||
@@ -8217,9 +8258,6 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
mCallingPackage = mActivityInfo.packageName;
|
||||
mResizeMode = mActivityInfo.resizeMode;
|
||||
mSupportsPictureInPicture = mActivityInfo.supportsPictureInPicture();
|
||||
if (mLastTaskDescription == null) {
|
||||
mLastTaskDescription = new TaskDescription();
|
||||
}
|
||||
|
||||
final Task task = buildInner();
|
||||
task.mHasBeenVisible = mHasBeenVisible;
|
||||
@@ -8253,9 +8291,9 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
return new Task(mAtmService, mTaskId, mIntent, mAffinityIntent, mAffinity,
|
||||
mRootAffinity, mRealActivity, mOrigActivity, mRootWasReset, mAutoRemoveRecents,
|
||||
mAskedCompatMode, mUserId, mEffectiveUid, mLastDescription, mLastTimeMoved,
|
||||
mNeverRelinquishIdentity, mLastTaskDescription, mTaskAffiliation,
|
||||
mPrevAffiliateTaskId, mNextAffiliateTaskId, mCallingUid, mCallingPackage,
|
||||
mCallingFeatureId, mResizeMode, mSupportsPictureInPicture,
|
||||
mNeverRelinquishIdentity, mLastTaskDescription, mLastSnapshotData,
|
||||
mTaskAffiliation, mPrevAffiliateTaskId, mNextAffiliateTaskId, mCallingUid,
|
||||
mCallingPackage, mCallingFeatureId, mResizeMode, mSupportsPictureInPicture,
|
||||
mRealActivitySuspended, mUserSetupComplete, mMinWidth, mMinHeight,
|
||||
mActivityInfo, mVoiceSession, mVoiceInteractor, mCreatedByOrganizer,
|
||||
mLaunchCookie, mDeferTaskAppear);
|
||||
|
||||
@@ -29,6 +29,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
|
||||
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
|
||||
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
@@ -59,6 +60,10 @@ import android.app.ActivityTaskManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.ColorSpace;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
@@ -66,6 +71,8 @@ import android.os.UserManager;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.util.ArraySet;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.Surface;
|
||||
import android.window.TaskSnapshot;
|
||||
|
||||
import androidx.test.filters.MediumTest;
|
||||
|
||||
@@ -446,12 +453,8 @@ public class RecentTasksTest extends WindowTestsBase {
|
||||
doReturn(false).when(child2).isOrganized();
|
||||
mRecentTasks.add(root);
|
||||
|
||||
doNothing().when(mRecentTasks).loadUserRecentsLocked(anyInt());
|
||||
doReturn(true).when(mRecentTasks).isUserRunning(anyInt(), anyInt());
|
||||
final List<RecentTaskInfo> infos = mRecentTasks.getRecentTasks(MAX_VALUE, 0 /* flags */,
|
||||
true /* getTasksAllowed */, TEST_USER_0_ID, 0 /* callingUid */).getList();
|
||||
|
||||
// Make sure only organized child will be appended.
|
||||
final List<RecentTaskInfo> infos = getRecentTasks(0 /* flags */);
|
||||
final List<RecentTaskInfo> childrenTaskInfos = infos.get(0).childrenTaskInfos;
|
||||
assertEquals(childrenTaskInfos.size(), 1);
|
||||
assertEquals(childrenTaskInfos.get(0).taskId, child1.mTaskId);
|
||||
@@ -1051,9 +1054,6 @@ public class RecentTasksTest extends WindowTestsBase {
|
||||
|
||||
@Test
|
||||
public void testTaskInfo_expectNoExtras() {
|
||||
doNothing().when(mRecentTasks).loadUserRecentsLocked(anyInt());
|
||||
doReturn(true).when(mRecentTasks).isUserRunning(anyInt(), anyInt());
|
||||
|
||||
final Bundle data = new Bundle();
|
||||
data.putInt("key", 100);
|
||||
final Task task1 = createTaskBuilder(".Task").build();
|
||||
@@ -1063,8 +1063,7 @@ public class RecentTasksTest extends WindowTestsBase {
|
||||
.build();
|
||||
mRecentTasks.add(r1.getTask());
|
||||
|
||||
final List<RecentTaskInfo> infos = mRecentTasks.getRecentTasks(MAX_VALUE, 0 /* flags */,
|
||||
true /* getTasksAllowed */, TEST_USER_0_ID, 0).getList();
|
||||
final List<RecentTaskInfo> infos = getRecentTasks(0 /* flags */);
|
||||
assertTrue(infos.size() == 1);
|
||||
for (int i = 0; i < infos.size(); i++) {
|
||||
final Bundle extras = infos.get(i).baseIntent.getExtras();
|
||||
@@ -1072,6 +1071,60 @@ public class RecentTasksTest extends WindowTestsBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLastSnapshotData_snapshotSaved() {
|
||||
final TaskSnapshot snapshot = createSnapshot(new Point(100, 100), new Point(80, 80));
|
||||
final Task task1 = createTaskBuilder(".Task").build();
|
||||
task1.onSnapshotChanged(snapshot);
|
||||
|
||||
mRecentTasks.add(task1);
|
||||
final List<RecentTaskInfo> infos = getRecentTasks(0 /* flags */);
|
||||
final RecentTaskInfo.PersistedTaskSnapshotData lastSnapshotData =
|
||||
infos.get(0).lastSnapshotData;
|
||||
assertTrue(lastSnapshotData.taskSize.equals(100, 100));
|
||||
assertTrue(lastSnapshotData.bufferSize.equals(80, 80));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLastSnapshotData_noBuffer() {
|
||||
final Task task1 = createTaskBuilder(".Task").build();
|
||||
final TaskSnapshot snapshot = createSnapshot(new Point(100, 100), null);
|
||||
task1.onSnapshotChanged(snapshot);
|
||||
|
||||
mRecentTasks.add(task1);
|
||||
final List<RecentTaskInfo> infos = getRecentTasks(0 /* flags */);
|
||||
final RecentTaskInfo.PersistedTaskSnapshotData lastSnapshotData =
|
||||
infos.get(0).lastSnapshotData;
|
||||
assertTrue(lastSnapshotData.taskSize.equals(100, 100));
|
||||
assertNull(lastSnapshotData.bufferSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLastSnapshotData_notSet() {
|
||||
final Task task1 = createTaskBuilder(".Task").build();
|
||||
|
||||
mRecentTasks.add(task1);
|
||||
final List<RecentTaskInfo> infos = getRecentTasks(0 /* flags */);
|
||||
final RecentTaskInfo.PersistedTaskSnapshotData lastSnapshotData =
|
||||
infos.get(0).lastSnapshotData;
|
||||
assertNull(lastSnapshotData.taskSize);
|
||||
assertNull(lastSnapshotData.bufferSize);
|
||||
}
|
||||
|
||||
private TaskSnapshot createSnapshot(Point taskSize, Point bufferSize) {
|
||||
HardwareBuffer buffer = null;
|
||||
if (bufferSize != null) {
|
||||
buffer = mock(HardwareBuffer.class);
|
||||
doReturn(bufferSize.x).when(buffer).getWidth();
|
||||
doReturn(bufferSize.y).when(buffer).getHeight();
|
||||
}
|
||||
return new TaskSnapshot(1, new ComponentName("", ""), buffer,
|
||||
ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
|
||||
Surface.ROTATION_0, taskSize, new Rect() /* insets */, false /* isLowResolution */,
|
||||
true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, 0 /* mSystemUiVisibility */,
|
||||
false /* isTranslucent */, false /* hasImeSurface */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the raw recent tasks list is in the provided order. Note that the expected tasks
|
||||
* should be ordered from least to most recent.
|
||||
@@ -1084,15 +1137,19 @@ public class RecentTasksTest extends WindowTestsBase {
|
||||
}
|
||||
}
|
||||
|
||||
private List<RecentTaskInfo> getRecentTasks(int flags) {
|
||||
doNothing().when(mRecentTasks).loadUserRecentsLocked(anyInt());
|
||||
doReturn(true).when(mRecentTasks).isUserRunning(anyInt(), anyInt());
|
||||
return mRecentTasks.getRecentTasks(MAX_VALUE, flags, true /* getTasksAllowed */,
|
||||
TEST_USER_0_ID, 0 /* callingUid */).getList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the recent tasks list is in the provided order. Note that the expected tasks
|
||||
* should be ordered from least to most recent.
|
||||
*/
|
||||
private void assertGetRecentTasksOrder(int getRecentTaskFlags, Task... expectedTasks) {
|
||||
doNothing().when(mRecentTasks).loadUserRecentsLocked(anyInt());
|
||||
doReturn(true).when(mRecentTasks).isUserRunning(anyInt(), anyInt());
|
||||
List<RecentTaskInfo> infos = mRecentTasks.getRecentTasks(MAX_VALUE, getRecentTaskFlags,
|
||||
true /* getTasksAllowed */, TEST_USER_0_ID, 0).getList();
|
||||
List<RecentTaskInfo> infos = getRecentTasks(getRecentTaskFlags);
|
||||
assertTrue(expectedTasks.length == infos.size());
|
||||
for (int i = 0; i < infos.size(); i++) {
|
||||
assertTrue(expectedTasks[i].mTaskId == infos.get(i).taskId);
|
||||
|
||||
Reference in New Issue
Block a user