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