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