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

Commit e632c7cb authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Android (Google) Code Review
Browse files

Merge changes from topics "breakdown-usage-by-uid", "notify-device-interaction" into udc-qpr-dev

* changes:
  Break down input device usage by uid
  Notify MetricsCollector of device interaction from Dispatcher
parents c66c24e8 44293795
Loading
Loading
Loading
Loading
+76 −4
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ namespace android {

using android::base::StringPrintf;
using std::chrono::nanoseconds;
using std::chrono_literals::operator""ns;

namespace {

@@ -72,10 +73,19 @@ class : public InputDeviceMetricsLogger {
                     ftl::enum_string(src).c_str(), durMillis);
        }

        ALOGD_IF(DEBUG, "    Uid breakdown:");

        std::vector<int32_t> uids;
        std::vector<int32_t> durationsPerUid;
        for (auto& [uid, dur] : report.uidBreakdown) {
            uids.push_back(uid);
            int32_t durMillis = std::chrono::duration_cast<std::chrono::milliseconds>(dur).count();
            durationsPerUid.push_back(durMillis);
            ALOGD_IF(DEBUG, "        - uid: %d\t duration: %dms", uid, durMillis);
        }
        util::stats_write(util::INPUTDEVICE_USAGE_REPORTED, identifier.vendor, identifier.product,
                          identifier.version, linuxBusToInputDeviceBusEnum(identifier.bus),
                          durationMillis, sources, durationsPerSource, /*uids=*/empty,
                          /*usage_durations_per_uid=*/empty);
                          durationMillis, sources, durationsPerSource, uids, durationsPerUid);
    }
} sStatsdLogger;

@@ -246,6 +256,15 @@ void InputDeviceMetricsCollector::notifyPointerCaptureChanged(
    mNextListener.notify(args);
}

void InputDeviceMetricsCollector::notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
                                                          const std::set<int32_t>& uids) {
    std::set<Uid> typeSafeUids;
    for (auto uid : uids) {
        typeSafeUids.emplace(uid);
    }
    mInteractionsQueue.push(DeviceId{deviceId}, timestamp, typeSafeUids);
}

void InputDeviceMetricsCollector::dump(std::string& dump) {
    dump += "InputDeviceMetricsCollector:\n";

@@ -304,17 +323,33 @@ void InputDeviceMetricsCollector::onInputDeviceUsage(DeviceId deviceId, nanoseco
    }
}

void InputDeviceMetricsCollector::onInputDeviceInteraction(const Interaction& interaction) {
    auto activeSessionIt = mActiveUsageSessions.find(std::get<DeviceId>(interaction));
    if (activeSessionIt == mActiveUsageSessions.end()) {
        return;
    }

    activeSessionIt->second.recordInteraction(interaction);
}

