Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a80ad04b authored by Robert Carr's avatar Robert Carr
Browse files

Port InputConsumerImpl to SurfaceFlinger input.

In the old system the InputConsumerImpl generated a handle
which was inserted after the appropriate window when building the list.
In the new system the InputConsumerImpl will need to manage a Surface
to assosciate this with. We hide all of them at the beginning of each Input pass
and show them again with a relative layer to the window they would have been
inserted after in the old logic. This resetting emulates the effect
of rebuilding the entire list every time.

Bug: 80101428
Bug: 113136004
Bug: 111440400
Change-Id: I387e16b82a76648d39f8cfc10cd5d30d4690275b
parent 679ccb01
Loading
Loading
Loading
Loading
+32 −6
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.wm;

import android.graphics.Rect;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
@@ -25,6 +26,8 @@ import android.view.WindowManager;

import android.view.InputApplicationHandle;
import android.view.InputWindowHandle;
import android.view.SurfaceControl;
import android.util.Slog;

import java.io.PrintWriter;

@@ -39,6 +42,9 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
    final int mClientPid;
    final UserHandle mClientUser;

    final SurfaceControl mInputSurface;
    Rect mTmpClipRect = new Rect();

    InputConsumerImpl(WindowManagerService service, IBinder token, String name,
            InputChannel inputChannel, int clientPid, UserHandle clientUser, int displayId) {
        mService = service;
@@ -80,6 +86,11 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
        mWindowHandle.ownerUid = Process.myUid();
        mWindowHandle.inputFeatures = 0;
        mWindowHandle.scaleFactor = 1.0f;

        mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId)
                .getSession()).setContainerLayer(true).setName("Input Consumer " + name)
                .setSize(1, 1)
                .build();
    }

    void linkToDeathRecipient() {
@@ -102,12 +113,27 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
        mToken.unlinkToDeath(this, 0);
    }

    void layout(int dw, int dh) {
        mWindowHandle.touchableRegion.set(0, 0, dw, dh);
        mWindowHandle.frameLeft = 0;
        mWindowHandle.frameTop = 0;
        mWindowHandle.frameRight = dw;
        mWindowHandle.frameBottom = dh;
    void layout(SurfaceControl.Transaction t, int dw, int dh) {
        t.setPosition(mInputSurface, 0, 0);

        mTmpClipRect.set(0, 0, dw, dh);
        t.setWindowCrop(mInputSurface, mTmpClipRect);
    }

    void layout(SurfaceControl.Transaction t, Rect r) {
        t.setPosition(mInputSurface, r.left, r.top);
        mTmpClipRect.set(0, 0, r.width(), r.height());
        t.setWindowCrop(mInputSurface, mTmpClipRect);
    }

    void hide(SurfaceControl.Transaction t) {
        t.hide(mInputSurface);
    }

    void show(SurfaceControl.Transaction t, WindowState w) {
        t.show(mInputSurface);
        t.setInputWindowInfo(mInputSurface, mWindowHandle);
        t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1);
    }

    private int getLayerLw(int windowType) {
+25 −16
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ final class InputMonitor {
    private boolean disposeInputConsumer(InputConsumerImpl consumer) {
        if (consumer != null) {
            consumer.disposeChannelsLw();
            consumer.hide(mInputTransaction);
            return true;
        }
        return false;
@@ -140,7 +141,16 @@ final class InputMonitor {

    void layoutInputConsumers(int dw, int dh) {
        for (int i = mInputConsumers.size() - 1; i >= 0; i--) {
            mInputConsumers.valueAt(i).layout(dw, dh);
            mInputConsumers.valueAt(i).layout(mInputTransaction, dw, dh);
        }
    }

    // The visibility of the input consumers is recomputed each time we
    // update the input windows. We use a model where consumers begin invisible
    // (set so by this function) and must meet some condition for visibility on each update.
    void resetInputConsumers(SurfaceControl.Transaction t) {
        for (int i = mInputConsumers.size() - 1; i >= 0; i--) {
            mInputConsumers.valueAt(i).hide(t);
        }
    }

@@ -398,7 +408,11 @@ final class InputMonitor {
            final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
            wallpaperController = dc.mWallpaperController;

            dc.forAllWindows(this, true /* traverseTopToBottom */);
            resetInputConsumers(mInputTransaction);

            dc.forAllWindows(this,
                    true /* traverseTopToBottom */);

            if (mAddWallpaperInputConsumerHandle) {
                // No visible wallpaper found, add the wallpaper input consumer at the end.
                addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
@@ -434,41 +448,36 @@ final class InputMonitor {
                        && recentsAnimationController.shouldApplyInputConsumer(w.mAppToken)) {
                    if (recentsAnimationController.updateInputConsumerForApp(
                            recentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
                        addInputWindowHandle(recentsAnimationInputConsumer.mWindowHandle);
                        recentsAnimationInputConsumer.show(mInputTransaction, w);
                        mAddRecentsAnimationInputConsumerHandle = false;
                    }
                    // If the target app window does not yet exist, then we don't add the input
                    // consumer window, but also don't add the app window below.
                    return;
                }
            }

            if (w.inPinnedWindowingMode()) {
                if (mAddPipInputConsumerHandle
                        && (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) {
                if (mAddPipInputConsumerHandle) {
                    // Update the bounds of the Pip input consumer to match the window bounds.
                    w.getBounds(mTmpRect);
                    // The touchable region is relative to the surface top-left
                    mTmpRect.top = mTmpRect.left = 0;

                    pipInputConsumer.layout(mInputTransaction, mTmpRect);
                    pipInputConsumer.mWindowHandle.touchableRegion.set(mTmpRect);
                    addInputWindowHandle(pipInputConsumer.mWindowHandle);
                    pipInputConsumer.show(mInputTransaction, w);
                    mAddPipInputConsumerHandle = false;
                }
                // TODO: Fix w.canReceiveTouchInput() to handle this case
                if (!hasFocus) {
                    // Skip this pinned stack window if it does not have focus
                    return;
                }
            }

            if (mAddInputConsumerHandle
                    && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
                addInputWindowHandle(navInputConsumer.mWindowHandle);
                navInputConsumer.show(mInputTransaction, w);
                mAddInputConsumerHandle = false;
            }

            if (mAddWallpaperInputConsumerHandle) {
                if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
                    // Add the wallpaper input consumer above the first visible wallpaper.
                    addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
                    wallpaperInputConsumer.show(mInputTransaction, w);
                    mAddWallpaperInputConsumerHandle = false;
                }
            }
+13 −2
Original line number Diff line number Diff line
@@ -2172,6 +2172,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            // Not modal or full screen modal
            getTouchableRegion(region);
        }

        // The area containing the shadows is not touchable.
        region.translate(mAttrs.surfaceInsets.left, mAttrs.surfaceInsets.top);

        return flags;
    }

@@ -2803,25 +2807,32 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }

    void getTouchableRegion(Region outRegion) {
        if (inPinnedWindowingMode() && !isFocused()) {
            outRegion.setEmpty();
            return;
        }

        final Rect frame = mWindowFrames.mFrame;
        switch (mTouchableInsets) {
            default:
            case TOUCHABLE_INSETS_FRAME:
                outRegion.set(frame);
                outRegion.translate(-frame.left, -frame.top);
                break;
            case TOUCHABLE_INSETS_CONTENT:
                applyInsets(outRegion, frame, mGivenContentInsets);
                outRegion.translate(-frame.left, -frame.top);
                break;
            case TOUCHABLE_INSETS_VISIBLE:
                applyInsets(outRegion, frame, mGivenVisibleInsets);
                outRegion.translate(-frame.left, -frame.top);
                break;
            case TOUCHABLE_INSETS_REGION: {
                outRegion.set(mGivenTouchableRegion);
                outRegion.translate(frame.left, frame.top);
                break;
            }
        }
        cropRegionToStackBoundsIfNeeded(outRegion);
        outRegion.translate(mAttrs.surfaceInsets.left, mAttrs.surfaceInsets.top);
    }

    private void cropRegionToStackBoundsIfNeeded(Region region) {