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