/* Updates the cached window information provided to the input dispatcher. */
  public void updateInputWindowsLw(boolean force) {
    if (!force && !mUpdateInputWindowsNeeded) {
      return;
    }
    mUpdateInputWindowsNeeded = false;

    if (false) Slog.d(TAG_WM, ">>>>>> ENTERED updateInputWindowsLw");

    // Populate the input window list with information about all of the windows that
    // could potentially receive input.
    // As an optimization, we could try to prune the list of windows but this turns
    // out to be difficult because only the native code knows for sure which window
    // currently has touch focus.
    boolean disableWallpaperTouchEvents = false;

    // If there's a drag in flight, provide a pseudowindow to catch drag input
    final boolean inDrag = (mService.mDragState != null);
    if (inDrag) {
      if (DEBUG_DRAG) {
        Log.d(TAG_WM, "Inserting drag window");
      }
      final InputWindowHandle dragWindowHandle = mService.mDragState.mDragWindowHandle;
      if (dragWindowHandle != null) {
        addInputWindowHandleLw(dragWindowHandle);
      } else {
        Slog.w(TAG_WM, "Drag is in progress but there is no " + "drag window handle.");
      }
    }

    final boolean inPositioning = (mService.mTaskPositioner != null);
    if (inPositioning) {
      if (DEBUG_TASK_POSITIONING) {
        Log.d(TAG_WM, "Inserting window handle for repositioning");
      }
      final InputWindowHandle dragWindowHandle = mService.mTaskPositioner.mDragWindowHandle;
      if (dragWindowHandle != null) {
        addInputWindowHandleLw(dragWindowHandle);
      } else {
        Slog.e(TAG_WM, "Repositioning is in progress but there is no drag window handle.");
      }
    }

    boolean addInputConsumerHandle = mService.mInputConsumer != null;

    boolean addWallpaperInputConsumerHandle = mService.mWallpaperInputConsumer != null;

    // Add all windows on the default display.
    final int numDisplays = mService.mDisplayContents.size();
    final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
    for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
      final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
      final WindowList windows = displayContent.getWindowList();
      for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
        final WindowState child = windows.get(winNdx);
        final InputChannel inputChannel = child.mInputChannel;
        final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
        if (inputChannel == null
            || inputWindowHandle == null
            || child.mRemoved
            || child.isAdjustedForMinimizedDock()) {
          // Skip this window because it cannot possibly receive input.
          continue;
        }
        if (addInputConsumerHandle
            && inputWindowHandle.layer <= mService.mInputConsumer.mWindowHandle.layer) {
          addInputWindowHandleLw(mService.mInputConsumer.mWindowHandle);
          addInputConsumerHandle = false;
        }

        if (addWallpaperInputConsumerHandle) {
          if (child.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER) {
            // Add the wallpaper input consumer above the first wallpaper window.
            addInputWindowHandleLw(mService.mWallpaperInputConsumer.mWindowHandle);
            addWallpaperInputConsumerHandle = false;
          }
        }

        final int flags = child.mAttrs.flags;
        final int privateFlags = child.mAttrs.privateFlags;
        final int type = child.mAttrs.type;

        final boolean hasFocus = (child == mInputFocus);
        final boolean isVisible = child.isVisibleLw();
        if ((privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS)
            != 0) {
          disableWallpaperTouchEvents = true;
        }
        final boolean hasWallpaper =
            wallpaperController.isWallpaperTarget(child)
                && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0
                && !disableWallpaperTouchEvents;
        final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);

        // If there's a drag in progress and 'child' is a potential drop target,
        // make sure it's been told about the drag
        if (inDrag && isVisible && onDefaultDisplay) {
          mService.mDragState.sendDragStartedIfNeededLw(child);
        }

        addInputWindowHandleLw(
            inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
      }
    }

    if (addWallpaperInputConsumerHandle) {
      // No wallpaper found, add the wallpaper input consumer at the end.
      addInputWindowHandleLw(mService.mWallpaperInputConsumer.mWindowHandle);
    }

    // Send windows to native code.
    mService.mInputManager.setInputWindows(mInputWindowHandles);

    // Clear the list in preparation for the next round.
    clearInputWindowHandlesLw();

    if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
  }
  /* Updates the cached window information provided to the input dispatcher. */
  public void updateInputWindowsLw(boolean force) {
    if (!force && !mUpdateInputWindowsNeeded) {
      return;
    }
    mUpdateInputWindowsNeeded = false;

    if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED updateInputWindowsLw");

    // Populate the input window list with information about all of the windows that
    // could potentially receive input.
    // As an optimization, we could try to prune the list of windows but this turns
    // out to be difficult because only the native code knows for sure which window
    // currently has touch focus.
    final ArrayList<WindowState> windows = mService.mWindows;

    // If there's a drag in flight, provide a pseudowindow to catch drag input
    final boolean inDrag = (mService.mDragState != null);
    if (inDrag) {
      if (WindowManagerService.DEBUG_DRAG) {
        Log.d(WindowManagerService.TAG, "Inserting drag window");
      }
      final InputWindowHandle dragWindowHandle = mService.mDragState.mDragWindowHandle;
      if (dragWindowHandle != null) {
        addInputWindowHandleLw(dragWindowHandle);
      } else {
        Slog.w(
            WindowManagerService.TAG,
            "Drag is in progress but there is no " + "drag window handle.");
      }
    }

    final int NFW = mService.mFakeWindows.size();
    for (int i = 0; i < NFW; i++) {
      addInputWindowHandleLw(mService.mFakeWindows.get(i).mWindowHandle);
    }

    final int N = windows.size();
    for (int i = N - 1; i >= 0; i--) {
      final WindowState child = windows.get(i);
      final InputChannel inputChannel = child.mInputChannel;
      final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
      if (inputChannel == null || inputWindowHandle == null || child.mRemoved) {
        // Skip this window because it cannot possibly receive input.
        continue;
      }

      final int flags = child.mAttrs.flags;
      final int type = child.mAttrs.type;

      final boolean hasFocus = (child == mInputFocus);
      final boolean isVisible = child.isVisibleLw();
      final boolean hasWallpaper =
          (child == mService.mWallpaperTarget)
              && (type != WindowManager.LayoutParams.TYPE_KEYGUARD);

      // If there's a drag in progress and 'child' is a potential drop target,
      // make sure it's been told about the drag
      if (inDrag && isVisible) {
        mService.mDragState.sendDragStartedIfNeededLw(child);
      }

      // Add a window to our list of input windows.
      inputWindowHandle.name = child.toString();
      inputWindowHandle.layoutParamsFlags = flags;
      inputWindowHandle.layoutParamsType = type;
      inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
      inputWindowHandle.visible = isVisible;
      inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
      inputWindowHandle.hasFocus = hasFocus;
      inputWindowHandle.hasWallpaper = hasWallpaper;
      inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
      inputWindowHandle.layer = child.mLayer;
      inputWindowHandle.ownerPid = child.mSession.mPid;
      inputWindowHandle.ownerUid = child.mSession.mUid;
      inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;

      final Rect frame = child.mFrame;
      inputWindowHandle.frameLeft = frame.left;
      inputWindowHandle.frameTop = frame.top;
      inputWindowHandle.frameRight = frame.right;
      inputWindowHandle.frameBottom = frame.bottom;

      if (child.mGlobalScale != 1) {
        // If we are scaling the window, input coordinates need
        // to be inversely scaled to map from what is on screen
        // to what is actually being touched in the UI.
        inputWindowHandle.scaleFactor = 1.0f / child.mGlobalScale;
      } else {
        inputWindowHandle.scaleFactor = 1;
      }

      child.getTouchableRegion(inputWindowHandle.touchableRegion);

      addInputWindowHandleLw(inputWindowHandle);
    }

    // Send windows to native code.
    mService.mInputManager.setInputWindows(mInputWindowHandles);

    // Clear the list in preparation for the next round.
    clearInputWindowHandlesLw();

    if (false) Slog.d(WindowManagerService.TAG, "<<<<<<< EXITED updateInputWindowsLw");
  }