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

Commit 1815557f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Ensure setFocusedApplication resets no focused window timeout"

parents 0ede4cdd e41c4518
Loading
Loading
Loading
Loading
+26 −18
Original line number Diff line number Diff line
@@ -364,6 +364,17 @@ const char* InputDispatcher::typeToString(InputDispatcher::FocusResult result) {
    }
}

template <typename T>
static bool sharedPointersEqual(const std::shared_ptr<T>& lhs, const std::shared_ptr<T>& rhs) {
    if (lhs == nullptr && rhs == nullptr) {
        return true;
    }
    if (lhs == nullptr || rhs == nullptr) {
        return false;
    }
    return *lhs == *rhs;
}

// --- InputDispatcher ---

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
@@ -3885,31 +3896,26 @@ void InputDispatcher::setFocusedApplication(
        ALOGD("setFocusedApplication displayId=%" PRId32 " %s", displayId,
              inputApplicationHandle ? inputApplicationHandle->getName().c_str() : "<nullptr>");
    }
    if (inputApplicationHandle != nullptr &&
        inputApplicationHandle->getApplicationToken() != nullptr) {
        // acquire lock
    { // acquire lock
        std::scoped_lock _l(mLock);

        std::shared_ptr<InputApplicationHandle> oldFocusedApplicationHandle =
                getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);

        // If oldFocusedApplicationHandle already exists
        if (oldFocusedApplicationHandle != nullptr) {
            // If a new focused application handle is different from the old one and
            // old focus application info is awaited focused application info.
            if (*oldFocusedApplicationHandle != *inputApplicationHandle &&
                mAwaitedFocusedApplication != nullptr &&
                *oldFocusedApplicationHandle == *mAwaitedFocusedApplication) {
                resetNoFocusedWindowTimeoutLocked();
            }
            // Erase the old application from container first
            mFocusedApplicationHandlesByDisplay.erase(displayId);
            // Should already get freed after removed from container but just double check.
            oldFocusedApplicationHandle.reset();
        if (sharedPointersEqual(oldFocusedApplicationHandle, inputApplicationHandle)) {
            return; // This application is already focused. No need to wake up or change anything.
        }

        // Set the new application handle.
        if (inputApplicationHandle != nullptr) {
            mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
        } else {
            mFocusedApplicationHandlesByDisplay.erase(displayId);
        }

        // No matter what the old focused application was, stop waiting on it because it is
        // no longer focused.
        resetNoFocusedWindowTimeoutLocked();
    } // release lock

    // Wake up poll loop since it may need to make new input dispatching choices.
@@ -4234,6 +4240,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
                                                 "hasWallpaper=%s, visible=%s, "
                                                 "flags=%s, type=0x%08x, "
                                                 "frame=[%d,%d][%d,%d], globalScale=%f, "
                                                 "applicationInfo=%s, "
                                                 "touchableRegion=",
                                         i, windowInfo->name.c_str(), windowInfo->displayId,
                                         windowInfo->portalToDisplayId,
@@ -4245,7 +4252,8 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
                                         static_cast<int32_t>(windowInfo->type),
                                         windowInfo->frameLeft, windowInfo->frameTop,
                                         windowInfo->frameRight, windowInfo->frameBottom,
                                         windowInfo->globalScaleFactor);
                                         windowInfo->globalScaleFactor,
                                         windowInfo->applicationInfo.name.c_str());
                    dumpRegion(dump, windowInfo->touchableRegion);
                    dump += StringPrintf(", inputFeatures=%s",
                                         windowInfo->inputFeatures.string().c_str());
+20 −0
Original line number Diff line number Diff line
@@ -2810,6 +2810,26 @@ TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
    mFakePolicy->assertNotifyAnrWasNotCalled();
}

TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
    mWindow->setFocusable(false);
    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
    mWindow->consumeFocusEvent(false);

    int32_t result =
            injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
                      INPUT_EVENT_INJECTION_SYNC_NONE, 10ms /*injectionTimeout*/);
    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, result);
    // Key will not go to window because we have no focused window.
    // The 'no focused window' ANR timer should start instead.

    // Now, the focused application goes away.
    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
    // The key should get dropped and there should be no ANR.

    ASSERT_TRUE(mDispatcher->waitForIdle());
    mFakePolicy->assertNotifyAnrWasNotCalled();
}

// Send an event to the app and have the app not respond right away.
// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
// So InputDispatcher will enqueue ACTION_CANCEL event as well.