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

Commit 523b461f authored by Jimmy's avatar Jimmy
Browse files

Add support for search modifier fallbacks

Fixes a bug in where kcm fallbacks with search based modifiers could
not activate since PhoneWindowManager would consume all search events.
This prevented the InputDispatcher from generating the fallback.

This change modifies the behavior so InputDispatcher handles whether
the search-based event will attempt to generate a fallback.

Bug: 384113980
Test: atest InputDispatcherTest

Flag: com.android.hardware.input.fix_search_modifier_fallbacks

Change-Id: Ib7eca10f00ec93fd46a93396b7908ff925dd705b
parent 4c54b762
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -125,10 +125,17 @@ struct KeyEntry : EventEntry {
    bool syntheticRepeat; // set to true for synthetic key repeats

    enum class InterceptKeyResult {
        // The interception result is unknown.
        UNKNOWN,
        // The event should be skipped and not sent to the application.
        SKIP,
        // The event should be sent to the application.
        CONTINUE,
        // The event should eventually be sent to the application, after a delay.
        TRY_AGAIN_LATER,
        // The event should not be initially sent to the application, but instead go through
        // post-processing to generate a fallback key event and then sent to the application.
        FALLBACK,
    };
    // These are special fields that may need to be modified while the event is being dispatched.
    mutable InterceptKeyResult interceptKeyResult; // set based on the interception result
+65 −2
Original line number Diff line number Diff line
@@ -952,7 +952,7 @@ InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
                                  new LatencyAggregatorWithHistograms()))
                        : std::move(std::unique_ptr<InputEventTimelineProcessor>(
                                  new LatencyAggregator()))),
        mLatencyTracker(*mInputEventTimelineProcessor) {
        mLatencyTracker(*mInputEventTimelineProcessor, mInputDevices) {
    mReporter = createInputReporter();

    mWindowInfoListener = sp<DispatcherWindowListener>::make(*this);
@@ -1961,11 +1961,74 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<con
        }
    }

    if (entry->interceptKeyResult == KeyEntry::InterceptKeyResult::FALLBACK) {
        findAndDispatchFallbackEvent(currentTime, entry, inputTargets);
        // Drop the key.
        return true;
    }

    // Dispatch the key.
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

void InputDispatcher::findAndDispatchFallbackEvent(nsecs_t currentTime,
                                                   std::shared_ptr<const KeyEntry> entry,
                                                   std::vector<InputTarget>& inputTargets) {
    // Find the fallback associated with the incoming key event and dispatch it.
    KeyEvent event = createKeyEvent(*entry);
    const int32_t originalKeyCode = entry->keyCode;

    // Fetch the fallback event.
    KeyCharacterMap::FallbackAction fallback;
    for (const InputDeviceInfo& deviceInfo : mInputDevices) {
        if (deviceInfo.getId() == entry->deviceId) {
            const KeyCharacterMap* map = deviceInfo.getKeyCharacterMap();

            LOG_ALWAYS_FATAL_IF(map == nullptr, "No KeyCharacterMap for device %d",
                                entry->deviceId);
            map->getFallbackAction(entry->keyCode, entry->metaState, &fallback);
            break;
        }
    }

    if (fallback.keyCode == AKEYCODE_UNKNOWN) {
        // No fallback detected.
        return;
    }

    std::unique_ptr<KeyEntry> fallbackKeyEntry =
            std::make_unique<KeyEntry>(mIdGenerator.nextId(), entry->injectionState,
                                       event.getEventTime(), event.getDeviceId(), event.getSource(),
                                       event.getDisplayId(), entry->policyFlags, entry->action,
                                       event.getFlags() | AKEY_EVENT_FLAG_FALLBACK,
                                       fallback.keyCode, event.getScanCode(), /*metaState=*/0,
                                       event.getRepeatCount(), event.getDownTime());

    if (mTracer) {
        fallbackKeyEntry->traceTracker =
                mTracer->traceDerivedEvent(*fallbackKeyEntry, *entry->traceTracker);
    }

    for (const InputTarget& inputTarget : inputTargets) {
        std::shared_ptr<Connection> connection = inputTarget.connection;
        if (!connection->responsive || (connection->status != Connection::Status::NORMAL)) {
            return;
        }

        connection->inputState.setFallbackKey(originalKeyCode, fallback.keyCode);
        if (entry->action == AKEY_EVENT_ACTION_UP) {
            connection->inputState.removeFallbackKey(originalKeyCode);
        }

        if (mTracer) {
            mTracer->dispatchToTargetHint(*fallbackKeyEntry->traceTracker, inputTarget);
        }
        enqueueDispatchEntryAndStartDispatchCycleLocked(currentTime, connection,
                                                        std::move(fallbackKeyEntry), inputTarget);
    }
}

