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

Commit a125784e authored by Robert Carr's avatar Robert Carr Committed by Rob Carr
Browse files

SurfaceFlinger: Cache updateInputWindows call

This is a conservative but safe cache. We invalidate it if
any layer with InputInfo, or any layer whose children/relative-children
have input info updates their drawing state. Not all these drawing state
updates will result in Input changes, but we can be confident that
without some drawing state change there wont be any Input changes,
and thus it seems the cache is safe. This will solve the case of
moving layers that don't have any InputInfo assosciated generating
setInputWindows calls.

Bug: 148675756
Test: Existing tests pass. go/wm-smoke
Change-Id: Ie5979b25370c2d5c3d8a55f187fc6fda1cc75b27
parent 10460043
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -485,6 +485,10 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
        }
    }

    if (recomputeVisibleRegions == true) {
        maybeDirtyInput();
    }

    return true;
}

+29 −0
Original line number Diff line number Diff line
@@ -993,6 +993,9 @@ uint32_t Layer::doTransaction(uint32_t flags) {
    commitTransaction(c);
    mPendingStatesSnapshot = mPendingStates;
    mCurrentState.callbackHandles = {};

    maybeDirtyInput();

    return flags;
}

@@ -2472,6 +2475,32 @@ Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t comp
    }
}

bool Layer::maybeDirtyInput() {
    // No sense redirtying input.
    if (mFlinger->inputDirty()) return true;

    if (hasInput()) {
        mFlinger->dirtyInput();
        return true;
    }

    // If a child or relative dirties the input, no sense continuing to traverse
    // so we return early and halt the recursion. We traverse ourselves instead
    // of using traverse() so we can implement this early halt.
    for (const sp<Layer>& child : mDrawingChildren) {
        if (child->maybeDirtyInput()) {
            return true;
        }
    }
    for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
        sp<Layer> relative = weakRelative.promote();
        if (relative && relative->maybeDirtyInput()) {
            return true;
        }
    }
    return false;
}

// ---------------------------------------------------------------------------

}; // namespace android
+4 −0
Original line number Diff line number Diff line
@@ -997,6 +997,10 @@ protected:
    // Window types from WindowManager.LayoutParams
    const int mWindowType;

    // Called when mDrawingState has changed. If we or one of our children/relatives hasInput()
    // then we will dirty the setInputWindows cache.
    bool maybeDirtyInput();

private:
    /**
     * Returns an unsorted vector of all layers that are part of this tree.
+15 −0
Original line number Diff line number Diff line
@@ -2769,6 +2769,19 @@ void SurfaceFlinger::updateInputFlinger() {
void SurfaceFlinger::updateInputWindowInfo() {
    std::vector<InputWindowInfo> inputHandles;

    // We use a simple caching algorithm here. mInputDirty begins as true,
    // after we call setInputWindows we set it to false, so
    // in the future we wont call it again.. We set input dirty to true again
    // when any layer that hasInput() has a transaction performed on it
    // or when any parent or relative parent of such a layer has a transaction
    // performed on it. Not all of these transactions will really result in
    // input changes but all input changes will spring from these transactions
    // so the cache is safe but not optimal. It seems like it might be annoyingly
    // costly to cache and comapre the actual InputWindowHandle vector though.
    if (!mInputDirty) {
        return;
    }

    mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
        if (layer->hasInput()) {
            // When calculating the screen bounds we ignore the transparent region since it may
@@ -2780,6 +2793,8 @@ void SurfaceFlinger::updateInputWindowInfo() {
    mInputFlinger->setInputWindows(inputHandles,
                                   mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
                                                                         : nullptr);

    mInputDirty = false;
}

void SurfaceFlinger::commitInputWindowCommands() {
+5 −0
Original line number Diff line number Diff line
@@ -1236,6 +1236,11 @@ private:
    // janky frames there are.
    nsecs_t mMissedFrameJankStart = 0;
    int32_t mMissedFrameJankCount = 0;

    // See updateInputWindowInfo() for details
    std::atomic<bool> mInputDirty = true;
    void dirtyInput() { mInputDirty = true; }
    bool inputDirty() { return mInputDirty; }
};

} // namespace android