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

Commit edd96400 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Support ANRs from windows that are not tracked by WM

Previously, ANRs for gesture monitors were reported using the pid of the
owner, and ANRs for all windows were reported using its input channel,
which was tracked by WM.

Now, there can be input windows that are not tracked by WM. We unify the
ANR reporting pipeline so that we first try to report an ANR using the
window's input channel. If the ANR reporting fails because the input
channel was not tracked by WM, we fall back on reporting ANR via the
pid of the window owner.

Bug: 210978621
Test: atest inputflinger_tests
Change-Id: I7f71186e042b0fc9df7d342a549ef609ff4862ae
Merged-In: I7f71186e042b0fc9df7d342a549ef609ff4862ae
parent e73b8065
Loading
Loading
Loading
Loading
+3 −8
Original line number Diff line number Diff line
@@ -61,18 +61,13 @@ private:
        ALOGE("There is no focused window for %s", applicationHandle->getName().c_str());
    }

    void notifyWindowUnresponsive(const sp<IBinder>& connectionToken,
    void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
                                  const std::string& reason) override {
        ALOGE("Window is not responding: %s", reason.c_str());
    }

    void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {}

    void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) override {
        ALOGE("Monitor is not responding: %s", reason.c_str());
    }

    void notifyMonitorResponsive(int32_t pid) override {}
    void notifyWindowResponsive(const sp<IBinder>& connectionToken,
                                std::optional<int32_t> pid) override {}

    void notifyInputChannelBroken(const sp<IBinder>&) override {}

+25 −41
Original line number Diff line number Diff line
@@ -5816,35 +5816,21 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingCommand(const sp<IBinder>&
    }
}

void InputDispatcher::sendMonitorUnresponsiveCommandLocked(int32_t pid, std::string reason) {
    auto command = [this, pid, reason = std::move(reason)]() REQUIRES(mLock) {
        scoped_unlock unlock(mLock);
        mPolicy->notifyMonitorUnresponsive(pid, reason);
    };
    postCommandLocked(std::move(command));
}

void InputDispatcher::sendWindowUnresponsiveCommandLocked(const sp<IBinder>& token,
                                                          std::optional<int32_t> pid,
                                                          std::string reason) {
    auto command = [this, token, reason = std::move(reason)]() REQUIRES(mLock) {
        scoped_unlock unlock(mLock);
        mPolicy->notifyWindowUnresponsive(token, reason);
    };
    postCommandLocked(std::move(command));
}

