blob: 85758a92fa9860dde9c038b02ed0887c37d00fcd [file] [log] [blame]
/*
* Copyright (C) 2018 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 android.app;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.LocusId;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import android.view.DisplayCutout;
import android.window.TaskSnapshot;
import android.window.WindowContainerToken;
import java.util.ArrayList;
import java.util.Objects;
/**
* Stores information about a particular Task.
*/
public class TaskInfo {
private static final String TAG = "TaskInfo";
/**
* The id of the user the task was running as if this is a leaf task. The id of the current
* running user of the system otherwise.
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int userId;
/**
* The identifier for this task.
*/
public int taskId;
/**
* Whether or not this task has any running activities.
*/
public boolean isRunning;
/**
* The base intent of the task (generally the intent that launched the task). This intent can
* be used to relaunch the task (if it is no longer running) or brought to the front if it is.
*/
@NonNull
public Intent baseIntent;
/**
* The component of the first activity in the task, can be considered the "application" of this
* task.
*/
@Nullable
public ComponentName baseActivity;
/**
* The component of the top activity in the task, currently showing to the user.
*/
@Nullable
public ComponentName topActivity;
/**
* The component of the target activity if this task was started from an activity alias.
* Otherwise, this is null.
*/
@Nullable
public ComponentName origActivity;
/**
* The component of the activity that started this task (may be the component of the activity
* alias).
* @hide
*/
@Nullable
public ComponentName realActivity;
/**
* The number of activities in this task (including running).
*/
public int numActivities;
/**
* The last time this task was active since boot (including time spent in sleep).
* @hide
*/
@UnsupportedAppUsage
public long lastActiveTime;
/**
* The id of the display this task is associated with.
* @hide
*/
public int displayId;
/**
* The recent activity values for the highest activity in the stack to have set the values.
* {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.
*/
@Nullable
public ActivityManager.TaskDescription taskDescription;
/**
* The locusId of the task.
* @hide
*/
@Nullable
public LocusId mTopActivityLocusId;
/**
* True if the task can go in the split-screen primary stack.
* @hide
*/
@UnsupportedAppUsage
public boolean supportsSplitScreenMultiWindow;
/**
* Whether this task supports multi windowing modes based on the device settings and the
* root activity resizability and configuration.
* @hide
*/
public boolean supportsMultiWindow;
/**
* The resize mode of the task. See {@link ActivityInfo#resizeMode}.
* @hide
*/
@UnsupportedAppUsage
public int resizeMode;
/**
* The current configuration of the task.
* @hide
*/
@NonNull
@UnsupportedAppUsage
public final Configuration configuration = new Configuration();
/**
* Used as an opaque identifier for this task.
* @hide
*/
@NonNull
public WindowContainerToken token;
/**
* The PictureInPictureParams for the Task, if set.
* @hide
*/
@Nullable
public PictureInPictureParams pictureInPictureParams;
/**
* The {@link Rect} copied from {@link DisplayCutout#getSafeInsets()} if the cutout is not of
* (LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS),
* {@code null} otherwise.
* @hide
*/
@Nullable
public Rect displayCutoutInsets;
/**
* The activity type of the top activity in this task.
* @hide
*/
public @WindowConfiguration.ActivityType int topActivityType;
/**
* The {@link ActivityInfo} of the top activity in this task.
* @hide
*/
@Nullable
public ActivityInfo topActivityInfo;
/**
* Whether the direct top activity is in size compat mode on foreground.
* @hide
*/
public boolean topActivityInSizeCompat;
/**
* Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity
* supports), this is what the system actually uses for resizability based on other policy and
* developer options.
* @hide
*/
public boolean isResizeable;
/**
* Relative position of the task's top left corner in the parent container.
* @hide
*/
public Point positionInParent;
/**
* The launch cookies associated with activities in this task if any.
* @see ActivityOptions#setLaunchCookie(IBinder)
* @hide
*/
public ArrayList<IBinder> launchCookies = new ArrayList<>();
/**
* The identifier of the parent task that is created by organizer, otherwise
* {@link ActivityTaskManager#INVALID_TASK_ID}.
* @hide
*/
public int parentTaskId;
/**
* Whether this task is focused.
* @hide
*/
public boolean isFocused;
/**
* Whether this task is visible.
* @hide
*/
public boolean isVisible;
TaskInfo() {
// Do nothing
}
private TaskInfo(Parcel source) {
readFromParcel(source);
}
/**
* @param isLowResolution
* @return
* @hide
*/
public TaskSnapshot getTaskSnapshot(boolean isLowResolution) {
try {
return ActivityTaskManager.getService().getTaskSnapshot(taskId, isLowResolution);
} catch (RemoteException e) {
Log.e(TAG, "Failed to get task snapshot, taskId=" + taskId, e);
return null;
}
}
/** @hide */
@NonNull
@TestApi
public WindowContainerToken getToken() {
return token;
}
/** @hide */
@NonNull
@TestApi
public Configuration getConfiguration() {
return configuration;
}
/** @hide */
@Nullable
@TestApi
public PictureInPictureParams getPictureInPictureParams() {
return pictureInPictureParams;
}
/** @hide */
@WindowConfiguration.WindowingMode
public int getWindowingMode() {
return configuration.windowConfiguration.getWindowingMode();
}
/** @hide */
@WindowConfiguration.ActivityType
public int getActivityType() {
return configuration.windowConfiguration.getActivityType();
}
/** @hide */
public void addLaunchCookie(IBinder cookie) {
if (cookie == null || launchCookies.contains(cookie)) return;
launchCookies.add(cookie);
}
/**
* @return {@code true} if this task contains the launch cookie.
* @hide
*/
@TestApi
public boolean containsLaunchCookie(@NonNull IBinder cookie) {
return launchCookies.contains(cookie);
}
/**
* @return The parent task id of this task.
* @hide
*/
@TestApi
public int getParentTaskId() {
return parentTaskId;
}
/** @hide */
@TestApi
public boolean hasParentTask() {
return parentTaskId != INVALID_TASK_ID;
}
/**
* Returns {@code true} if parameters that are important for task organizers have changed
* and {@link com.android.server.wm.TaskOrginizerController} needs to notify listeners
* about that.
* @hide
*/
public boolean equalsForTaskOrganizer(@Nullable TaskInfo that) {
if (that == null) {
return false;
}
return topActivityType == that.topActivityType
&& isResizeable == that.isResizeable
&& supportsMultiWindow == that.supportsMultiWindow
&& Objects.equals(positionInParent, that.positionInParent)
&& Objects.equals(pictureInPictureParams, that.pictureInPictureParams)
&& Objects.equals(displayCutoutInsets, that.displayCutoutInsets)
&& getWindowingMode() == that.getWindowingMode()
&& Objects.equals(taskDescription, that.taskDescription)
&& isFocused == that.isFocused
&& isVisible == that.isVisible;
}
/**
* @return {@code true} if parameters that are important for size compat have changed.
* @hide
*/
public boolean equalsForSizeCompat(@Nullable TaskInfo that) {
if (that == null) {
return false;
}
return displayId == that.displayId
&& taskId == that.taskId
&& topActivityInSizeCompat == that.topActivityInSizeCompat
// Bounds are important if top activity is in size compat
&& (!topActivityInSizeCompat || configuration.windowConfiguration.getBounds()
.equals(that.configuration.windowConfiguration.getBounds()))
&& (!topActivityInSizeCompat || configuration.getLayoutDirection()
== that.configuration.getLayoutDirection())
&& (!topActivityInSizeCompat || isVisible == that.isVisible);
}
/**
* Reads the TaskInfo from a parcel.
*/
void readFromParcel(Parcel source) {
userId = source.readInt();
taskId = source.readInt();
displayId = source.readInt();
isRunning = source.readBoolean();
baseIntent = source.readTypedObject(Intent.CREATOR);
baseActivity = ComponentName.readFromParcel(source);
topActivity = ComponentName.readFromParcel(source);
origActivity = ComponentName.readFromParcel(source);
realActivity = ComponentName.readFromParcel(source);
numActivities = source.readInt();
lastActiveTime = source.readLong();
taskDescription = source.readTypedObject(ActivityManager.TaskDescription.CREATOR);
supportsSplitScreenMultiWindow = source.readBoolean();
supportsMultiWindow = source.readBoolean();
resizeMode = source.readInt();
configuration.readFromParcel(source);
token = WindowContainerToken.CREATOR.createFromParcel(source);
topActivityType = source.readInt();
pictureInPictureParams = source.readTypedObject(PictureInPictureParams.CREATOR);
displayCutoutInsets = source.readTypedObject(Rect.CREATOR);
topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
isResizeable = source.readBoolean();
source.readBinderList(launchCookies);
positionInParent = source.readTypedObject(Point.CREATOR);
parentTaskId = source.readInt();
isFocused = source.readBoolean();
isVisible = source.readBoolean();
topActivityInSizeCompat = source.readBoolean();
mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR);
}
/**
* Writes the TaskInfo to a parcel.
*/
void writeToParcel(Parcel dest, int flags) {
dest.writeInt(userId);
dest.writeInt(taskId);
dest.writeInt(displayId);
dest.writeBoolean(isRunning);
dest.writeTypedObject(baseIntent, 0);
ComponentName.writeToParcel(baseActivity, dest);
ComponentName.writeToParcel(topActivity, dest);
ComponentName.writeToParcel(origActivity, dest);
ComponentName.writeToParcel(realActivity, dest);
dest.writeInt(numActivities);
dest.writeLong(lastActiveTime);
dest.writeTypedObject(taskDescription, flags);
dest.writeBoolean(supportsSplitScreenMultiWindow);
dest.writeBoolean(supportsMultiWindow);
dest.writeInt(resizeMode);
configuration.writeToParcel(dest, flags);
token.writeToParcel(dest, flags);
dest.writeInt(topActivityType);
dest.writeTypedObject(pictureInPictureParams, flags);
dest.writeTypedObject(displayCutoutInsets, flags);
dest.writeTypedObject(topActivityInfo, flags);
dest.writeBoolean(isResizeable);
dest.writeBinderList(launchCookies);
dest.writeTypedObject(positionInParent, flags);
dest.writeInt(parentTaskId);
dest.writeBoolean(isFocused);
dest.writeBoolean(isVisible);
dest.writeBoolean(topActivityInSizeCompat);
dest.writeTypedObject(mTopActivityLocusId, flags);
}
@Override
public String toString() {
return "TaskInfo{userId=" + userId + " taskId=" + taskId
+ " displayId=" + displayId
+ " isRunning=" + isRunning
+ " baseIntent=" + baseIntent + " baseActivity=" + baseActivity
+ " topActivity=" + topActivity + " origActivity=" + origActivity
+ " realActivity=" + realActivity
+ " numActivities=" + numActivities
+ " lastActiveTime=" + lastActiveTime
+ " supportsSplitScreenMultiWindow=" + supportsSplitScreenMultiWindow
+ " supportsMultiWindow=" + supportsMultiWindow
+ " resizeMode=" + resizeMode
+ " isResizeable=" + isResizeable
+ " token=" + token
+ " topActivityType=" + topActivityType
+ " pictureInPictureParams=" + pictureInPictureParams
+ " displayCutoutSafeInsets=" + displayCutoutInsets
+ " topActivityInfo=" + topActivityInfo
+ " launchCookies=" + launchCookies
+ " positionInParent=" + positionInParent
+ " parentTaskId=" + parentTaskId
+ " isFocused=" + isFocused
+ " isVisible=" + isVisible
+ " topActivityInSizeCompat=" + topActivityInSizeCompat
+ " locusId= " + mTopActivityLocusId
+ "}";
}
}