void InputDeviceMetricsCollector::reportCompletedSessions() {
    const auto currentTime = mLogger.getCurrentTime();
    // Process all pending interactions.
    for (auto interaction = mInteractionsQueue.pop(); interaction;
         interaction = mInteractionsQueue.pop()) {
        onInputDeviceInteraction(*interaction);
    }

    const auto currentTime = mLogger.getCurrentTime();
    std::vector<DeviceId> completedUsageSessions;

    // Process usages for all active session to determine if any sessions have expired.
    for (auto& [deviceId, activeSession] : mActiveUsageSessions) {
        if (activeSession.checkIfCompletedAt(currentTime)) {
            completedUsageSessions.emplace_back(deviceId);
        }
    }

    // Close out and log all expired usage sessions.
    for (DeviceId deviceId : completedUsageSessions) {
        const auto infoIt = mLoggedDeviceInfos.find(deviceId);
        LOG_ALWAYS_FATAL_IF(infoIt == mLoggedDeviceInfos.end());
@@ -346,6 +381,23 @@ void InputDeviceMetricsCollector::ActiveSession::recordUsage(nanoseconds eventTi
    mDeviceSession.end = eventTime;
}

void InputDeviceMetricsCollector::ActiveSession::recordInteraction(const Interaction& interaction) {
    const auto sessionExpiryTime = mDeviceSession.end + mUsageSessionTimeout;
    const auto timestamp = std::get<nanoseconds>(interaction);
    if (timestamp >= sessionExpiryTime) {
        // This interaction occurred after the device's current active session is set to expire.
        // Ignore it.
        return;
    }

    for (Uid uid : std::get<std::set<Uid>>(interaction)) {
        auto [activeUidIt, inserted] = mActiveSessionsByUid.try_emplace(uid, timestamp, timestamp);
        if (!inserted) {
            activeUidIt->second.end = timestamp;
        }
    }
}

bool InputDeviceMetricsCollector::ActiveSession::checkIfCompletedAt(nanoseconds timestamp) {
    const auto sessionExpiryTime = timestamp - mUsageSessionTimeout;
    std::vector<InputDeviceUsageSource> completedSourceSessionsForDevice;
@@ -360,6 +412,21 @@ bool InputDeviceMetricsCollector::ActiveSession::checkIfCompletedAt(nanoseconds
        mSourceUsageBreakdown.emplace_back(source, session.end - session.start);
        mActiveSessionsBySource.erase(it);
    }

    std::vector<Uid> completedUidSessionsForDevice;
    for (auto& [uid, session] : mActiveSessionsByUid) {
        if (session.end <= sessionExpiryTime) {
            completedUidSessionsForDevice.emplace_back(uid);
        }
    }
    for (Uid uid : completedUidSessionsForDevice) {
        auto it = mActiveSessionsByUid.find(uid);
        const auto& [_, session] = *it;
        mUidUsageBreakdown.emplace_back(uid, session.end - session.start);
        mActiveSessionsByUid.erase(it);
    }

    // This active session has expired if there are no more active source sessions tracked.
    return mActiveSessionsBySource.empty();
}

@@ -372,7 +439,12 @@ InputDeviceMetricsCollector::ActiveSession::finishSession() {
    }
    mActiveSessionsBySource.clear();

    return {deviceUsageDuration, mSourceUsageBreakdown};
    for (const auto& [uid, uidSession] : mActiveSessionsByUid) {
        mUidUsageBreakdown.emplace_back(uid, uidSession.end - uidSession.start);
    }
    mActiveSessionsByUid.clear();

    return {deviceUsageDuration, mSourceUsageBreakdown, mUidUsageBreakdown};
}

} // namespace android
+31 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include "InputListener.h"
#include "NotifyArgs.h"
#include "SyncQueue.h"

