1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.window; 18 19 import static android.app.WindowConfiguration.WindowingMode; 20 21 import static java.util.Objects.requireNonNull; 22 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.TestApi; 26 import android.content.res.Configuration; 27 import android.graphics.Point; 28 import android.graphics.Rect; 29 import android.os.IBinder; 30 import android.os.Parcel; 31 import android.os.Parcelable; 32 33 import java.util.ArrayList; 34 import java.util.List; 35 36 /** 37 * Stores information about a particular TaskFragment. 38 * @hide 39 */ 40 @TestApi 41 public final class TaskFragmentInfo implements Parcelable { 42 43 /** 44 * Client assigned unique token in {@link TaskFragmentCreationParams#getFragmentToken()} to 45 * create this TaskFragment with. 46 */ 47 @NonNull 48 private final IBinder mFragmentToken; 49 50 @NonNull 51 private final WindowContainerToken mToken; 52 53 @NonNull 54 private final Configuration mConfiguration = new Configuration(); 55 56 /** The number of the running activities in the TaskFragment. */ 57 private final int mRunningActivityCount; 58 59 /** Whether this TaskFragment is visible on the window hierarchy. */ 60 private final boolean mIsVisible; 61 62 /** 63 * List of Activity tokens that are children of this TaskFragment. It only contains Activities 64 * that belong to the organizer process for security. 65 */ 66 @NonNull 67 private final List<IBinder> mActivities = new ArrayList<>(); 68 69 /** 70 * List of Activity tokens that were explicitly requested to be launched in this TaskFragment. 71 * It only contains Activities that belong to the organizer process for security. 72 */ 73 @NonNull 74 private final List<IBinder> mInRequestedTaskFragmentActivities = new ArrayList<>(); 75 76 /** Relative position of the fragment's top left corner in the parent container. */ 77 private final Point mPositionInParent = new Point(); 78 79 /** 80 * Whether the last running activity in the TaskFragment was finished due to clearing task while 81 * launching an activity in the host Task. 82 */ 83 private final boolean mIsTaskClearedForReuse; 84 85 /** 86 * Whether the last running activity in the TaskFragment was reparented to a different Task 87 * because it is entering PiP. 88 */ 89 private final boolean mIsTaskFragmentClearedForPip; 90 91 /** 92 * Whether the last running activity of the TaskFragment was removed because it was reordered to 93 * front of the Task. 94 */ 95 private final boolean mIsClearedForReorderActivityToFront; 96 97 /** 98 * The maximum {@link android.content.pm.ActivityInfo.WindowLayout#minWidth} and 99 * {@link android.content.pm.ActivityInfo.WindowLayout#minHeight} aggregated from the 100 * TaskFragment's child activities. 101 */ 102 @NonNull 103 private final Point mMinimumDimensions = new Point(); 104 105 /** @hide */ TaskFragmentInfo( @onNull IBinder fragmentToken, @NonNull WindowContainerToken token, @NonNull Configuration configuration, int runningActivityCount, boolean isVisible, @NonNull List<IBinder> activities, @NonNull List<IBinder> inRequestedTaskFragmentActivities, @NonNull Point positionInParent, boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip, boolean isClearedForReorderActivityToFront, @NonNull Point minimumDimensions)106 public TaskFragmentInfo( 107 @NonNull IBinder fragmentToken, @NonNull WindowContainerToken token, 108 @NonNull Configuration configuration, int runningActivityCount, 109 boolean isVisible, @NonNull List<IBinder> activities, 110 @NonNull List<IBinder> inRequestedTaskFragmentActivities, 111 @NonNull Point positionInParent, boolean isTaskClearedForReuse, 112 boolean isTaskFragmentClearedForPip, boolean isClearedForReorderActivityToFront, 113 @NonNull Point minimumDimensions) { 114 mFragmentToken = requireNonNull(fragmentToken); 115 mToken = requireNonNull(token); 116 mConfiguration.setTo(configuration); 117 mRunningActivityCount = runningActivityCount; 118 mIsVisible = isVisible; 119 mActivities.addAll(activities); 120 mInRequestedTaskFragmentActivities.addAll(inRequestedTaskFragmentActivities); 121 mPositionInParent.set(positionInParent); 122 mIsTaskClearedForReuse = isTaskClearedForReuse; 123 mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip; 124 mIsClearedForReorderActivityToFront = isClearedForReorderActivityToFront; 125 mMinimumDimensions.set(minimumDimensions); 126 } 127 128 @NonNull getFragmentToken()129 public IBinder getFragmentToken() { 130 return mFragmentToken; 131 } 132 133 @NonNull getToken()134 public WindowContainerToken getToken() { 135 return mToken; 136 } 137 138 @NonNull getConfiguration()139 public Configuration getConfiguration() { 140 return mConfiguration; 141 } 142 isEmpty()143 public boolean isEmpty() { 144 return mRunningActivityCount == 0; 145 } 146 hasRunningActivity()147 public boolean hasRunningActivity() { 148 return mRunningActivityCount > 0; 149 } 150 getRunningActivityCount()151 public int getRunningActivityCount() { 152 return mRunningActivityCount; 153 } 154 isVisible()155 public boolean isVisible() { 156 return mIsVisible; 157 } 158 159 @NonNull getActivities()160 public List<IBinder> getActivities() { 161 return mActivities; 162 } 163 164 @NonNull getActivitiesRequestedInTaskFragment()165 public List<IBinder> getActivitiesRequestedInTaskFragment() { 166 return mInRequestedTaskFragmentActivities; 167 } 168 169 /** Returns the relative position of the fragment's top left corner in the parent container. */ 170 @NonNull getPositionInParent()171 public Point getPositionInParent() { 172 return mPositionInParent; 173 } 174 isTaskClearedForReuse()175 public boolean isTaskClearedForReuse() { 176 return mIsTaskClearedForReuse; 177 } 178 179 /** @hide */ isTaskFragmentClearedForPip()180 public boolean isTaskFragmentClearedForPip() { 181 return mIsTaskFragmentClearedForPip; 182 } 183 184 /** @hide */ isClearedForReorderActivityToFront()185 public boolean isClearedForReorderActivityToFront() { 186 return mIsClearedForReorderActivityToFront; 187 } 188 189 @WindowingMode getWindowingMode()190 public int getWindowingMode() { 191 return mConfiguration.windowConfiguration.getWindowingMode(); 192 } 193 194 /** 195 * Returns the minimum width this TaskFragment can be resized to. 196 * Client side must not {@link WindowContainerTransaction#setRelativeBounds} 197 * that {@link Rect#width()} is shorter than the reported value. 198 * @hide pending unhide 199 */ getMinimumWidth()200 public int getMinimumWidth() { 201 return mMinimumDimensions.x; 202 } 203 204 /** 205 * Returns the minimum width this TaskFragment can be resized to. 206 * Client side must not {@link WindowContainerTransaction#setRelativeBounds} 207 * that {@link Rect#height()} is shorter than the reported value. 208 * @hide pending unhide 209 */ getMinimumHeight()210 public int getMinimumHeight() { 211 return mMinimumDimensions.y; 212 } 213 214 /** 215 * Returns {@code true} if the parameters that are important for task fragment organizers are 216 * equal between this {@link TaskFragmentInfo} and {@param that}. 217 * Note that this method is usually called with 218 * {@link com.android.server.wm.WindowOrganizerController#configurationsAreEqualForOrganizer( 219 * Configuration, Configuration)} to determine if this {@link TaskFragmentInfo} should 220 * be dispatched to the client. 221 */ equalsForTaskFragmentOrganizer(@ullable TaskFragmentInfo that)222 public boolean equalsForTaskFragmentOrganizer(@Nullable TaskFragmentInfo that) { 223 if (that == null) { 224 return false; 225 } 226 227 return mFragmentToken.equals(that.mFragmentToken) 228 && mToken.equals(that.mToken) 229 && mRunningActivityCount == that.mRunningActivityCount 230 && mIsVisible == that.mIsVisible 231 && getWindowingMode() == that.getWindowingMode() 232 && mActivities.equals(that.mActivities) 233 && mInRequestedTaskFragmentActivities.equals( 234 that.mInRequestedTaskFragmentActivities) 235 && mPositionInParent.equals(that.mPositionInParent) 236 && mIsTaskClearedForReuse == that.mIsTaskClearedForReuse 237 && mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip 238 && mIsClearedForReorderActivityToFront == that.mIsClearedForReorderActivityToFront 239 && mMinimumDimensions.equals(that.mMinimumDimensions); 240 } 241 TaskFragmentInfo(Parcel in)242 private TaskFragmentInfo(Parcel in) { 243 mFragmentToken = in.readStrongBinder(); 244 mToken = in.readTypedObject(WindowContainerToken.CREATOR); 245 mConfiguration.readFromParcel(in); 246 mRunningActivityCount = in.readInt(); 247 mIsVisible = in.readBoolean(); 248 in.readBinderList(mActivities); 249 in.readBinderList(mInRequestedTaskFragmentActivities); 250 mPositionInParent.readFromParcel(in); 251 mIsTaskClearedForReuse = in.readBoolean(); 252 mIsTaskFragmentClearedForPip = in.readBoolean(); 253 mIsClearedForReorderActivityToFront = in.readBoolean(); 254 mMinimumDimensions.readFromParcel(in); 255 } 256 257 /** @hide */ 258 @Override writeToParcel(@onNull Parcel dest, int flags)259 public void writeToParcel(@NonNull Parcel dest, int flags) { 260 dest.writeStrongBinder(mFragmentToken); 261 dest.writeTypedObject(mToken, flags); 262 mConfiguration.writeToParcel(dest, flags); 263 dest.writeInt(mRunningActivityCount); 264 dest.writeBoolean(mIsVisible); 265 dest.writeBinderList(mActivities); 266 dest.writeBinderList(mInRequestedTaskFragmentActivities); 267 mPositionInParent.writeToParcel(dest, flags); 268 dest.writeBoolean(mIsTaskClearedForReuse); 269 dest.writeBoolean(mIsTaskFragmentClearedForPip); 270 dest.writeBoolean(mIsClearedForReorderActivityToFront); 271 mMinimumDimensions.writeToParcel(dest, flags); 272 } 273 274 @NonNull 275 public static final Creator<TaskFragmentInfo> CREATOR = 276 new Creator<TaskFragmentInfo>() { 277 @Override 278 public TaskFragmentInfo createFromParcel(Parcel in) { 279 return new TaskFragmentInfo(in); 280 } 281 282 @Override 283 public TaskFragmentInfo[] newArray(int size) { 284 return new TaskFragmentInfo[size]; 285 } 286 }; 287 288 @Override toString()289 public String toString() { 290 return "TaskFragmentInfo{" 291 + " fragmentToken=" + mFragmentToken 292 + " token=" + mToken 293 + " runningActivityCount=" + mRunningActivityCount 294 + " isVisible=" + mIsVisible 295 + " activities=" + mActivities 296 + " inRequestedTaskFragmentActivities" + mInRequestedTaskFragmentActivities 297 + " positionInParent=" + mPositionInParent 298 + " isTaskClearedForReuse=" + mIsTaskClearedForReuse 299 + " isTaskFragmentClearedForPip=" + mIsTaskFragmentClearedForPip 300 + " mIsClearedForReorderActivityToFront=" + mIsClearedForReorderActivityToFront 301 + " minimumDimensions=" + mMinimumDimensions 302 + "}"; 303 } 304 305 /** @hide */ 306 @Override describeContents()307 public int describeContents() { 308 return 0; 309 } 310 } 311