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