1 /*
2  * Copyright (C) 2020 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 com.android.server.wm;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.graphics.Region;
22 import android.os.IBinder;
23 import android.os.InputConfig;
24 import android.view.InputApplicationHandle;
25 import android.view.InputWindowHandle;
26 import android.view.InputWindowHandle.InputConfigFlags;
27 import android.view.SurfaceControl;
28 import android.view.WindowManager;
29 
30 import java.util.Objects;
31 
32 /**
33  * The wrapper of {@link InputWindowHandle} with field change detection to reduce unnecessary
34  * updates to surface, e.g. if there are no changes, then skip invocation of
35  * {@link SurfaceControl.Transaction#setInputWindowInfo(SurfaceControl, InputWindowHandle)}.
36  * It also sets the {@link InputConfigFlags} values for the input window.
37  */
38 class InputWindowHandleWrapper {
39 
40     /** The wrapped handle should not be directly exposed to avoid untracked changes. */
41     private final @NonNull InputWindowHandle mHandle;
42 
43     /** Whether the {@link #mHandle} is changed. */
44     private boolean mChanged = true;
45 
InputWindowHandleWrapper(@onNull InputWindowHandle handle)46     InputWindowHandleWrapper(@NonNull InputWindowHandle handle) {
47         mHandle = handle;
48     }
49 
50     /**
51      * Returns {@code true} if the input window handle has changed since the last invocation of
52      * {@link #applyChangesToSurface(SurfaceControl.Transaction, SurfaceControl)}}
53      */
isChanged()54     boolean isChanged() {
55         return mChanged;
56     }
57 
forceChange()58     void forceChange() {
59         mChanged = true;
60     }
61 
applyChangesToSurface(@onNull SurfaceControl.Transaction t, @NonNull SurfaceControl sc)62     void applyChangesToSurface(@NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl sc) {
63         t.setInputWindowInfo(sc, mHandle);
64         mChanged = false;
65     }
66 
getDisplayId()67     int getDisplayId() {
68         return mHandle.displayId;
69     }
70 
isFocusable()71     boolean isFocusable() {
72         return (mHandle.inputConfig & InputConfig.NOT_FOCUSABLE) == 0;
73     }
74 
isPaused()75     boolean isPaused() {
76         return (mHandle.inputConfig & InputConfig.PAUSE_DISPATCHING) != 0;
77     }
78 
isTrustedOverlay()79     boolean isTrustedOverlay() {
80         return (mHandle.inputConfig & InputConfig.TRUSTED_OVERLAY) != 0;
81     }
82 
hasWallpaper()83     boolean hasWallpaper() {
84         return (mHandle.inputConfig & InputConfig.DUPLICATE_TOUCH_TO_WALLPAPER)
85                 != 0;
86     }
87 
getInputApplicationHandle()88     InputApplicationHandle getInputApplicationHandle() {
89         return mHandle.inputApplicationHandle;
90     }
91 
setInputApplicationHandle(InputApplicationHandle handle)92     void setInputApplicationHandle(InputApplicationHandle handle) {
93         if (mHandle.inputApplicationHandle == handle) {
94             return;
95         }
96         mHandle.inputApplicationHandle = handle;
97         mChanged = true;
98     }
99 
setToken(IBinder token)100     void setToken(IBinder token) {
101         if (mHandle.token == token) {
102             return;
103         }
104         mHandle.token = token;
105         mChanged = true;
106     }
107 
setName(String name)108     void setName(String name) {
109         if (Objects.equals(mHandle.name, name)) {
110             return;
111         }
112         mHandle.name = name;
113         mChanged = true;
114     }
115 
setLayoutParamsFlags(@indowManager.LayoutParams.Flags int flags)116     void setLayoutParamsFlags(@WindowManager.LayoutParams.Flags int flags) {
117         if (mHandle.layoutParamsFlags == flags) {
118             return;
119         }
120         mHandle.layoutParamsFlags = flags;
121         mChanged = true;
122     }
123 
setLayoutParamsType(int type)124     void setLayoutParamsType(int type) {
125         if (mHandle.layoutParamsType == type) {
126             return;
127         }
128         mHandle.layoutParamsType = type;
129         mChanged = true;
130     }
131 
setDispatchingTimeoutMillis(long timeout)132     void setDispatchingTimeoutMillis(long timeout) {
133         if (mHandle.dispatchingTimeoutMillis == timeout) {
134             return;
135         }
136         mHandle.dispatchingTimeoutMillis = timeout;
137         mChanged = true;
138     }
139 
setTouchableRegion(Region region)140     void setTouchableRegion(Region region) {
141         if (mHandle.touchableRegion.equals(region)) {
142             return;
143         }
144         mHandle.touchableRegion.set(region);
145         mChanged = true;
146     }
147 
clearTouchableRegion()148     void clearTouchableRegion() {
149         if (mHandle.touchableRegion.isEmpty()) {
150             return;
151         }
152         mHandle.touchableRegion.setEmpty();
153         mChanged = true;
154     }
155 
setFocusable(boolean focusable)156     void setFocusable(boolean focusable) {
157         if (isFocusable() == focusable) {
158             return;
159         }
160         mHandle.setInputConfig(InputConfig.NOT_FOCUSABLE, !focusable);
161         mChanged = true;
162     }
163 
setTouchOcclusionMode(int mode)164     void setTouchOcclusionMode(int mode) {
165         if (mHandle.touchOcclusionMode == mode) {
166             return;
167         }
168         mHandle.touchOcclusionMode = mode;
169         mChanged = true;
170     }
171 
setHasWallpaper(boolean hasWallpaper)172     void setHasWallpaper(boolean hasWallpaper) {
173         if (this.hasWallpaper() == hasWallpaper) {
174             return;
175         }
176         mHandle.setInputConfig(InputConfig.DUPLICATE_TOUCH_TO_WALLPAPER,
177                 hasWallpaper);
178         mChanged = true;
179     }
180 
setPaused(boolean paused)181     void setPaused(boolean paused) {
182         if (isPaused() == paused) {
183             return;
184         }
185         mHandle.setInputConfig(InputConfig.PAUSE_DISPATCHING, paused);
186         mChanged = true;
187     }
188 
setTrustedOverlay(boolean trustedOverlay)189     void setTrustedOverlay(boolean trustedOverlay) {
190         if (isTrustedOverlay() == trustedOverlay) {
191             return;
192         }
193         mHandle.setInputConfig(InputConfig.TRUSTED_OVERLAY, trustedOverlay);
194         mChanged = true;
195     }
196 
setTrustedOverlay(SurfaceControl.Transaction t, SurfaceControl sc, boolean trustedOverlay)197     void setTrustedOverlay(SurfaceControl.Transaction t, SurfaceControl sc,
198             boolean trustedOverlay) {
199         mHandle.setTrustedOverlay(t, sc, trustedOverlay);
200     }
201 
setOwnerPid(int pid)202     void setOwnerPid(int pid) {
203         if (mHandle.ownerPid == pid) {
204             return;
205         }
206         mHandle.ownerPid = pid;
207         mChanged = true;
208     }
209 
setOwnerUid(int uid)210     void setOwnerUid(int uid) {
211         if (mHandle.ownerUid == uid) {
212             return;
213         }
214         mHandle.ownerUid = uid;
215         mChanged = true;
216     }
217 
setPackageName(String packageName)218     void setPackageName(String packageName) {
219         if (Objects.equals(mHandle.packageName, packageName)) {
220             return;
221         }
222         mHandle.packageName = packageName;
223         mChanged = true;
224     }
225 
setDisplayId(int displayId)226     void setDisplayId(int displayId) {
227         if (mHandle.displayId == displayId) {
228             return;
229         }
230         mHandle.displayId = displayId;
231         mChanged = true;
232     }
233 
setSurfaceInset(int inset)234     void setSurfaceInset(int inset) {
235         if (mHandle.surfaceInset == inset) {
236             return;
237         }
238         mHandle.surfaceInset = inset;
239         mChanged = true;
240     }
241 
setScaleFactor(float scale)242     void setScaleFactor(float scale) {
243         if (mHandle.scaleFactor == scale) {
244             return;
245         }
246         mHandle.scaleFactor = scale;
247         mChanged = true;
248     }
249 
setTouchableRegionCrop(@ullable SurfaceControl bounds)250     void setTouchableRegionCrop(@Nullable SurfaceControl bounds) {
251         if (mHandle.touchableRegionSurfaceControl.get() == bounds) {
252             return;
253         }
254         mHandle.setTouchableRegionCrop(bounds);
255         mChanged = true;
256     }
257 
setReplaceTouchableRegionWithCrop(boolean replace)258     void setReplaceTouchableRegionWithCrop(boolean replace) {
259         if (mHandle.replaceTouchableRegionWithCrop == replace) {
260             return;
261         }
262         mHandle.replaceTouchableRegionWithCrop = replace;
263         mChanged = true;
264     }
265 
setWindowToken(IBinder windowToken)266     void setWindowToken(IBinder windowToken) {
267         if (mHandle.getWindowToken() == windowToken) {
268             return;
269         }
270         mHandle.setWindowToken(windowToken);
271         mChanged = true;
272     }
273 
setInputConfigMasked(@nputConfigFlags int inputConfig, @InputConfigFlags int mask)274     void setInputConfigMasked(@InputConfigFlags int inputConfig, @InputConfigFlags int mask) {
275         final int inputConfigMasked = inputConfig & mask;
276         if (inputConfigMasked == (mHandle.inputConfig & mask)) {
277             return;
278         }
279         mHandle.inputConfig &= ~mask;
280         mHandle.inputConfig |= inputConfigMasked;
281         mChanged = true;
282     }
283 
setFocusTransferTarget(IBinder toToken)284     void setFocusTransferTarget(IBinder toToken) {
285         if (mHandle.focusTransferTarget == toToken) {
286             return;
287         }
288         mHandle.focusTransferTarget = toToken;
289         mChanged = true;
290     }
291 
292     @Override
toString()293     public String toString() {
294         return mHandle + ", changed=" + mChanged;
295     }
296 }
297