1 /* 2 * Copyright (C) 2010 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 static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 20 import static android.view.Display.INVALID_DISPLAY; 21 import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION; 22 import static android.view.WindowManager.INPUT_CONSUMER_PIP; 23 import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; 24 import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER; 25 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 26 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 27 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 28 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 29 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS; 30 import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; 31 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 32 33 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; 34 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT; 35 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 36 37 import android.graphics.Rect; 38 import android.os.Handler; 39 import android.os.IBinder; 40 import android.os.Looper; 41 import android.os.Process; 42 import android.os.Trace; 43 import android.os.UserHandle; 44 import android.util.ArrayMap; 45 import android.util.Slog; 46 import android.view.InputApplicationHandle; 47 import android.view.InputChannel; 48 import android.view.InputEventReceiver; 49 import android.view.InputWindowHandle; 50 import android.view.SurfaceControl; 51 52 import com.android.server.policy.WindowManagerPolicy; 53 import com.android.server.protolog.common.ProtoLog; 54 55 import java.io.PrintWriter; 56 import java.util.Set; 57 import java.util.function.Consumer; 58 59 final class InputMonitor { 60 private final WindowManagerService mService; 61 62 // Current window with input focus for keys and other non-touch events. May be null. 63 private WindowState mInputFocus; 64 65 // When true, need to call updateInputWindowsLw(). 66 private boolean mUpdateInputWindowsNeeded = true; 67 private boolean mUpdateInputWindowsPending; 68 private boolean mUpdateInputWindowsImmediately; 69 70 // Currently focused input window handle. 71 private InputWindowHandle mFocusedInputWindowHandle; 72 73 private boolean mDisableWallpaperTouchEvents; 74 private final Rect mTmpRect = new Rect(); 75 private final UpdateInputForAllWindowsConsumer mUpdateInputForAllWindowsConsumer; 76 77 private final int mDisplayId; 78 private final DisplayContent mDisplayContent; 79 private boolean mDisplayRemoved; 80 81 private final SurfaceControl.Transaction mInputTransaction; 82 private final Handler mHandler; 83 84 /** 85 * The set of input consumer added to the window manager by name, which consumes input events 86 * for the windows below it. 87 */ 88 private final ArrayMap<String, InputConsumerImpl> mInputConsumers = new ArrayMap(); 89 90 private static final class EventReceiverInputConsumer extends InputConsumerImpl 91 implements WindowManagerPolicy.InputConsumer { 92 private InputMonitor mInputMonitor; 93 private final InputEventReceiver mInputEventReceiver; 94 EventReceiverInputConsumer(WindowManagerService service, InputMonitor monitor, Looper looper, String name, InputEventReceiver.Factory inputEventReceiverFactory, int clientPid, UserHandle clientUser, int displayId)95 EventReceiverInputConsumer(WindowManagerService service, InputMonitor monitor, 96 Looper looper, String name, 97 InputEventReceiver.Factory inputEventReceiverFactory, 98 int clientPid, UserHandle clientUser, int displayId) { 99 super(service, null /* token */, name, null /* inputChannel */, clientPid, clientUser, 100 displayId); 101 mInputMonitor = monitor; 102 mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver( 103 mClientChannel, looper); 104 } 105 106 @Override dismiss()107 public void dismiss() { 108 synchronized (mService.mGlobalLock) { 109 mInputMonitor.mInputConsumers.remove(mName); 110 hide(mInputMonitor.mInputTransaction); 111 mInputMonitor.updateInputWindowsLw(true /* force */); 112 } 113 } 114 115 @Override dispose()116 public void dispose() { 117 synchronized (mService.mGlobalLock) { 118 disposeChannelsLw(mInputMonitor.mInputTransaction); 119 mInputEventReceiver.dispose(); 120 mInputMonitor.updateInputWindowsLw(true /* force */); 121 } 122 } 123 } 124 125 private class UpdateInputWindows implements Runnable { 126 @Override run()127 public void run() { 128 synchronized (mService.mGlobalLock) { 129 mUpdateInputWindowsPending = false; 130 mUpdateInputWindowsNeeded = false; 131 132 if (mDisplayRemoved) { 133 return; 134 } 135 136 // Populate the input window list with information about all of the windows that 137 // could potentially receive input. 138 // As an optimization, we could try to prune the list of windows but this turns 139 // out to be difficult because only the native code knows for sure which window 140 // currently has touch focus. 141 142 // If there's a drag in flight, provide a pseudo-window to catch drag input 143 final boolean inDrag = mService.mDragDropController.dragDropActiveLocked(); 144 145 // Add all windows on the default display. 146 mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag); 147 } 148 } 149 } 150 151 private final UpdateInputWindows mUpdateInputWindows = new UpdateInputWindows(); 152 InputMonitor(WindowManagerService service, DisplayContent displayContent)153 InputMonitor(WindowManagerService service, DisplayContent displayContent) { 154 mService = service; 155 mDisplayContent = displayContent; 156 mDisplayId = displayContent.getDisplayId(); 157 mInputTransaction = mService.mTransactionFactory.get(); 158 mHandler = mService.mAnimationHandler; 159 mUpdateInputForAllWindowsConsumer = new UpdateInputForAllWindowsConsumer(); 160 } 161 onDisplayRemoved()162 void onDisplayRemoved() { 163 mHandler.removeCallbacks(mUpdateInputWindows); 164 mHandler.post(() -> { 165 // Make sure any pending setInputWindowInfo transactions are completed. That prevents 166 // the timing of updating input info of removed display after cleanup. 167 mService.mTransactionFactory.get().syncInputWindows().apply(); 168 // It calls InputDispatcher::setInputWindows directly. 169 mService.mInputManager.onDisplayRemoved(mDisplayId); 170 }); 171 mDisplayRemoved = true; 172 } 173 addInputConsumer(String name, InputConsumerImpl consumer)174 private void addInputConsumer(String name, InputConsumerImpl consumer) { 175 mInputConsumers.put(name, consumer); 176 consumer.linkToDeathRecipient(); 177 updateInputWindowsLw(true /* force */); 178 } 179 destroyInputConsumer(String name)180 boolean destroyInputConsumer(String name) { 181 if (disposeInputConsumer(mInputConsumers.remove(name))) { 182 updateInputWindowsLw(true /* force */); 183 return true; 184 } 185 return false; 186 } 187 disposeInputConsumer(InputConsumerImpl consumer)188 private boolean disposeInputConsumer(InputConsumerImpl consumer) { 189 if (consumer != null) { 190 consumer.disposeChannelsLw(mInputTransaction); 191 return true; 192 } 193 return false; 194 } 195 getInputConsumer(String name)196 InputConsumerImpl getInputConsumer(String name) { 197 return mInputConsumers.get(name); 198 } 199 layoutInputConsumers(int dw, int dh)200 void layoutInputConsumers(int dw, int dh) { 201 try { 202 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "layoutInputConsumer"); 203 for (int i = mInputConsumers.size() - 1; i >= 0; i--) { 204 mInputConsumers.valueAt(i).layout(mInputTransaction, dw, dh); 205 } 206 } finally { 207 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 208 } 209 } 210 211 // The visibility of the input consumers is recomputed each time we 212 // update the input windows. We use a model where consumers begin invisible 213 // (set so by this function) and must meet some condition for visibility on each update. resetInputConsumers(SurfaceControl.Transaction t)214 void resetInputConsumers(SurfaceControl.Transaction t) { 215 for (int i = mInputConsumers.size() - 1; i >= 0; i--) { 216 mInputConsumers.valueAt(i).hide(t); 217 } 218 } 219 createInputConsumer(Looper looper, String name, InputEventReceiver.Factory inputEventReceiverFactory)220 WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name, 221 InputEventReceiver.Factory inputEventReceiverFactory) { 222 if (mInputConsumers.containsKey(name)) { 223 throw new IllegalStateException("Existing input consumer found with name: " + name 224 + ", display: " + mDisplayId); 225 } 226 final EventReceiverInputConsumer consumer = new EventReceiverInputConsumer(mService, 227 this, looper, name, inputEventReceiverFactory, Process.myPid(), 228 UserHandle.SYSTEM, mDisplayId); 229 addInputConsumer(name, consumer); 230 return consumer; 231 } 232 createInputConsumer(IBinder token, String name, InputChannel inputChannel, int clientPid, UserHandle clientUser)233 void createInputConsumer(IBinder token, String name, InputChannel inputChannel, int clientPid, 234 UserHandle clientUser) { 235 if (mInputConsumers.containsKey(name)) { 236 throw new IllegalStateException("Existing input consumer found with name: " + name 237 + ", display: " + mDisplayId); 238 } 239 240 final InputConsumerImpl consumer = new InputConsumerImpl(mService, token, name, 241 inputChannel, clientPid, clientUser, mDisplayId); 242 switch (name) { 243 case INPUT_CONSUMER_WALLPAPER: 244 consumer.mWindowHandle.hasWallpaper = true; 245 break; 246 case INPUT_CONSUMER_PIP: 247 // The touchable region of the Pip input window is cropped to the bounds of the 248 // stack, and we need FLAG_NOT_TOUCH_MODAL to ensure other events fall through 249 consumer.mWindowHandle.layoutParamsFlags |= FLAG_NOT_TOUCH_MODAL; 250 break; 251 } 252 addInputConsumer(name, consumer); 253 } 254 255 populateInputWindowHandle(final InputWindowHandle inputWindowHandle, final WindowState child, int flags, final int type, final boolean isVisible, final boolean hasFocus, final boolean hasWallpaper)256 void populateInputWindowHandle(final InputWindowHandle inputWindowHandle, 257 final WindowState child, int flags, final int type, final boolean isVisible, 258 final boolean hasFocus, final boolean hasWallpaper) { 259 // Add a window to our list of input windows. 260 inputWindowHandle.name = child.toString(); 261 flags = child.getSurfaceTouchableRegion(inputWindowHandle, flags); 262 inputWindowHandle.layoutParamsFlags = flags; 263 inputWindowHandle.layoutParamsType = type; 264 inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos(); 265 inputWindowHandle.visible = isVisible; 266 inputWindowHandle.canReceiveKeys = child.canReceiveKeys(); 267 inputWindowHandle.hasFocus = hasFocus; 268 inputWindowHandle.hasWallpaper = hasWallpaper; 269 inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false; 270 inputWindowHandle.ownerPid = child.mSession.mPid; 271 inputWindowHandle.ownerUid = child.mSession.mUid; 272 inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures; 273 inputWindowHandle.displayId = child.getDisplayId(); 274 275 final Rect frame = child.getFrameLw(); 276 inputWindowHandle.frameLeft = frame.left; 277 inputWindowHandle.frameTop = frame.top; 278 inputWindowHandle.frameRight = frame.right; 279 inputWindowHandle.frameBottom = frame.bottom; 280 281 // Surface insets are hardcoded to be the same in all directions 282 // and we could probably deprecate the "left/right/top/bottom" concept. 283 // we avoid reintroducing this concept by just choosing one of them here. 284 inputWindowHandle.surfaceInset = child.getAttrs().surfaceInsets.left; 285 286 /** 287 * If the window is in a TaskManaged by a TaskOrganizer then most cropping 288 * will be applied using the SurfaceControl hierarchy from the Organizer. 289 * This means we need to make sure that these changes in crop are reflected 290 * in the input windows, and so ensure this flag is set so that 291 * the input crop always reflects the surface hierarchy. 292 * we may have some issues with modal-windows, but I guess we can 293 * cross that bridge when we come to implementing full-screen TaskOrg 294 */ 295 if (child.getTask() != null && child.getTask().isOrganized()) { 296 inputWindowHandle.replaceTouchableRegionWithCrop(null /* Use this surfaces crop */); 297 } 298 299 if (child.mGlobalScale != 1) { 300 // If we are scaling the window, input coordinates need 301 // to be inversely scaled to map from what is on screen 302 // to what is actually being touched in the UI. 303 inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale; 304 } else { 305 inputWindowHandle.scaleFactor = 1; 306 } 307 308 if (DEBUG_INPUT) { 309 Slog.d(TAG_WM, "addInputWindowHandle: " 310 + child + ", " + inputWindowHandle); 311 } 312 313 if (hasFocus) { 314 mFocusedInputWindowHandle = inputWindowHandle; 315 } 316 } 317 setUpdateInputWindowsNeededLw()318 void setUpdateInputWindowsNeededLw() { 319 mUpdateInputWindowsNeeded = true; 320 } 321 322 /* Updates the cached window information provided to the input dispatcher. */ updateInputWindowsLw(boolean force)323 void updateInputWindowsLw(boolean force) { 324 if (!force && !mUpdateInputWindowsNeeded) { 325 return; 326 } 327 scheduleUpdateInputWindows(); 328 } 329 scheduleUpdateInputWindows()330 private void scheduleUpdateInputWindows() { 331 if (mDisplayRemoved) { 332 return; 333 } 334 335 if (!mUpdateInputWindowsPending) { 336 mUpdateInputWindowsPending = true; 337 mHandler.post(mUpdateInputWindows); 338 } 339 } 340 341 /** 342 * Immediately update the input transaction and merge into the passing Transaction that could be 343 * collected and applied later. 344 */ updateInputWindowsImmediately(SurfaceControl.Transaction t)345 void updateInputWindowsImmediately(SurfaceControl.Transaction t) { 346 mHandler.removeCallbacks(mUpdateInputWindows); 347 mUpdateInputWindowsImmediately = true; 348 mUpdateInputWindows.run(); 349 mUpdateInputWindowsImmediately = false; 350 t.merge(mInputTransaction); 351 } 352 353 /** 354 * Called when the current input focus changes. 355 * Layer assignment is assumed to be complete by the time this is called. 356 */ setInputFocusLw(WindowState newWindow, boolean updateInputWindows)357 public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) { 358 ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "Input focus has changed to %s", newWindow); 359 360 if (newWindow != mInputFocus) { 361 if (newWindow != null && newWindow.canReceiveKeys()) { 362 // Displaying a window implicitly causes dispatching to be unpaused. 363 // This is to protect against bugs if someone pauses dispatching but 364 // forgets to resume. 365 newWindow.mToken.paused = false; 366 } 367 368 mInputFocus = newWindow; 369 setUpdateInputWindowsNeededLw(); 370 371 if (updateInputWindows) { 372 updateInputWindowsLw(false /*force*/); 373 } 374 } 375 } 376 setFocusedAppLw(ActivityRecord newApp)377 public void setFocusedAppLw(ActivityRecord newApp) { 378 // Focused app has changed. 379 if (newApp == null) { 380 mService.mInputManager.setFocusedApplication(mDisplayId, null); 381 } else { 382 final InputApplicationHandle handle = newApp.mInputApplicationHandle; 383 handle.name = newApp.toString(); 384 handle.dispatchingTimeoutNanos = newApp.mInputDispatchingTimeoutNanos; 385 386 mService.mInputManager.setFocusedApplication(mDisplayId, handle); 387 } 388 } 389 pauseDispatchingLw(WindowToken window)390 public void pauseDispatchingLw(WindowToken window) { 391 if (! window.paused) { 392 if (DEBUG_INPUT) { 393 Slog.v(TAG_WM, "Pausing WindowToken " + window); 394 } 395 396 window.paused = true; 397 updateInputWindowsLw(true /*force*/); 398 } 399 } 400 resumeDispatchingLw(WindowToken window)401 public void resumeDispatchingLw(WindowToken window) { 402 if (window.paused) { 403 if (DEBUG_INPUT) { 404 Slog.v(TAG_WM, "Resuming WindowToken " + window); 405 } 406 407 window.paused = false; 408 updateInputWindowsLw(true /*force*/); 409 } 410 } 411 dump(PrintWriter pw, String prefix)412 void dump(PrintWriter pw, String prefix) { 413 final Set<String> inputConsumerKeys = mInputConsumers.keySet(); 414 if (!inputConsumerKeys.isEmpty()) { 415 pw.println(prefix + "InputConsumers:"); 416 for (String key : inputConsumerKeys) { 417 mInputConsumers.get(key).dump(pw, key, prefix); 418 } 419 } 420 } 421 422 private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> { 423 InputConsumerImpl mNavInputConsumer; 424 InputConsumerImpl mPipInputConsumer; 425 InputConsumerImpl mWallpaperInputConsumer; 426 InputConsumerImpl mRecentsAnimationInputConsumer; 427 428 private boolean mAddNavInputConsumerHandle; 429 private boolean mAddPipInputConsumerHandle; 430 private boolean mAddWallpaperInputConsumerHandle; 431 private boolean mAddRecentsAnimationInputConsumerHandle; 432 433 boolean mInDrag; 434 WallpaperController mWallpaperController; 435 436 // An invalid window handle that tells SurfaceFlinger not update the input info. 437 final InputWindowHandle mInvalidInputWindow = new InputWindowHandle(null, mDisplayId); 438 updateInputWindows(boolean inDrag)439 private void updateInputWindows(boolean inDrag) { 440 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateInputWindows"); 441 442 mNavInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION); 443 mPipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP); 444 mWallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER); 445 mRecentsAnimationInputConsumer = getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION); 446 447 mAddNavInputConsumerHandle = mNavInputConsumer != null; 448 mAddPipInputConsumerHandle = mPipInputConsumer != null; 449 mAddWallpaperInputConsumerHandle = mWallpaperInputConsumer != null; 450 mAddRecentsAnimationInputConsumerHandle = mRecentsAnimationInputConsumer != null; 451 452 mTmpRect.setEmpty(); 453 mDisableWallpaperTouchEvents = false; 454 mInDrag = inDrag; 455 mWallpaperController = mDisplayContent.mWallpaperController; 456 457 resetInputConsumers(mInputTransaction); 458 459 mDisplayContent.forAllWindows(this, 460 true /* traverseTopToBottom */); 461 462 if (mAddWallpaperInputConsumerHandle) { 463 mWallpaperInputConsumer.show(mInputTransaction, 0); 464 } 465 if (!mUpdateInputWindowsImmediately) { 466 mDisplayContent.getPendingTransaction().merge(mInputTransaction); 467 mDisplayContent.scheduleAnimation(); 468 } 469 470 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 471 } 472 473 @Override accept(WindowState w)474 public void accept(WindowState w) { 475 final InputChannel inputChannel = w.mInputChannel; 476 final InputWindowHandle inputWindowHandle = w.mInputWindowHandle; 477 final RecentsAnimationController recentsAnimationController = 478 mService.getRecentsAnimationController(); 479 final boolean shouldApplyRecentsInputConsumer = recentsAnimationController != null 480 && recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord); 481 final int type = w.mAttrs.type; 482 final boolean isVisible = w.isVisibleLw(); 483 if (inputChannel == null || inputWindowHandle == null || w.mRemoved 484 || (w.cantReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) { 485 if (w.mWinAnimator.hasSurface()) { 486 // Assign an InputInfo with type to the overlay window which can't receive input 487 // event. This is used to omit Surfaces from occlusion detection. 488 populateOverlayInputInfo(mInvalidInputWindow, w.getName(), type, isVisible); 489 mInputTransaction.setInputWindowInfo( 490 w.mWinAnimator.mSurfaceController.getClientViewRootSurface(), 491 mInvalidInputWindow); 492 return; 493 } 494 // Skip this window because it cannot possibly receive input. 495 return; 496 } 497 498 final int flags = w.mAttrs.flags; 499 final int privateFlags = w.mAttrs.privateFlags; 500 final boolean hasFocus = w.isFocused(); 501 502 if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) { 503 if (recentsAnimationController.updateInputConsumerForApp( 504 mRecentsAnimationInputConsumer.mWindowHandle, hasFocus)) { 505 mRecentsAnimationInputConsumer.show(mInputTransaction, w); 506 mAddRecentsAnimationInputConsumerHandle = false; 507 } 508 } 509 510 if (w.inPinnedWindowingMode()) { 511 if (mAddPipInputConsumerHandle) { 512 final Task rootTask = w.getTask().getRootTask(); 513 mPipInputConsumer.mWindowHandle.replaceTouchableRegionWithCrop( 514 rootTask.getSurfaceControl()); 515 // We set the layer to z=MAX-1 so that it's always on top. 516 mPipInputConsumer.reparent(mInputTransaction, rootTask); 517 mPipInputConsumer.show(mInputTransaction, Integer.MAX_VALUE - 1); 518 mAddPipInputConsumerHandle = false; 519 } 520 } 521 522 if (mAddNavInputConsumerHandle) { 523 mNavInputConsumer.show(mInputTransaction, w); 524 mAddNavInputConsumerHandle = false; 525 } 526 527 if (mAddWallpaperInputConsumerHandle) { 528 if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) { 529 // Add the wallpaper input consumer above the first visible wallpaper. 530 mWallpaperInputConsumer.show(mInputTransaction, w); 531 mAddWallpaperInputConsumerHandle = false; 532 } 533 } 534 535 if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) { 536 mDisableWallpaperTouchEvents = true; 537 } 538 final boolean hasWallpaper = mWallpaperController.isWallpaperTarget(w) 539 && !mService.mPolicy.isKeyguardShowing() 540 && !mDisableWallpaperTouchEvents; 541 542 // If there's a drag in progress and 'child' is a potential drop target, 543 // make sure it's been told about the drag 544 if (mInDrag && isVisible && w.getDisplayContent().isDefaultDisplay) { 545 mService.mDragDropController.sendDragStartedIfNeededLocked(w); 546 } 547 548 populateInputWindowHandle( 549 inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper); 550 551 // register key interception info 552 mService.mKeyInterceptionInfoForToken.put(inputWindowHandle.token, 553 w.getKeyInterceptionInfo()); 554 555 if (w.mWinAnimator.hasSurface()) { 556 mInputTransaction.setInputWindowInfo( 557 w.mWinAnimator.mSurfaceController.getClientViewRootSurface(), 558 inputWindowHandle); 559 } 560 } 561 } 562 563 // This would reset InputWindowHandle fields to prevent it could be found by input event. 564 // We need to check if any new field of InputWindowHandle could impact the result. populateOverlayInputInfo(final InputWindowHandle inputWindowHandle, final String name, final int type, final boolean isVisible)565 private static void populateOverlayInputInfo(final InputWindowHandle inputWindowHandle, 566 final String name, final int type, final boolean isVisible) { 567 inputWindowHandle.name = name; 568 inputWindowHandle.layoutParamsType = type; 569 inputWindowHandle.dispatchingTimeoutNanos = 570 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 571 inputWindowHandle.visible = isVisible; 572 inputWindowHandle.canReceiveKeys = false; 573 inputWindowHandle.hasFocus = false; 574 inputWindowHandle.inputFeatures = INPUT_FEATURE_NO_INPUT_CHANNEL; 575 inputWindowHandle.scaleFactor = 1; 576 inputWindowHandle.layoutParamsFlags = 577 FLAG_NOT_TOUCH_MODAL | FLAG_NOT_TOUCHABLE | FLAG_NOT_FOCUSABLE; 578 inputWindowHandle.portalToDisplayId = INVALID_DISPLAY; 579 inputWindowHandle.touchableRegion.setEmpty(); 580 inputWindowHandle.setTouchableRegionCrop(null); 581 } 582 583 /** 584 * Helper function to generate an InputInfo with type SECURE_SYSTEM_OVERLAY. This input 585 * info will not have an input channel or be touchable, but is used to omit Surfaces 586 * from occlusion detection, so that System global overlays like the Watermark aren't 587 * counted by the InputDispatcher as occluding applications below. 588 */ setTrustedOverlayInputInfo(SurfaceControl sc, SurfaceControl.Transaction t, int displayId, String name)589 static void setTrustedOverlayInputInfo(SurfaceControl sc, SurfaceControl.Transaction t, 590 int displayId, String name) { 591 InputWindowHandle inputWindowHandle = new InputWindowHandle(null, displayId); 592 populateOverlayInputInfo(inputWindowHandle, name, TYPE_SECURE_SYSTEM_OVERLAY, true); 593 t.setInputWindowInfo(sc, inputWindowHandle); 594 } 595 } 596