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.app.ActivityManager.StackId.PINNED_STACK_ID; 20 import static android.view.Display.DEFAULT_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_WALLPAPER; 24 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 25 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS; 26 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 27 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 28 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 29 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG; 30 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 31 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT; 32 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; 33 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 34 35 import android.app.ActivityManager; 36 import android.graphics.Rect; 37 import android.os.Debug; 38 import android.os.Looper; 39 import android.os.RemoteException; 40 import android.util.ArrayMap; 41 import android.util.Log; 42 import android.util.Slog; 43 import android.view.InputChannel; 44 import android.view.InputEventReceiver; 45 import android.view.KeyEvent; 46 import android.view.WindowManager; 47 48 import android.view.WindowManagerPolicy; 49 50 import com.android.server.input.InputApplicationHandle; 51 import com.android.server.input.InputManagerService; 52 import com.android.server.input.InputWindowHandle; 53 54 import java.io.PrintWriter; 55 import java.util.Arrays; 56 import java.util.Set; 57 import java.util.function.Consumer; 58 59 final class InputMonitor implements InputManagerService.WindowManagerCallbacks { 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, prevents input dispatch from proceeding until set to false again. 66 private boolean mInputDispatchFrozen; 67 68 // The reason the input is currently frozen or null if the input isn't frozen. 69 private String mInputFreezeReason = null; 70 71 // When true, input dispatch proceeds normally. Otherwise all events are dropped. 72 // Initially false, so that input does not get dispatched until boot is finished at 73 // which point the ActivityManager will enable dispatching. 74 private boolean mInputDispatchEnabled; 75 76 // When true, need to call updateInputWindowsLw(). 77 private boolean mUpdateInputWindowsNeeded = true; 78 79 // Array of window handles to provide to the input dispatcher. 80 private InputWindowHandle[] mInputWindowHandles; 81 private int mInputWindowHandleCount; 82 private InputWindowHandle mFocusedInputWindowHandle; 83 84 private boolean mAddInputConsumerHandle; 85 private boolean mAddPipInputConsumerHandle; 86 private boolean mAddWallpaperInputConsumerHandle; 87 private boolean mDisableWallpaperTouchEvents; 88 private final Rect mTmpRect = new Rect(); 89 private final UpdateInputForAllWindowsConsumer mUpdateInputForAllWindowsConsumer = 90 new UpdateInputForAllWindowsConsumer(); 91 92 // Set to true when the first input device configuration change notification 93 // is received to indicate that the input devices are ready. 94 private final Object mInputDevicesReadyMonitor = new Object(); 95 private boolean mInputDevicesReady; 96 97 /** 98 * The set of input consumer added to the window manager by name, which consumes input events 99 * for the windows below it. 100 */ 101 private final ArrayMap<String, InputConsumerImpl> mInputConsumers = new ArrayMap(); 102 103 private static final class EventReceiverInputConsumer extends InputConsumerImpl 104 implements WindowManagerPolicy.InputConsumer { 105 private InputMonitor mInputMonitor; 106 private final InputEventReceiver mInputEventReceiver; 107 EventReceiverInputConsumer(WindowManagerService service, InputMonitor monitor, Looper looper, String name, InputEventReceiver.Factory inputEventReceiverFactory)108 EventReceiverInputConsumer(WindowManagerService service, InputMonitor monitor, 109 Looper looper, String name, 110 InputEventReceiver.Factory inputEventReceiverFactory) { 111 super(service, name, null); 112 mInputMonitor = monitor; 113 mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver( 114 mClientChannel, looper); 115 } 116 117 @Override dismiss()118 public void dismiss() { 119 synchronized (mService.mWindowMap) { 120 if (mInputMonitor.destroyInputConsumer(mWindowHandle.name)) { 121 mInputEventReceiver.dispose(); 122 } 123 } 124 } 125 } 126 InputMonitor(WindowManagerService service)127 public InputMonitor(WindowManagerService service) { 128 mService = service; 129 } 130 addInputConsumer(String name, InputConsumerImpl consumer)131 private void addInputConsumer(String name, InputConsumerImpl consumer) { 132 mInputConsumers.put(name, consumer); 133 updateInputWindowsLw(true /* force */); 134 } 135 destroyInputConsumer(String name)136 boolean destroyInputConsumer(String name) { 137 if (disposeInputConsumer(mInputConsumers.remove(name))) { 138 updateInputWindowsLw(true /* force */); 139 return true; 140 } 141 return false; 142 } 143 disposeInputConsumer(InputConsumerImpl consumer)144 private boolean disposeInputConsumer(InputConsumerImpl consumer) { 145 if (consumer != null) { 146 consumer.disposeChannelsLw(); 147 return true; 148 } 149 return false; 150 } 151 getInputConsumer(String name, int displayId)152 InputConsumerImpl getInputConsumer(String name, int displayId) { 153 // TODO(multi-display): Allow input consumers on non-default displays? 154 return (displayId == DEFAULT_DISPLAY) ? mInputConsumers.get(name) : null; 155 } 156 layoutInputConsumers(int dw, int dh)157 void layoutInputConsumers(int dw, int dh) { 158 for (int i = mInputConsumers.size() - 1; i >= 0; i--) { 159 mInputConsumers.valueAt(i).layout(dw, dh); 160 } 161 } 162 createInputConsumer(Looper looper, String name, InputEventReceiver.Factory inputEventReceiverFactory)163 WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name, 164 InputEventReceiver.Factory inputEventReceiverFactory) { 165 if (mInputConsumers.containsKey(name)) { 166 throw new IllegalStateException("Existing input consumer found with name: " + name); 167 } 168 169 final EventReceiverInputConsumer consumer = new EventReceiverInputConsumer(mService, 170 this, looper, name, inputEventReceiverFactory); 171 addInputConsumer(name, consumer); 172 return consumer; 173 } 174 createInputConsumer(String name, InputChannel inputChannel)175 void createInputConsumer(String name, InputChannel inputChannel) { 176 if (mInputConsumers.containsKey(name)) { 177 throw new IllegalStateException("Existing input consumer found with name: " + name); 178 } 179 180 final InputConsumerImpl consumer = new InputConsumerImpl(mService, name, inputChannel); 181 switch (name) { 182 case INPUT_CONSUMER_WALLPAPER: 183 consumer.mWindowHandle.hasWallpaper = true; 184 break; 185 case INPUT_CONSUMER_PIP: 186 // The touchable region of the Pip input window is cropped to the bounds of the 187 // stack, and we need FLAG_NOT_TOUCH_MODAL to ensure other events fall through 188 consumer.mWindowHandle.layoutParamsFlags |= FLAG_NOT_TOUCH_MODAL; 189 break; 190 } 191 addInputConsumer(name, consumer); 192 } 193 194 /* Notifies the window manager about a broken input channel. 195 * 196 * Called by the InputManager. 197 */ 198 @Override notifyInputChannelBroken(InputWindowHandle inputWindowHandle)199 public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) { 200 if (inputWindowHandle == null) { 201 return; 202 } 203 204 synchronized (mService.mWindowMap) { 205 WindowState windowState = (WindowState) inputWindowHandle.windowState; 206 if (windowState != null) { 207 Slog.i(TAG_WM, "WINDOW DIED " + windowState); 208 windowState.removeIfPossible(); 209 } 210 } 211 } 212 213 /* Notifies the window manager about an application that is not responding. 214 * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch. 215 * 216 * Called by the InputManager. 217 */ 218 @Override notifyANR(InputApplicationHandle inputApplicationHandle, InputWindowHandle inputWindowHandle, String reason)219 public long notifyANR(InputApplicationHandle inputApplicationHandle, 220 InputWindowHandle inputWindowHandle, String reason) { 221 AppWindowToken appWindowToken = null; 222 WindowState windowState = null; 223 boolean aboveSystem = false; 224 synchronized (mService.mWindowMap) { 225 if (inputWindowHandle != null) { 226 windowState = (WindowState) inputWindowHandle.windowState; 227 if (windowState != null) { 228 appWindowToken = windowState.mAppToken; 229 } 230 } 231 if (appWindowToken == null && inputApplicationHandle != null) { 232 appWindowToken = (AppWindowToken)inputApplicationHandle.appWindowToken; 233 } 234 235 if (windowState != null) { 236 Slog.i(TAG_WM, "Input event dispatching timed out " 237 + "sending to " + windowState.mAttrs.getTitle() 238 + ". Reason: " + reason); 239 // Figure out whether this window is layered above system windows. 240 // We need to do this here to help the activity manager know how to 241 // layer its ANR dialog. 242 int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw( 243 TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow); 244 aboveSystem = windowState.mBaseLayer > systemAlertLayer; 245 } else if (appWindowToken != null) { 246 Slog.i(TAG_WM, "Input event dispatching timed out " 247 + "sending to application " + appWindowToken.stringName 248 + ". Reason: " + reason); 249 } else { 250 Slog.i(TAG_WM, "Input event dispatching timed out " 251 + ". Reason: " + reason); 252 } 253 254 mService.saveANRStateLocked(appWindowToken, windowState, reason); 255 } 256 257 // All the calls below need to happen without the WM lock held since they call into AM. 258 mService.mAmInternal.saveANRState(reason); 259 260 if (appWindowToken != null && appWindowToken.appToken != null) { 261 // Notify the activity manager about the timeout and let it decide whether 262 // to abort dispatching or keep waiting. 263 final AppWindowContainerController controller = appWindowToken.getController(); 264 final boolean abort = controller != null 265 && controller.keyDispatchingTimedOut(reason, 266 (windowState != null) ? windowState.mSession.mPid : -1); 267 if (!abort) { 268 // The activity manager declined to abort dispatching. 269 // Wait a bit longer and timeout again later. 270 return appWindowToken.mInputDispatchingTimeoutNanos; 271 } 272 } else if (windowState != null) { 273 try { 274 // Notify the activity manager about the timeout and let it decide whether 275 // to abort dispatching or keep waiting. 276 long timeout = ActivityManager.getService().inputDispatchingTimedOut( 277 windowState.mSession.mPid, aboveSystem, reason); 278 if (timeout >= 0) { 279 // The activity manager declined to abort dispatching. 280 // Wait a bit longer and timeout again later. 281 return timeout * 1000000L; // nanoseconds 282 } 283 } catch (RemoteException ex) { 284 } 285 } 286 return 0; // abort dispatching 287 } 288 addInputWindowHandle(final InputWindowHandle windowHandle)289 private void addInputWindowHandle(final InputWindowHandle windowHandle) { 290 if (mInputWindowHandles == null) { 291 mInputWindowHandles = new InputWindowHandle[16]; 292 } 293 if (mInputWindowHandleCount >= mInputWindowHandles.length) { 294 mInputWindowHandles = Arrays.copyOf(mInputWindowHandles, 295 mInputWindowHandleCount * 2); 296 } 297 mInputWindowHandles[mInputWindowHandleCount++] = windowHandle; 298 } 299 addInputWindowHandle(final InputWindowHandle inputWindowHandle, final WindowState child, int flags, final int type, final boolean isVisible, final boolean hasFocus, final boolean hasWallpaper)300 void addInputWindowHandle(final InputWindowHandle inputWindowHandle, 301 final WindowState child, int flags, final int type, final boolean isVisible, 302 final boolean hasFocus, final boolean hasWallpaper) { 303 // Add a window to our list of input windows. 304 inputWindowHandle.name = child.toString(); 305 flags = child.getTouchableRegion(inputWindowHandle.touchableRegion, flags); 306 inputWindowHandle.layoutParamsFlags = flags; 307 inputWindowHandle.layoutParamsType = type; 308 inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos(); 309 inputWindowHandle.visible = isVisible; 310 inputWindowHandle.canReceiveKeys = child.canReceiveKeys(); 311 inputWindowHandle.hasFocus = hasFocus; 312 inputWindowHandle.hasWallpaper = hasWallpaper; 313 inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false; 314 inputWindowHandle.layer = child.mLayer; 315 inputWindowHandle.ownerPid = child.mSession.mPid; 316 inputWindowHandle.ownerUid = child.mSession.mUid; 317 inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures; 318 319 final Rect frame = child.mFrame; 320 inputWindowHandle.frameLeft = frame.left; 321 inputWindowHandle.frameTop = frame.top; 322 inputWindowHandle.frameRight = frame.right; 323 inputWindowHandle.frameBottom = frame.bottom; 324 325 if (child.mGlobalScale != 1) { 326 // If we are scaling the window, input coordinates need 327 // to be inversely scaled to map from what is on screen 328 // to what is actually being touched in the UI. 329 inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale; 330 } else { 331 inputWindowHandle.scaleFactor = 1; 332 } 333 334 if (DEBUG_INPUT) { 335 Slog.d(TAG_WM, "addInputWindowHandle: " 336 + child + ", " + inputWindowHandle); 337 } 338 addInputWindowHandle(inputWindowHandle); 339 if (hasFocus) { 340 mFocusedInputWindowHandle = inputWindowHandle; 341 } 342 } 343 clearInputWindowHandlesLw()344 private void clearInputWindowHandlesLw() { 345 while (mInputWindowHandleCount != 0) { 346 mInputWindowHandles[--mInputWindowHandleCount] = null; 347 } 348 mFocusedInputWindowHandle = null; 349 } 350 setUpdateInputWindowsNeededLw()351 void setUpdateInputWindowsNeededLw() { 352 mUpdateInputWindowsNeeded = true; 353 } 354 355 /* Updates the cached window information provided to the input dispatcher. */ updateInputWindowsLw(boolean force)356 void updateInputWindowsLw(boolean force) { 357 if (!force && !mUpdateInputWindowsNeeded) { 358 return; 359 } 360 mUpdateInputWindowsNeeded = false; 361 362 if (false) Slog.d(TAG_WM, ">>>>>> ENTERED updateInputWindowsLw"); 363 364 // Populate the input window list with information about all of the windows that 365 // could potentially receive input. 366 // As an optimization, we could try to prune the list of windows but this turns 367 // out to be difficult because only the native code knows for sure which window 368 // currently has touch focus. 369 370 // If there's a drag in flight, provide a pseudo-window to catch drag input 371 final boolean inDrag = (mService.mDragState != null); 372 if (inDrag) { 373 if (DEBUG_DRAG) { 374 Log.d(TAG_WM, "Inserting drag window"); 375 } 376 final InputWindowHandle dragWindowHandle = mService.mDragState.getInputWindowHandle(); 377 if (dragWindowHandle != null) { 378 addInputWindowHandle(dragWindowHandle); 379 } else { 380 Slog.w(TAG_WM, "Drag is in progress but there is no " 381 + "drag window handle."); 382 } 383 } 384 385 final boolean inPositioning = (mService.mTaskPositioner != null); 386 if (inPositioning) { 387 if (DEBUG_TASK_POSITIONING) { 388 Log.d(TAG_WM, "Inserting window handle for repositioning"); 389 } 390 final InputWindowHandle dragWindowHandle = mService.mTaskPositioner.mDragWindowHandle; 391 if (dragWindowHandle != null) { 392 addInputWindowHandle(dragWindowHandle); 393 } else { 394 Slog.e(TAG_WM, 395 "Repositioning is in progress but there is no drag window handle."); 396 } 397 } 398 399 // Add all windows on the default display. 400 mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag); 401 402 if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw"); 403 } 404 405 /* Notifies that the input device configuration has changed. */ 406 @Override notifyConfigurationChanged()407 public void notifyConfigurationChanged() { 408 // TODO(multi-display): Notify proper displays that are associated with this input device. 409 mService.sendNewConfiguration(DEFAULT_DISPLAY); 410 411 synchronized (mInputDevicesReadyMonitor) { 412 if (!mInputDevicesReady) { 413 mInputDevicesReady = true; 414 mInputDevicesReadyMonitor.notifyAll(); 415 } 416 } 417 } 418 419 /* Waits until the built-in input devices have been configured. */ waitForInputDevicesReady(long timeoutMillis)420 public boolean waitForInputDevicesReady(long timeoutMillis) { 421 synchronized (mInputDevicesReadyMonitor) { 422 if (!mInputDevicesReady) { 423 try { 424 mInputDevicesReadyMonitor.wait(timeoutMillis); 425 } catch (InterruptedException ex) { 426 } 427 } 428 return mInputDevicesReady; 429 } 430 } 431 432 /* Notifies that the lid switch changed state. */ 433 @Override notifyLidSwitchChanged(long whenNanos, boolean lidOpen)434 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 435 mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen); 436 } 437 438 /* Notifies that the camera lens cover state has changed. */ 439 @Override notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered)440 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 441 mService.mPolicy.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered); 442 } 443 444 /* Provides an opportunity for the window manager policy to intercept early key 445 * processing as soon as the key has been read from the device. */ 446 @Override interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)447 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 448 return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags); 449 } 450 451 /* Provides an opportunity for the window manager policy to intercept early motion event 452 * processing when the device is in a non-interactive state since these events are normally 453 * dropped. */ 454 @Override interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags)455 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 456 return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive( 457 whenNanos, policyFlags); 458 } 459 460 /* Provides an opportunity for the window manager policy to process a key before 461 * ordinary dispatch. */ 462 @Override interceptKeyBeforeDispatching( InputWindowHandle focus, KeyEvent event, int policyFlags)463 public long interceptKeyBeforeDispatching( 464 InputWindowHandle focus, KeyEvent event, int policyFlags) { 465 WindowState windowState = focus != null ? (WindowState) focus.windowState : null; 466 return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags); 467 } 468 469 /* Provides an opportunity for the window manager policy to process a key that 470 * the application did not handle. */ 471 @Override dispatchUnhandledKey( InputWindowHandle focus, KeyEvent event, int policyFlags)472 public KeyEvent dispatchUnhandledKey( 473 InputWindowHandle focus, KeyEvent event, int policyFlags) { 474 WindowState windowState = focus != null ? (WindowState) focus.windowState : null; 475 return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags); 476 } 477 478 /* Callback to get pointer layer. */ 479 @Override getPointerLayer()480 public int getPointerLayer() { 481 return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER) 482 * WindowManagerService.TYPE_LAYER_MULTIPLIER 483 + WindowManagerService.TYPE_LAYER_OFFSET; 484 } 485 486 /* Called when the current input focus changes. 487 * Layer assignment is assumed to be complete by the time this is called. 488 */ setInputFocusLw(WindowState newWindow, boolean updateInputWindows)489 public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) { 490 if (DEBUG_FOCUS_LIGHT || DEBUG_INPUT) { 491 Slog.d(TAG_WM, "Input focus has changed to " + newWindow); 492 } 493 494 if (newWindow != mInputFocus) { 495 if (newWindow != null && newWindow.canReceiveKeys()) { 496 // Displaying a window implicitly causes dispatching to be unpaused. 497 // This is to protect against bugs if someone pauses dispatching but 498 // forgets to resume. 499 newWindow.mToken.paused = false; 500 } 501 502 mInputFocus = newWindow; 503 setUpdateInputWindowsNeededLw(); 504 505 if (updateInputWindows) { 506 updateInputWindowsLw(false /*force*/); 507 } 508 } 509 } 510 setFocusedAppLw(AppWindowToken newApp)511 public void setFocusedAppLw(AppWindowToken newApp) { 512 // Focused app has changed. 513 if (newApp == null) { 514 mService.mInputManager.setFocusedApplication(null); 515 } else { 516 final InputApplicationHandle handle = newApp.mInputApplicationHandle; 517 handle.name = newApp.toString(); 518 handle.dispatchingTimeoutNanos = newApp.mInputDispatchingTimeoutNanos; 519 520 mService.mInputManager.setFocusedApplication(handle); 521 } 522 } 523 pauseDispatchingLw(WindowToken window)524 public void pauseDispatchingLw(WindowToken window) { 525 if (! window.paused) { 526 if (DEBUG_INPUT) { 527 Slog.v(TAG_WM, "Pausing WindowToken " + window); 528 } 529 530 window.paused = true; 531 updateInputWindowsLw(true /*force*/); 532 } 533 } 534 resumeDispatchingLw(WindowToken window)535 public void resumeDispatchingLw(WindowToken window) { 536 if (window.paused) { 537 if (DEBUG_INPUT) { 538 Slog.v(TAG_WM, "Resuming WindowToken " + window); 539 } 540 541 window.paused = false; 542 updateInputWindowsLw(true /*force*/); 543 } 544 } 545 freezeInputDispatchingLw()546 public void freezeInputDispatchingLw() { 547 if (!mInputDispatchFrozen) { 548 if (DEBUG_INPUT) { 549 Slog.v(TAG_WM, "Freezing input dispatching"); 550 } 551 552 mInputDispatchFrozen = true; 553 554 if (DEBUG_INPUT || true) { 555 mInputFreezeReason = Debug.getCallers(6); 556 } 557 updateInputDispatchModeLw(); 558 } 559 } 560 thawInputDispatchingLw()561 public void thawInputDispatchingLw() { 562 if (mInputDispatchFrozen) { 563 if (DEBUG_INPUT) { 564 Slog.v(TAG_WM, "Thawing input dispatching"); 565 } 566 567 mInputDispatchFrozen = false; 568 mInputFreezeReason = null; 569 updateInputDispatchModeLw(); 570 } 571 } 572 setEventDispatchingLw(boolean enabled)573 public void setEventDispatchingLw(boolean enabled) { 574 if (mInputDispatchEnabled != enabled) { 575 if (DEBUG_INPUT) { 576 Slog.v(TAG_WM, "Setting event dispatching to " + enabled); 577 } 578 579 mInputDispatchEnabled = enabled; 580 updateInputDispatchModeLw(); 581 } 582 } 583 updateInputDispatchModeLw()584 private void updateInputDispatchModeLw() { 585 mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen); 586 } 587 dump(PrintWriter pw, String prefix)588 void dump(PrintWriter pw, String prefix) { 589 if (mInputFreezeReason != null) { 590 pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason); 591 } 592 final Set<String> inputConsumerKeys = mInputConsumers.keySet(); 593 if (!inputConsumerKeys.isEmpty()) { 594 pw.println(prefix + "InputConsumers:"); 595 for (String key : inputConsumerKeys) { 596 pw.println(prefix + " name=" + key); 597 } 598 } 599 } 600 601 private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> { 602 603 InputConsumerImpl navInputConsumer; 604 InputConsumerImpl pipInputConsumer; 605 InputConsumerImpl wallpaperInputConsumer; 606 Rect pipTouchableBounds; 607 boolean inDrag; 608 WallpaperController wallpaperController; 609 updateInputWindows(boolean inDrag)610 private void updateInputWindows(boolean inDrag) { 611 612 // TODO: multi-display 613 navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY); 614 pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY); 615 wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY); 616 mAddInputConsumerHandle = navInputConsumer != null; 617 mAddPipInputConsumerHandle = pipInputConsumer != null; 618 mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null; 619 mTmpRect.setEmpty(); 620 pipTouchableBounds = mAddPipInputConsumerHandle ? mTmpRect : null; 621 mDisableWallpaperTouchEvents = false; 622 this.inDrag = inDrag; 623 wallpaperController = mService.mRoot.mWallpaperController; 624 625 mService.mRoot.forAllWindows(this, true /* traverseTopToBottom */); 626 if (mAddWallpaperInputConsumerHandle) { 627 // No visible wallpaper found, add the wallpaper input consumer at the end. 628 addInputWindowHandle(wallpaperInputConsumer.mWindowHandle); 629 } 630 631 // Send windows to native code. 632 mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle); 633 634 clearInputWindowHandlesLw(); 635 } 636 637 @Override accept(WindowState w)638 public void accept(WindowState w) { 639 final InputChannel inputChannel = w.mInputChannel; 640 final InputWindowHandle inputWindowHandle = w.mInputWindowHandle; 641 if (inputChannel == null || inputWindowHandle == null || w.mRemoved 642 || w.canReceiveTouchInput()) { 643 // Skip this window because it cannot possibly receive input. 644 return; 645 } 646 647 final int flags = w.mAttrs.flags; 648 final int privateFlags = w.mAttrs.privateFlags; 649 final int type = w.mAttrs.type; 650 final boolean hasFocus = w == mInputFocus; 651 final boolean isVisible = w.isVisibleLw(); 652 653 if (w.getStackId() == PINNED_STACK_ID) { 654 if (mAddPipInputConsumerHandle 655 && (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) { 656 // Update the bounds of the Pip input consumer to match the Pinned stack 657 w.getStack().getBounds(pipTouchableBounds); 658 pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds); 659 addInputWindowHandle(pipInputConsumer.mWindowHandle); 660 mAddPipInputConsumerHandle = false; 661 } 662 // TODO: Fix w.canReceiveTouchInput() to handle this case 663 if (!hasFocus) { 664 // Skip this pinned stack window if it does not have focus 665 return; 666 } 667 } 668 669 if (mAddInputConsumerHandle 670 && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) { 671 addInputWindowHandle(navInputConsumer.mWindowHandle); 672 mAddInputConsumerHandle = false; 673 } 674 675 if (mAddWallpaperInputConsumerHandle) { 676 if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) { 677 // Add the wallpaper input consumer above the first visible wallpaper. 678 addInputWindowHandle(wallpaperInputConsumer.mWindowHandle); 679 mAddWallpaperInputConsumerHandle = false; 680 } 681 } 682 683 if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) { 684 mDisableWallpaperTouchEvents = true; 685 } 686 final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w) 687 && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0 688 && !mDisableWallpaperTouchEvents; 689 690 // If there's a drag in progress and 'child' is a potential drop target, 691 // make sure it's been told about the drag 692 if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) { 693 mService.mDragState.sendDragStartedIfNeededLw(w); 694 } 695 696 addInputWindowHandle( 697 inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper); 698 } 699 } 700 } 701