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