1 /*
2  * Copyright (C) 2014 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.view;
18 
19 import android.app.ActivityTaskManager;
20 import android.graphics.Region;
21 import android.os.IBinder;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.util.Pools;
25 import android.view.accessibility.AccessibilityNodeInfo;
26 
27 import java.util.ArrayList;
28 import java.util.List;
29 
30 /**
31  * This class represents information about a window from the
32  * window manager to another part of the system.
33  *
34  * @hide
35  */
36 public class WindowInfo implements Parcelable {
37     private static final int MAX_POOL_SIZE = 10;
38 
39     private static final Pools.SynchronizedPool<WindowInfo> sPool =
40             new Pools.SynchronizedPool<WindowInfo>(MAX_POOL_SIZE);
41 
42     public int type;
43     public int layer;
44     public IBinder token;
45     public IBinder parentToken;
46     public IBinder activityToken;
47     public boolean focused;
48     public Region regionInScreen = new Region();
49     public List<IBinder> childTokens;
50     public CharSequence title;
51     public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
52     public boolean inPictureInPicture;
53     public boolean hasFlagWatchOutsideTouch;
54     public int displayId = Display.INVALID_DISPLAY;
55     public int taskId = ActivityTaskManager.INVALID_TASK_ID;
56 
WindowInfo()57     private WindowInfo() {
58         /* do nothing - hide constructor */
59     }
60 
obtain()61     public static WindowInfo obtain() {
62         WindowInfo window = sPool.acquire();
63         if (window == null) {
64             window = new WindowInfo();
65         }
66         return window;
67     }
68 
obtain(WindowInfo other)69     public static WindowInfo obtain(WindowInfo other) {
70         WindowInfo window = obtain();
71         window.displayId = other.displayId;
72         window.taskId = other.taskId;
73         window.type = other.type;
74         window.layer = other.layer;
75         window.token = other.token;
76         window.parentToken = other.parentToken;
77         window.activityToken = other.activityToken;
78         window.focused = other.focused;
79         window.regionInScreen.set(other.regionInScreen);
80         window.title = other.title;
81         window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor;
82         window.inPictureInPicture = other.inPictureInPicture;
83         window.hasFlagWatchOutsideTouch = other.hasFlagWatchOutsideTouch;
84 
85         if (other.childTokens != null && !other.childTokens.isEmpty()) {
86             if (window.childTokens == null) {
87                 window.childTokens = new ArrayList<IBinder>(other.childTokens);
88             } else {
89                 window.childTokens.addAll(other.childTokens);
90             }
91         }
92 
93         return window;
94     }
95 
recycle()96     public void recycle() {
97         clear();
98         sPool.release(this);
99     }
100 
101     @Override
describeContents()102     public int describeContents() {
103         return 0;
104     }
105 
106     @Override
writeToParcel(Parcel parcel, int flags)107     public void writeToParcel(Parcel parcel, int flags) {
108         parcel.writeInt(displayId);
109         parcel.writeInt(taskId);
110         parcel.writeInt(type);
111         parcel.writeInt(layer);
112         parcel.writeStrongBinder(token);
113         parcel.writeStrongBinder(parentToken);
114         parcel.writeStrongBinder(activityToken);
115         parcel.writeInt(focused ? 1 : 0);
116         regionInScreen.writeToParcel(parcel, flags);
117         parcel.writeCharSequence(title);
118         parcel.writeLong(accessibilityIdOfAnchor);
119         parcel.writeInt(inPictureInPicture ? 1 : 0);
120         parcel.writeInt(hasFlagWatchOutsideTouch ? 1 : 0);
121 
122         if (childTokens != null && !childTokens.isEmpty()) {
123             parcel.writeInt(1);
124             parcel.writeBinderList(childTokens);
125         } else {
126             parcel.writeInt(0);
127         }
128     }
129 
130     @Override
toString()131     public String toString() {
132         StringBuilder builder = new StringBuilder();
133         builder.append("WindowInfo[");
134         builder.append("title=").append(title);
135         builder.append(", displayId=").append(displayId);
136         builder.append(", taskId=").append(taskId);
137         builder.append(", type=").append(type);
138         builder.append(", layer=").append(layer);
139         builder.append(", token=").append(token);
140         builder.append(", region=").append(regionInScreen);
141         builder.append(", bounds=").append(regionInScreen.getBounds());
142         builder.append(", parent=").append(parentToken);
143         builder.append(", focused=").append(focused);
144         builder.append(", children=").append(childTokens);
145         builder.append(", accessibility anchor=").append(accessibilityIdOfAnchor);
146         builder.append(", pictureInPicture=").append(inPictureInPicture);
147         builder.append(", watchOutsideTouch=").append(hasFlagWatchOutsideTouch);
148         builder.append(']');
149         return builder.toString();
150     }
151 
initFromParcel(Parcel parcel)152     private void initFromParcel(Parcel parcel) {
153         displayId = parcel.readInt();
154         taskId = parcel.readInt();
155         type = parcel.readInt();
156         layer = parcel.readInt();
157         token = parcel.readStrongBinder();
158         parentToken = parcel.readStrongBinder();
159         activityToken = parcel.readStrongBinder();
160         focused = (parcel.readInt() == 1);
161         regionInScreen = Region.CREATOR.createFromParcel(parcel);
162         title = parcel.readCharSequence();
163         accessibilityIdOfAnchor = parcel.readLong();
164         inPictureInPicture = (parcel.readInt() == 1);
165         hasFlagWatchOutsideTouch = (parcel.readInt() == 1);
166 
167         final boolean hasChildren = (parcel.readInt() == 1);
168         if (hasChildren) {
169             if (childTokens == null) {
170                 childTokens = new ArrayList<IBinder>();
171             }
172             parcel.readBinderList(childTokens);
173         }
174     }
175 
clear()176     private void clear() {
177         displayId = Display.INVALID_DISPLAY;
178         taskId = ActivityTaskManager.INVALID_TASK_ID;
179         type = 0;
180         layer = 0;
181         token = null;
182         parentToken = null;
183         activityToken = null;
184         focused = false;
185         regionInScreen.setEmpty();
186         if (childTokens != null) {
187             childTokens.clear();
188         }
189         inPictureInPicture = false;
190         hasFlagWatchOutsideTouch = false;
191     }
192 
193     public static final @android.annotation.NonNull Parcelable.Creator<WindowInfo> CREATOR =
194             new Creator<WindowInfo>() {
195         @Override
196         public WindowInfo createFromParcel(Parcel parcel) {
197             WindowInfo window = obtain();
198             window.initFromParcel(parcel);
199             return window;
200         }
201 
202         @Override
203         public WindowInfo[] newArray(int size) {
204             return new WindowInfo[size];
205         }
206     };
207 }
208