OSDN Git Service

Correctly blame ANR on process using another process token
[android-x86/frameworks-base.git] / services / core / java / com / android / server / wm / InputMonitor.java
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
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
118         public void dismiss() {
119             synchronized (mService.mWindowMap) {
120                 if (mInputMonitor.destroyInputConsumer(mWindowHandle.name)) {
121                     mInputEventReceiver.dispose();
122                 }
123             }
124         }
125     }
126
127     public InputMonitor(WindowManagerService service) {
128         mService = service;
129     }
130
131     private void addInputConsumer(String name, InputConsumerImpl consumer) {
132         mInputConsumers.put(name, consumer);
133         updateInputWindowsLw(true /* force */);
134     }
135
136     boolean destroyInputConsumer(String name) {
137         if (disposeInputConsumer(mInputConsumers.remove(name))) {
138             updateInputWindowsLw(true /* force */);
139             return true;
140         }
141         return false;
142     }
143
144     private boolean disposeInputConsumer(InputConsumerImpl consumer) {
145         if (consumer != null) {
146             consumer.disposeChannelsLw();
147             return true;
148         }
149         return false;
150     }
151
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
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
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
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
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
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         if (appWindowToken != null && appWindowToken.appToken != null) {
258             // Notify the activity manager about the timeout and let it decide whether
259             // to abort dispatching or keep waiting.
260             final AppWindowContainerController controller = appWindowToken.getController();
261             final boolean abort = controller != null
262                     && controller.keyDispatchingTimedOut(reason, windowState.mSession.mPid);
263             if (!abort) {
264                 // The activity manager declined to abort dispatching.
265                 // Wait a bit longer and timeout again later.
266                 return appWindowToken.mInputDispatchingTimeoutNanos;
267             }
268         } else if (windowState != null) {
269             try {
270                 // Notify the activity manager about the timeout and let it decide whether
271                 // to abort dispatching or keep waiting.
272                 long timeout = ActivityManager.getService().inputDispatchingTimedOut(
273                         windowState.mSession.mPid, aboveSystem, reason);
274                 if (timeout >= 0) {
275                     // The activity manager declined to abort dispatching.
276                     // Wait a bit longer and timeout again later.
277                     return timeout * 1000000L; // nanoseconds
278                 }
279             } catch (RemoteException ex) {
280             }
281         }
282         return 0; // abort dispatching
283     }
284
285     private void addInputWindowHandle(final InputWindowHandle windowHandle) {
286         if (mInputWindowHandles == null) {
287             mInputWindowHandles = new InputWindowHandle[16];
288         }
289         if (mInputWindowHandleCount >= mInputWindowHandles.length) {
290             mInputWindowHandles = Arrays.copyOf(mInputWindowHandles,
291                     mInputWindowHandleCount * 2);
292         }
293         mInputWindowHandles[mInputWindowHandleCount++] = windowHandle;
294     }
295
296     void addInputWindowHandle(final InputWindowHandle inputWindowHandle,
297             final WindowState child, int flags, final int type, final boolean isVisible,
298             final boolean hasFocus, final boolean hasWallpaper) {
299         // Add a window to our list of input windows.
300         inputWindowHandle.name = child.toString();
301         flags = child.getTouchableRegion(inputWindowHandle.touchableRegion, flags);
302         inputWindowHandle.layoutParamsFlags = flags;
303         inputWindowHandle.layoutParamsType = type;
304         inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
305         inputWindowHandle.visible = isVisible;
306         inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
307         inputWindowHandle.hasFocus = hasFocus;
308         inputWindowHandle.hasWallpaper = hasWallpaper;
309         inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
310         inputWindowHandle.layer = child.mLayer;
311         inputWindowHandle.ownerPid = child.mSession.mPid;
312         inputWindowHandle.ownerUid = child.mSession.mUid;
313         inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
314
315         final Rect frame = child.mFrame;
316         inputWindowHandle.frameLeft = frame.left;
317         inputWindowHandle.frameTop = frame.top;
318         inputWindowHandle.frameRight = frame.right;
319         inputWindowHandle.frameBottom = frame.bottom;
320
321         if (child.mGlobalScale != 1) {
322             // If we are scaling the window, input coordinates need
323             // to be inversely scaled to map from what is on screen
324             // to what is actually being touched in the UI.
325             inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale;
326         } else {
327             inputWindowHandle.scaleFactor = 1;
328         }
329
330         if (DEBUG_INPUT) {
331             Slog.d(TAG_WM, "addInputWindowHandle: "
332                     + child + ", " + inputWindowHandle);
333         }
334         addInputWindowHandle(inputWindowHandle);
335         if (hasFocus) {
336             mFocusedInputWindowHandle = inputWindowHandle;
337         }
338     }
339
340     private void clearInputWindowHandlesLw() {
341         while (mInputWindowHandleCount != 0) {
342             mInputWindowHandles[--mInputWindowHandleCount] = null;
343         }
344         mFocusedInputWindowHandle = null;
345     }
346
347     void setUpdateInputWindowsNeededLw() {
348         mUpdateInputWindowsNeeded = true;
349     }
350
351     /* Updates the cached window information provided to the input dispatcher. */
352     void updateInputWindowsLw(boolean force) {
353         if (!force && !mUpdateInputWindowsNeeded) {
354             return;
355         }
356         mUpdateInputWindowsNeeded = false;
357
358         if (false) Slog.d(TAG_WM, ">>>>>> ENTERED updateInputWindowsLw");
359
360         // Populate the input window list with information about all of the windows that
361         // could potentially receive input.
362         // As an optimization, we could try to prune the list of windows but this turns
363         // out to be difficult because only the native code knows for sure which window
364         // currently has touch focus.
365
366         // If there's a drag in flight, provide a pseudo-window to catch drag input
367         final boolean inDrag = (mService.mDragState != null);
368         if (inDrag) {
369             if (DEBUG_DRAG) {
370                 Log.d(TAG_WM, "Inserting drag window");
371             }
372             final InputWindowHandle dragWindowHandle = mService.mDragState.getInputWindowHandle();
373             if (dragWindowHandle != null) {
374                 addInputWindowHandle(dragWindowHandle);
375             } else {
376                 Slog.w(TAG_WM, "Drag is in progress but there is no "
377                         + "drag window handle.");
378             }
379         }
380
381         final boolean inPositioning = (mService.mTaskPositioner != null);
382         if (inPositioning) {
383             if (DEBUG_TASK_POSITIONING) {
384                 Log.d(TAG_WM, "Inserting window handle for repositioning");
385             }
386             final InputWindowHandle dragWindowHandle = mService.mTaskPositioner.mDragWindowHandle;
387             if (dragWindowHandle != null) {
388                 addInputWindowHandle(dragWindowHandle);
389             } else {
390                 Slog.e(TAG_WM,
391                         "Repositioning is in progress but there is no drag window handle.");
392             }
393         }
394
395         // Add all windows on the default display.
396         mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
397
398         if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
399     }
400
401     /* Notifies that the input device configuration has changed. */
402     @Override
403     public void notifyConfigurationChanged() {
404         // TODO(multi-display): Notify proper displays that are associated with this input device.
405         mService.sendNewConfiguration(DEFAULT_DISPLAY);
406
407         synchronized (mInputDevicesReadyMonitor) {
408             if (!mInputDevicesReady) {
409                 mInputDevicesReady = true;
410                 mInputDevicesReadyMonitor.notifyAll();
411             }
412         }
413     }
414
415     /* Waits until the built-in input devices have been configured. */
416     public boolean waitForInputDevicesReady(long timeoutMillis) {
417         synchronized (mInputDevicesReadyMonitor) {
418             if (!mInputDevicesReady) {
419                 try {
420                     mInputDevicesReadyMonitor.wait(timeoutMillis);
421                 } catch (InterruptedException ex) {
422                 }
423             }
424             return mInputDevicesReady;
425         }
426     }
427
428     /* Notifies that the lid switch changed state. */
429     @Override
430     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
431         mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
432     }
433
434     /* Notifies that the camera lens cover state has changed. */
435     @Override
436     public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
437         mService.mPolicy.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
438     }
439
440     /* Provides an opportunity for the window manager policy to intercept early key
441      * processing as soon as the key has been read from the device. */
442     @Override
443     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
444         return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
445     }
446
447     /* Provides an opportunity for the window manager policy to intercept early motion event
448      * processing when the device is in a non-interactive state since these events are normally
449      * dropped. */
450     @Override
451     public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
452         return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive(
453                 whenNanos, policyFlags);
454     }
455
456     /* Provides an opportunity for the window manager policy to process a key before
457      * ordinary dispatch. */
458     @Override
459     public long interceptKeyBeforeDispatching(
460             InputWindowHandle focus, KeyEvent event, int policyFlags) {
461         WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
462         return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
463     }
464
465     /* Provides an opportunity for the window manager policy to process a key that
466      * the application did not handle. */
467     @Override
468     public KeyEvent dispatchUnhandledKey(
469             InputWindowHandle focus, KeyEvent event, int policyFlags) {
470         WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
471         return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
472     }
473
474     /* Callback to get pointer layer. */
475     @Override
476     public int getPointerLayer() {
477         return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER)
478                 * WindowManagerService.TYPE_LAYER_MULTIPLIER
479                 + WindowManagerService.TYPE_LAYER_OFFSET;
480     }
481
482     /* Called when the current input focus changes.
483      * Layer assignment is assumed to be complete by the time this is called.
484      */
485     public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
486         if (DEBUG_FOCUS_LIGHT || DEBUG_INPUT) {
487             Slog.d(TAG_WM, "Input focus has changed to " + newWindow);
488         }
489
490         if (newWindow != mInputFocus) {
491             if (newWindow != null && newWindow.canReceiveKeys()) {
492                 // Displaying a window implicitly causes dispatching to be unpaused.
493                 // This is to protect against bugs if someone pauses dispatching but
494                 // forgets to resume.
495                 newWindow.mToken.paused = false;
496             }
497
498             mInputFocus = newWindow;
499             setUpdateInputWindowsNeededLw();
500
501             if (updateInputWindows) {
502                 updateInputWindowsLw(false /*force*/);
503             }
504         }
505     }
506
507     public void setFocusedAppLw(AppWindowToken newApp) {
508         // Focused app has changed.
509         if (newApp == null) {
510             mService.mInputManager.setFocusedApplication(null);
511         } else {
512             final InputApplicationHandle handle = newApp.mInputApplicationHandle;
513             handle.name = newApp.toString();
514             handle.dispatchingTimeoutNanos = newApp.mInputDispatchingTimeoutNanos;
515
516             mService.mInputManager.setFocusedApplication(handle);
517         }
518     }
519
520     public void pauseDispatchingLw(WindowToken window) {
521         if (! window.paused) {
522             if (DEBUG_INPUT) {
523                 Slog.v(TAG_WM, "Pausing WindowToken " + window);
524             }
525
526             window.paused = true;
527             updateInputWindowsLw(true /*force*/);
528         }
529     }
530
531     public void resumeDispatchingLw(WindowToken window) {
532         if (window.paused) {
533             if (DEBUG_INPUT) {
534                 Slog.v(TAG_WM, "Resuming WindowToken " + window);
535             }
536
537             window.paused = false;
538             updateInputWindowsLw(true /*force*/);
539         }
540     }
541
542     public void freezeInputDispatchingLw() {
543         if (!mInputDispatchFrozen) {
544             if (DEBUG_INPUT) {
545                 Slog.v(TAG_WM, "Freezing input dispatching");
546             }
547
548             mInputDispatchFrozen = true;
549
550             if (DEBUG_INPUT || true) {
551                 mInputFreezeReason = Debug.getCallers(6);
552             }
553             updateInputDispatchModeLw();
554         }
555     }
556
557     public void thawInputDispatchingLw() {
558         if (mInputDispatchFrozen) {
559             if (DEBUG_INPUT) {
560                 Slog.v(TAG_WM, "Thawing input dispatching");
561             }
562
563             mInputDispatchFrozen = false;
564             mInputFreezeReason = null;
565             updateInputDispatchModeLw();
566         }
567     }
568
569     public void setEventDispatchingLw(boolean enabled) {
570         if (mInputDispatchEnabled != enabled) {
571             if (DEBUG_INPUT) {
572                 Slog.v(TAG_WM, "Setting event dispatching to " + enabled);
573             }
574
575             mInputDispatchEnabled = enabled;
576             updateInputDispatchModeLw();
577         }
578     }
579
580     private void updateInputDispatchModeLw() {
581         mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
582     }
583
584     void dump(PrintWriter pw, String prefix) {
585         if (mInputFreezeReason != null) {
586             pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason);
587         }
588         final Set<String> inputConsumerKeys = mInputConsumers.keySet();
589         if (!inputConsumerKeys.isEmpty()) {
590             pw.println(prefix + "InputConsumers:");
591             for (String key : inputConsumerKeys) {
592                 pw.println(prefix + "  name=" + key);
593             }
594         }
595     }
596
597     private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
598
599         InputConsumerImpl navInputConsumer;
600         InputConsumerImpl pipInputConsumer;
601         InputConsumerImpl wallpaperInputConsumer;
602         Rect pipTouchableBounds;
603         boolean inDrag;
604         WallpaperController wallpaperController;
605
606         private void updateInputWindows(boolean inDrag) {
607
608             // TODO: multi-display
609             navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY);
610             pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY);
611             wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY);
612             mAddInputConsumerHandle = navInputConsumer != null;
613             mAddPipInputConsumerHandle = pipInputConsumer != null;
614             mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
615             mTmpRect.setEmpty();
616             pipTouchableBounds = mAddPipInputConsumerHandle ? mTmpRect : null;
617             mDisableWallpaperTouchEvents = false;
618             this.inDrag = inDrag;
619             wallpaperController = mService.mRoot.mWallpaperController;
620
621             mService.mRoot.forAllWindows(this, true /* traverseTopToBottom */);
622             if (mAddWallpaperInputConsumerHandle) {
623                 // No visible wallpaper found, add the wallpaper input consumer at the end.
624                 addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
625             }
626
627             // Send windows to native code.
628             mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle);
629
630             clearInputWindowHandlesLw();
631         }
632
633         @Override
634         public void accept(WindowState w) {
635             final InputChannel inputChannel = w.mInputChannel;
636             final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
637             if (inputChannel == null || inputWindowHandle == null || w.mRemoved
638                     || w.canReceiveTouchInput()) {
639                 // Skip this window because it cannot possibly receive input.
640                 return;
641             }
642
643             final int flags = w.mAttrs.flags;
644             final int privateFlags = w.mAttrs.privateFlags;
645             final int type = w.mAttrs.type;
646             final boolean hasFocus = w == mInputFocus;
647             final boolean isVisible = w.isVisibleLw();
648
649             if (w.getStackId() == PINNED_STACK_ID) {
650                 if (mAddPipInputConsumerHandle
651                         && (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) {
652                     // Update the bounds of the Pip input consumer to match the Pinned stack
653                     w.getStack().getBounds(pipTouchableBounds);
654                     pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
655                     addInputWindowHandle(pipInputConsumer.mWindowHandle);
656                     mAddPipInputConsumerHandle = false;
657                 }
658                 // TODO: Fix w.canReceiveTouchInput() to handle this case
659                 if (!hasFocus) {
660                     // Skip this pinned stack window if it does not have focus
661                     return;
662                 }
663             }
664
665             if (mAddInputConsumerHandle
666                     && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
667                 addInputWindowHandle(navInputConsumer.mWindowHandle);
668                 mAddInputConsumerHandle = false;
669             }
670
671             if (mAddWallpaperInputConsumerHandle) {
672                 if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
673                     // Add the wallpaper input consumer above the first visible wallpaper.
674                     addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
675                     mAddWallpaperInputConsumerHandle = false;
676                 }
677             }
678
679             if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
680                 mDisableWallpaperTouchEvents = true;
681             }
682             final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w)
683                     && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
684                     && !mDisableWallpaperTouchEvents;
685
686             // If there's a drag in progress and 'child' is a potential drop target,
687             // make sure it's been told about the drag
688             if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
689                 mService.mDragState.sendDragStartedIfNeededLw(w);
690             }
691
692             addInputWindowHandle(
693                     inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
694         }
695     }
696 }