void InputDispatcher::sendMonitorResponsiveCommandLocked(int32_t pid) {
    auto command = [this, pid]() REQUIRES(mLock) {
    auto command = [this, token, pid, reason = std::move(reason)]() REQUIRES(mLock) {
        scoped_unlock unlock(mLock);
        mPolicy->notifyMonitorResponsive(pid);
        mPolicy->notifyWindowUnresponsive(token, pid, reason);
    };
    postCommandLocked(std::move(command));
}

void InputDispatcher::sendWindowResponsiveCommandLocked(const sp<IBinder>& connectionToken) {
    auto command = [this, connectionToken]() REQUIRES(mLock) {
void InputDispatcher::sendWindowResponsiveCommandLocked(const sp<IBinder>& token,
                                                        std::optional<int32_t> pid) {
    auto command = [this, token, pid]() REQUIRES(mLock) {
        scoped_unlock unlock(mLock);
        mPolicy->notifyWindowResponsive(connectionToken);
        mPolicy->notifyWindowResponsive(token, pid);
    };
    postCommandLocked(std::move(command));
}
@@ -5857,22 +5843,21 @@ void InputDispatcher::sendWindowResponsiveCommandLocked(const sp<IBinder>& conne
void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& connection,
                                                          std::string reason) {
    const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken();
    std::optional<int32_t> pid;
    if (connection.monitor) {
        ALOGW("Monitor %s is unresponsive: %s", connection.inputChannel->getName().c_str(),
              reason.c_str());
        std::optional<int32_t> pid = findMonitorPidByTokenLocked(connectionToken);
        if (!pid.has_value()) {
            ALOGE("Could not find unresponsive monitor for connection %s",
                  connection.inputChannel->getName().c_str());
            return;
        }
        sendMonitorUnresponsiveCommandLocked(pid.value(), std::move(reason));
        return;
    }
    // If not a monitor, must be a window
        pid = findMonitorPidByTokenLocked(connectionToken);
    } else {
        // The connection is a window
        ALOGW("Window %s is unresponsive: %s", connection.inputChannel->getName().c_str(),
              reason.c_str());
    sendWindowUnresponsiveCommandLocked(connectionToken, std::move(reason));
        const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken);
        if (handle != nullptr) {
            pid = handle->getInfo()->ownerPid;
        }
    }
    sendWindowUnresponsiveCommandLocked(connectionToken, pid, std::move(reason));
}

/**
@@ -5880,18 +5865,17 @@ void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& conn
 */
void InputDispatcher::processConnectionResponsiveLocked(const Connection& connection) {
    const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken();
    std::optional<int32_t> pid;
    if (connection.monitor) {
        std::optional<int32_t> pid = findMonitorPidByTokenLocked(connectionToken);
        if (!pid.has_value()) {
            ALOGE("Could not find responsive monitor for connection %s",
                  connection.inputChannel->getName().c_str());
            return;
        pid = findMonitorPidByTokenLocked(connectionToken);
    } else {
        // The connection is a window
        const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken);
        if (handle != nullptr) {
            pid = handle->getInfo()->ownerPid;
        }
        sendMonitorResponsiveCommandLocked(pid.value());
        return;
    }
    // If not a monitor, must be a window
    sendWindowResponsiveCommandLocked(connectionToken);
    sendWindowResponsiveCommandLocked(connectionToken, pid);
}

bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& connection,
+4 −4
Original line number Diff line number Diff line
@@ -503,11 +503,11 @@ private:
     */
    void processConnectionResponsiveLocked(const Connection& connection) REQUIRES(mLock);

    void sendMonitorUnresponsiveCommandLocked(int32_t pid, std::string reason) REQUIRES(mLock);
    void sendWindowUnresponsiveCommandLocked(const sp<IBinder>& connectionToken, std::string reason)
    void sendWindowUnresponsiveCommandLocked(const sp<IBinder>& connectionToken,
                                             std::optional<int32_t> pid, std::string reason)
            REQUIRES(mLock);
    void sendMonitorResponsiveCommandLocked(int32_t pid) REQUIRES(mLock);
    void sendWindowResponsiveCommandLocked(const sp<IBinder>& connectionToken) REQUIRES(mLock);
    void sendWindowResponsiveCommandLocked(const sp<IBinder>& connectionToken,
                                           std::optional<int32_t> pid) REQUIRES(mLock);

    // Optimization: AnrTracker is used to quickly find which connection is due for a timeout next.
    // AnrTracker must be kept in-sync with all responsive connection.waitQueues.
+6 −17
Original line number Diff line number Diff line
@@ -51,30 +51,19 @@ public:
            const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) = 0;

    /* Notifies the system that a window just became unresponsive. This indicates that ANR
     * should be raised for this window. The window is identified via token.
     * The string reason contains information about the input event that we haven't received
     * a response for.
     * should be raised for this window. The window can be identified via its input token and the
     * pid of the owner. The string reason contains information about the input event that we
     * haven't received a response for.
     */
    virtual void notifyWindowUnresponsive(const sp<IBinder>& token, const std::string& reason) = 0;
    /* Notifies the system that a monitor just became unresponsive. This indicates that ANR
     * should be raised for this monitor. The monitor is identified via its pid.
     * The string reason contains information about the input event that we haven't received
     * a response for.
     */
    virtual void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) = 0;
    virtual void notifyWindowUnresponsive(const sp<IBinder>& token, std::optional<int32_t> pid,
                                          const std::string& reason) = 0;

    /* Notifies the system that a window just became responsive. This is only called after the
     * window was first marked "unresponsive". This indicates that ANR dialog (if any) should
     * no longer should be shown to the user. The window is eligible to cause a new ANR in the
     * future.
     */
    virtual void notifyWindowResponsive(const sp<IBinder>& token) = 0;
    /* Notifies the system that a monitor just became responsive. This is only called after the
     * monitor was first marked "unresponsive". This indicates that ANR dialog (if any) should
     * no longer should be shown to the user. The monitor is eligible to cause a new ANR in the
     * future.
     */
    virtual void notifyMonitorResponsive(int32_t pid) = 0;
    virtual void notifyWindowResponsive(const sp<IBinder>& token, std::optional<int32_t> pid) = 0;

    /* Notifies the system that an input channel is unrecoverably broken. */
    virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
+132 −134

File changed.

Preview size limit exceeded, changes collapsed.