1 /*
2  * Copyright (C) 2011 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.annotation.IntDef;
20 import android.annotation.Nullable;
21 import android.graphics.Matrix;
22 import android.graphics.Region;
23 import android.gui.TouchOcclusionMode;
24 import android.os.IBinder;
25 import android.os.InputConfig;
26 
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.lang.ref.WeakReference;
30 
31 /**
32  * Functions as a handle for a window that can receive input, and allows for the behavior of the
33  * input window to be configured.
34  * @hide
35  */
36 public final class InputWindowHandle {
37 
38     /**
39      * An internal annotation for all the {@link android.os.InputConfig} flags that can be
40      * specified to {@link #inputConfig} to control the behavior of an input window. Only the
41      * flags listed here are valid for use in Java.
42      *
43      * The default flag value is 0, which is what we expect for a normal application window. Adding
44      * a flag indicates that the window's behavior deviates from that of a normal application
45      * window.
46      *
47      * The flags are defined as an AIDL enum to keep it in sync with native code.
48      * {@link android.os.InputConfig} flags that are not listed here should not be used in Java, and
49      * are only meant to be used in native code.
50      */
51     @Retention(RetentionPolicy.SOURCE)
52     @IntDef(flag = true, value = {
53             InputConfig.DEFAULT,
54             InputConfig.NO_INPUT_CHANNEL,
55             InputConfig.NOT_FOCUSABLE,
56             InputConfig.NOT_TOUCHABLE,
57             InputConfig.PREVENT_SPLITTING,
58             InputConfig.DUPLICATE_TOUCH_TO_WALLPAPER,
59             InputConfig.IS_WALLPAPER,
60             InputConfig.PAUSE_DISPATCHING,
61             InputConfig.TRUSTED_OVERLAY,
62             InputConfig.WATCH_OUTSIDE_TOUCH,
63             InputConfig.SLIPPERY,
64             InputConfig.DISABLE_USER_ACTIVITY,
65             InputConfig.SPY,
66             InputConfig.INTERCEPTS_STYLUS,
67             InputConfig.CLONE,
68     })
69     public @interface InputConfigFlags {}
70 
71     // Pointer to the native input window handle.
72     // This field is lazily initialized via JNI.
73     @SuppressWarnings("unused")
74     private long ptr;
75 
76     // The input application handle.
77     public InputApplicationHandle inputApplicationHandle;
78 
79     // The token associates input data with a window and its input channel. The client input
80     // channel and the server input channel will both contain this token.
81     public IBinder token;
82 
83     /**
84      * The {@link IWindow} handle if InputWindowHandle is associated with a window, null otherwise.
85      */
86     @Nullable
87     private IBinder windowToken;
88     /**
89      * Used to cache IWindow from the windowToken so we don't need to convert every time getWindow
90      * is called.
91      */
92     private IWindow window;
93 
94     // The window name.
95     public String name;
96 
97     // Window layout params attributes. (WindowManager.LayoutParams)
98     // These values do not affect any input configurations. Use {@link #inputConfig} instead.
99     public int layoutParamsFlags;
100     public int layoutParamsType;
101 
102     // Dispatching timeout.
103     public long dispatchingTimeoutMillis;
104 
105     // Window frame.
106     public int frameLeft;
107     public int frameTop;
108     public int frameRight;
109     public int frameBottom;
110 
111     public int surfaceInset;
112 
113     // Global scaling factor applied to touch events when they are dispatched
114     // to the window
115     public float scaleFactor;
116 
117     // Window touchable region.
118     public final Region touchableRegion = new Region();
119 
120     // Flags that specify the behavior of this input window. See {@link #InputConfigFlags}.
121     @InputConfigFlags
122     public int inputConfig;
123 
124     // What effect this window has on touch occlusion if it lets touches pass through
125     // By default windows will block touches if they are untrusted and from a different UID due to
126     // security concerns
127     public int touchOcclusionMode = TouchOcclusionMode.BLOCK_UNTRUSTED;
128 
129     // Id of process and user that owns the window.
130     public int ownerPid;
131     public int ownerUid;
132 
133     // Owner package of the window
134     public String packageName;
135 
136     // Display this input window is on.
137     public int displayId;
138 
139     /**
140      * Crops the {@link #touchableRegion} to the bounds of the surface provided.
141      *
142      * This can be used in cases where the window should be constrained to the bounds of a parent
143      * window. That is, the window should receive touch events outside its window frame, but be
144      * limited to its stack bounds, such as in the case of split screen.
145      */
146     public WeakReference<SurfaceControl> touchableRegionSurfaceControl = new WeakReference<>(null);
147 
148     /**
149      * Replace {@link #touchableRegion} with the bounds of {@link #touchableRegionSurfaceControl}.
150      * If the handle is {@code null}, the bounds of the surface associated with this window is used
151      * as the touchable region.
152      */
153     public boolean replaceTouchableRegionWithCrop;
154 
155     /**
156      * The transform that should be applied to the Window to get it from screen coordinates to
157      * window coordinates
158      */
159     public Matrix transform;
160 
161     /**
162      * The input token for the window to which focus should be transferred when this input window
163      * can be successfully focused. If null, this input window will not transfer its focus to
164      * any other window.
165      */
166     @Nullable
167     public IBinder focusTransferTarget;
168 
nativeDispose()169     private native void nativeDispose();
170 
InputWindowHandle(InputApplicationHandle inputApplicationHandle, int displayId)171     public InputWindowHandle(InputApplicationHandle inputApplicationHandle, int displayId) {
172         this.inputApplicationHandle = inputApplicationHandle;
173         this.displayId = displayId;
174     }
175 
InputWindowHandle(InputWindowHandle other)176     public InputWindowHandle(InputWindowHandle other) {
177         // Do not copy ptr to prevent this copy from sharing the same native object.
178         ptr = 0;
179         inputApplicationHandle = new InputApplicationHandle(other.inputApplicationHandle);
180         token = other.token;
181         windowToken = other.windowToken;
182         window = other.window;
183         name = other.name;
184         layoutParamsFlags = other.layoutParamsFlags;
185         layoutParamsType = other.layoutParamsType;
186         dispatchingTimeoutMillis = other.dispatchingTimeoutMillis;
187         frameLeft = other.frameLeft;
188         frameTop = other.frameTop;
189         frameRight = other.frameRight;
190         frameBottom = other.frameBottom;
191         surfaceInset = other.surfaceInset;
192         scaleFactor = other.scaleFactor;
193         touchableRegion.set(other.touchableRegion);
194         inputConfig = other.inputConfig;
195         touchOcclusionMode = other.touchOcclusionMode;
196         ownerPid = other.ownerPid;
197         ownerUid = other.ownerUid;
198         packageName = other.packageName;
199         displayId = other.displayId;
200         touchableRegionSurfaceControl = other.touchableRegionSurfaceControl;
201         replaceTouchableRegionWithCrop = other.replaceTouchableRegionWithCrop;
202         if (other.transform != null) {
203             transform = new Matrix();
204             transform.set(other.transform);
205         }
206         focusTransferTarget = other.focusTransferTarget;
207     }
208 
209     @Override
toString()210     public String toString() {
211         return new StringBuilder(name != null ? name : "")
212                 .append(", frame=[").append(frameLeft).append(",").append(frameTop).append(",")
213                         .append(frameRight).append(",").append(frameBottom).append("]")
214                 .append(", touchableRegion=").append(touchableRegion)
215                 .append(", scaleFactor=").append(scaleFactor)
216                 .append(", transform=").append(transform)
217                 .append(", windowToken=").append(windowToken)
218                 .append(", displayId=").append(displayId)
219                 .append(", isClone=").append((inputConfig & InputConfig.CLONE) != 0)
220                 .toString();
221 
222     }
223 
224     @Override
finalize()225     protected void finalize() throws Throwable {
226         try {
227             nativeDispose();
228         } finally {
229             super.finalize();
230         }
231     }
232 
233     /**
234      * Set the window's touchable region to the bounds of {@link #touchableRegionSurfaceControl}
235      * and ignore the value of {@link #touchableRegion}.
236      *
237      * @param bounds surface to set the touchable region to. Set to {@code null} to set the
238      *               touchable region as the current surface bounds.
239      */
replaceTouchableRegionWithCrop(@ullable SurfaceControl bounds)240     public void replaceTouchableRegionWithCrop(@Nullable SurfaceControl bounds) {
241         setTouchableRegionCrop(bounds);
242         replaceTouchableRegionWithCrop = true;
243     }
244 
245     /**
246      * Crop the window touchable region to the bounds of the surface provided.
247      */
setTouchableRegionCrop(@ullable SurfaceControl bounds)248     public void setTouchableRegionCrop(@Nullable SurfaceControl bounds) {
249         touchableRegionSurfaceControl = new WeakReference<>(bounds);
250     }
251 
setWindowToken(IWindow iwindow)252     public void setWindowToken(IWindow iwindow) {
253         windowToken = iwindow.asBinder();
254         window = iwindow;
255     }
256 
getWindowToken()257     public @Nullable IBinder getWindowToken() {
258         return windowToken;
259     }
260 
getWindow()261     public IWindow getWindow() {
262         if (window != null) {
263             return window;
264         }
265         window = IWindow.Stub.asInterface(windowToken);
266         return window;
267     }
268 
269     /**
270      * Set the provided inputConfig flag values.
271      * @param inputConfig the flag values to change
272      * @param value the provided flag values are set when true, and cleared when false
273      */
setInputConfig(@nputConfigFlags int inputConfig, boolean value)274     public void setInputConfig(@InputConfigFlags int inputConfig, boolean value) {
275         if (value) {
276             this.inputConfig |= inputConfig;
277             return;
278         }
279         this.inputConfig &= ~inputConfig;
280     }
281 }
282