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