#include <ftl/mixins.h>
#include <input/InputDevice.h>
@@ -33,10 +34,16 @@ namespace android {
/**
 * Logs metrics about registered input devices and their usages.
 *
 * Not thread safe. Must be called from a single thread.
 * All methods in the InputListenerInterface must be called from a single thread.
 */
class InputDeviceMetricsCollectorInterface : public InputListenerInterface {
public:
    /**
     * Notify the metrics collector that there was an input device interaction with apps.
     * Called from the InputDispatcher thread.
     */
    virtual void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
                                         const std::set<int32_t>& uids) = 0;
    /**
     * Dump the state of the interaction blocker.
     * This method may be called on any thread (usually by the input manager on a binder thread).
@@ -92,9 +99,14 @@ public:
    using SourceUsageBreakdown =
            std::vector<std::pair<InputDeviceUsageSource, std::chrono::nanoseconds /*duration*/>>;

    // Describes the breakdown of an input device usage session by the UIDs that it interacted with.
    using UidUsageBreakdown =
            std::vector<std::pair<int32_t /*uid*/, std::chrono::nanoseconds /*duration*/>>;

    struct DeviceUsageReport {
        std::chrono::nanoseconds usageDuration;
        SourceUsageBreakdown sourceBreakdown;
        UidUsageBreakdown uidBreakdown;
    };

    virtual void logInputDeviceUsageReported(const InputDeviceIdentifier&,
@@ -121,6 +133,8 @@ public:
    void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
    void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;

    void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
                                 const std::set<int32_t>& uids) override;
    void dump(std::string& dump) override;

private:
@@ -138,13 +152,25 @@ private:
        return std::to_string(ftl::to_underlying(id));
    }

    // Type-safe wrapper for a UID.
    struct Uid : ftl::Constructible<Uid, std::int32_t>, ftl::Equatable<Uid>, ftl::Orderable<Uid> {
        using Constructible::Constructible;
    };
    static inline std::string toString(const Uid& src) {
        return std::to_string(ftl::to_underlying(src));
    }

    std::map<DeviceId, InputDeviceInfo> mLoggedDeviceInfos;

    using Interaction = std::tuple<DeviceId, std::chrono::nanoseconds, std::set<Uid>>;
    SyncQueue<Interaction> mInteractionsQueue;

    class ActiveSession {
    public:
        explicit ActiveSession(std::chrono::nanoseconds usageSessionTimeout,
                               std::chrono::nanoseconds startTime);
        void recordUsage(std::chrono::nanoseconds eventTime, InputDeviceUsageSource source);
        void recordInteraction(const Interaction&);
        bool checkIfCompletedAt(std::chrono::nanoseconds timestamp);
        InputDeviceMetricsLogger::DeviceUsageReport finishSession();

@@ -159,6 +185,9 @@ private:

        std::map<InputDeviceUsageSource, UsageSession> mActiveSessionsBySource{};
        InputDeviceMetricsLogger::SourceUsageBreakdown mSourceUsageBreakdown{};

        std::map<Uid, UsageSession> mActiveSessionsByUid{};
        InputDeviceMetricsLogger::UidUsageBreakdown mUidUsageBreakdown{};
    };

    // The input devices that currently have active usage sessions.
@@ -169,6 +198,7 @@ private:
    using SourceProvider = std::function<std::set<InputDeviceUsageSource>(const InputDeviceInfo&)>;
    void onInputDeviceUsage(DeviceId deviceId, std::chrono::nanoseconds eventTime,
                            const SourceProvider& getSources);
    void onInputDeviceInteraction(const Interaction&);
    void reportCompletedSessions();
};

+4 −0
Original line number Diff line number Diff line
@@ -127,6 +127,10 @@ InputProcessorInterface& InputManager::getProcessor() {
    return *mProcessor;
}

InputDeviceMetricsCollectorInterface& InputManager::getMetricsCollector() {
    return *mCollector;
}

InputDispatcherInterface& InputManager::getDispatcher() {
    return *mDispatcher;
}
+4 −0
Original line number Diff line number Diff line
@@ -86,6 +86,9 @@ public:
    /* Gets the input processor. */
    virtual InputProcessorInterface& getProcessor() = 0;

    /* Gets the metrics collector. */
    virtual InputDeviceMetricsCollectorInterface& getMetricsCollector() = 0;

    /* Gets the input dispatcher. */
    virtual InputDispatcherInterface& getDispatcher() = 0;

@@ -109,6 +112,7 @@ public:

    InputReaderInterface& getReader() override;
    InputProcessorInterface& getProcessor() override;
    InputDeviceMetricsCollectorInterface& getMetricsCollector() override;
    InputDispatcherInterface& getDispatcher() override;
    void monitor() override;
    void dump(std::string& dump) override;
+3 −0
Original line number Diff line number Diff line
@@ -111,6 +111,9 @@ private:

    void notifyDropWindow(const sp<IBinder>&, float x, float y) override {}

    void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
                                 const std::set<int32_t>& uids) override {}

    InputDispatcherConfiguration mConfig;
};

Loading