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