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