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