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