void InputDispatcher::logOutboundKeyDetails(const char* prefix, const KeyEntry& entry) {
    LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
            << prefix << "eventTime=" << entry.eventTime << ", deviceId=" << entry.deviceId
@@ -4346,7 +4409,7 @@ void InputDispatcher::notifyInputDevicesChanged(const NotifyInputDevicesChangedA
    std::scoped_lock _l(mLock);
    // Reset key repeating in case a keyboard device was added or removed or something.
    resetKeyRepeatLocked();
    mLatencyTracker.setInputDevices(args.inputDeviceInfos);
    mInputDevices = args.inputDeviceInfos;
}

void InputDispatcher::notifyKey(const NotifyKeyArgs& args) {
+4 −0
Original line number Diff line number Diff line
@@ -918,10 +918,14 @@ private:
    std::unique_ptr<const KeyEntry> afterKeyEventLockedInterruptable(
            const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry,
            bool handled) REQUIRES(mLock);
    void findAndDispatchFallbackEvent(nsecs_t currentTime, std::shared_ptr<const KeyEntry> entry,
                                      std::vector<InputTarget>& inputTargets) REQUIRES(mLock);

    // Statistics gathering.
    nsecs_t mLastStatisticPushTime = 0;
    std::unique_ptr<InputEventTimelineProcessor> mInputEventTimelineProcessor GUARDED_BY(mLock);
    // Must outlive `mLatencyTracker`.
    std::vector<InputDeviceInfo> mInputDevices;
    LatencyTracker mLatencyTracker GUARDED_BY(mLock);
    void traceInboundQueueLengthLocked() REQUIRES(mLock);
    void traceOutboundQueueLength(const Connection& connection);
+3 −6
Original line number Diff line number Diff line
@@ -67,8 +67,9 @@ static void eraseByValue(std::multimap<K, V>& map, const V& value) {

} // namespace

LatencyTracker::LatencyTracker(InputEventTimelineProcessor& processor)
      : mTimelineProcessor(&processor) {}
LatencyTracker::LatencyTracker(InputEventTimelineProcessor& processor,
                               std::vector<InputDeviceInfo>& inputDevices)
      : mTimelineProcessor(&processor), mInputDevices(inputDevices) {}

void LatencyTracker::trackListener(const NotifyArgs& args) {
    if (const NotifyKeyArgs* keyArgs = std::get_if<NotifyKeyArgs>(&args)) {
@@ -248,8 +249,4 @@ std::string LatencyTracker::dump(const char* prefix) const {
            StringPrintf("%s  mEventTimes.size() = %zu\n", prefix, mEventTimes.size());
}

void LatencyTracker::setInputDevices(const std::vector<InputDeviceInfo>& inputDevices) {
    mInputDevices = inputDevices;
}

} // namespace android::inputdispatcher
+6 −3
Original line number Diff line number Diff line
@@ -20,9 +20,11 @@

#include <map>
#include <unordered_map>
#include <vector>

#include <binder/IBinder.h>
#include <input/Input.h>
#include <input/InputDevice.h>

#include "InputEventTimeline.h"
#include "NotifyArgs.h"
@@ -41,8 +43,10 @@ public:
    /**
     * Create a LatencyTracker.
     * param reportingFunction: the function that will be called in order to report full latency.
     * param inputDevices: input devices relevant for tracking.
     */
    LatencyTracker(InputEventTimelineProcessor& processor);
    LatencyTracker(InputEventTimelineProcessor& processor,
                   std::vector<InputDeviceInfo>& inputDevices);
    /**
     * Start keeping track of an event identified by the args. This must be called first.
     * If duplicate events are encountered (events that have the same eventId), none of them will be
@@ -60,7 +64,6 @@ public:
                              std::array<nsecs_t, GraphicsTimeline::SIZE> timeline);

    std::string dump(const char* prefix) const;
    void setInputDevices(const std::vector<InputDeviceInfo>& inputDevices);

private:
    /**
@@ -81,7 +84,7 @@ private:
    std::multimap<nsecs_t /*eventTime*/, int32_t /*inputEventId*/> mEventTimes;

    InputEventTimelineProcessor* mTimelineProcessor;
    std::vector<InputDeviceInfo> mInputDevices;
    std::vector<InputDeviceInfo>& mInputDevices;

    void trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime, DeviceId deviceId,
                       const std::set<InputDeviceUsageSource>& sources, int32_t inputEventAction,
Loading