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