/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "InputHub"
//#define LOG_NDEBUG 0

#include "InputHub.h"

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/capability.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>

#include <vector>

#include <android/input.h>
#include <hardware_legacy/power.h>
#include <linux/input.h>

#include <utils/Log.h>

#include "BitUtils.h"

namespace android {

static const char WAKE_LOCK_ID[] = "KeyEvents";
static const int NO_TIMEOUT = -1;
static const int EPOLL_MAX_EVENTS = 16;
static const int INPUT_MAX_EVENTS = 128;

static constexpr bool testBit(int bit, const uint8_t arr[]) {
    return arr[bit / 8] & (1 << (bit % 8));
}

static constexpr size_t sizeofBitArray(size_t bits) {
    return (bits + 7) / 8;
}

static void getLinuxRelease(int* major, int* minor) {
    struct utsname info;
    if (uname(&info) || sscanf(info.release, "%d.%d", major, minor) <= 0) {
        *major = 0, *minor = 0;
        ALOGE("Could not get linux version: %s", strerror(errno));
    }
}

static bool processHasCapability(int capability) {
    LOG_ALWAYS_FATAL_IF(!cap_valid(capability), "invalid linux capability: %d", capability);
    struct __user_cap_header_struct cap_header_data;
    struct __user_cap_data_struct cap_data_data[2];
    cap_user_header_t caphdr = &cap_header_data;
    cap_user_data_t capdata = cap_data_data;
    caphdr->pid = 0;
    caphdr->version = _LINUX_CAPABILITY_VERSION_3;
    LOG_ALWAYS_FATAL_IF(capget(caphdr, capdata) != 0,
            "Could not get process capabilities. errno=%d", errno);
    int idx = CAP_TO_INDEX(capability);
    return capdata[idx].effective & CAP_TO_MASK(capability);
}

class EvdevDeviceNode : public InputDeviceNode {
public:
    static EvdevDeviceNode* openDeviceNode(const std::string& path);

    virtual ~EvdevDeviceNode() {
        ALOGV("closing %s (fd=%d)", mPath.c_str(), mFd);
        if (mFd >= 0) {
            ::close(mFd);
        }
    }

    virtual int getFd() const { return mFd; }
    virtual const std::string& getPath() const override { return mPath; }
    virtual const std::string& getName() const override { return mName; }
    virtual const std::string& getLocation() const override { return mLocation; }
    virtual const std::string& getUniqueId() const override { return mUniqueId; }

    virtual uint16_t getBusType() const override { return mBusType; }
    virtual uint16_t getVendorId() const override { return mVendorId; }
    virtual uint16_t getProductId() const override { return mProductId; }
    virtual uint16_t getVersion() const override { return mVersion; }

    virtual bool hasKey(int32_t key) const override;
    virtual bool hasKeyInRange(int32_t start, int32_t end) const override;
    virtual bool hasRelativeAxis(int32_t axis) const override;
    virtual bool hasAbsoluteAxis(int32_t axis) const override;
    virtual bool hasSwitch(int32_t sw) const override;
    virtual bool hasForceFeedback(int32_t ff) const override;
    virtual bool hasInputProperty(int property) const override;

    virtual int32_t getKeyState(int32_t key) const override;
    virtual int32_t getSwitchState(int32_t sw) const override;
    virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const override;
    virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const override;

    virtual void vibrate(nsecs_t duration) override;
    virtual void cancelVibrate() override;

    virtual void disableDriverKeyRepeat() override;

private:
    EvdevDeviceNode(const std::string& path, int fd) :
        mFd(fd), mPath(path) {}

    status_t queryProperties();
    void queryAxisInfo();

    int mFd;
    std::string mPath;

    std::string mName;
    std::string mLocation;
    std::string mUniqueId;

    uint16_t mBusType;
    uint16_t mVendorId;
    uint16_t mProductId;
    uint16_t mVersion;

    uint8_t mKeyBitmask[KEY_CNT / 8];
    uint8_t mAbsBitmask[ABS_CNT / 8];
    uint8_t mRelBitmask[REL_CNT / 8];
    uint8_t mSwBitmask[SW_CNT / 8];
    uint8_t mLedBitmask[LED_CNT / 8];
    uint8_t mFfBitmask[FF_CNT / 8];
    uint8_t mPropBitmask[INPUT_PROP_CNT / 8];

    std::unordered_map<uint32_t, std::unique_ptr<AbsoluteAxisInfo>> mAbsInfo;

    bool mFfEffectPlaying = false;
    int16_t mFfEffectId = -1;
};

EvdevDeviceNode* EvdevDeviceNode::openDeviceNode(const std::string& path) {
    auto fd = TEMP_FAILURE_RETRY(::open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC));
    if (fd < 0) {
        ALOGE("could not open evdev device %s. err=%d", path.c_str(), errno);
        return nullptr;
    }

    // Tell the kernel that we want to use the monotonic clock for reporting
    // timestamps associated with input events. This is important because the
    // input system uses the timestamps extensively and assumes they were
    // recorded using the monotonic clock.
    //
    // The EVIOCSCLOCKID ioctl was introduced in Linux 3.4.
    int clockId = CLOCK_MONOTONIC;
    if (TEMP_FAILURE_RETRY(ioctl(fd, EVIOCSCLOCKID, &clockId)) < 0) {
        ALOGW("Could not set input clock id to CLOCK_MONOTONIC. errno=%d", errno);
    }

    auto node = new EvdevDeviceNode(path, fd);
    status_t ret = node->queryProperties();
    if (ret != OK) {
        ALOGE("could not open evdev device %s: failed to read properties. errno=%d",
                path.c_str(), ret);
        delete node;
        return nullptr;
    }
    return node;
}

status_t EvdevDeviceNode::queryProperties() {
    char buffer[80];

    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGNAME(sizeof(buffer) - 1), buffer)) < 1) {
        ALOGV("could not get device name for %s.", mPath.c_str());
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        mName = buffer;
    }

    int driverVersion;
    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGVERSION, &driverVersion))) {
        ALOGE("could not get driver version for %s. err=%d", mPath.c_str(), errno);
        return -errno;
    }

    struct input_id inputId;
    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGID, &inputId))) {
        ALOGE("could not get device input id for %s. err=%d", mPath.c_str(), errno);
        return -errno;
    }
    mBusType = inputId.bustype;
    mVendorId = inputId.vendor;
    mProductId = inputId.product;
    mVersion = inputId.version;

    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGPHYS(sizeof(buffer) - 1), buffer)) < 1) {
        ALOGV("could not get location for %s.", mPath.c_str());
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        mLocation = buffer;
    }

    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGUNIQ(sizeof(buffer) - 1), buffer)) < 1) {
        ALOGV("could not get unique id for %s.", mPath.c_str());
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        mUniqueId = buffer;
    }

    ALOGV("add device %s", mPath.c_str());
    ALOGV("  bus:        %04x\n"
          "  vendor:     %04x\n"
          "  product:    %04x\n"
          "  version:    %04x\n",
        mBusType, mVendorId, mProductId, mVersion);
    ALOGV("  name:       \"%s\"\n"
          "  location:   \"%s\"\n"
          "  unique_id:  \"%s\"\n"
          "  descriptor: (TODO)\n"
          "  driver:     v%d.%d.%d",
        mName.c_str(), mLocation.c_str(), mUniqueId.c_str(),
        driverVersion >> 16, (driverVersion >> 8) & 0xff, (driverVersion >> 16) & 0xff);

    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_KEY, sizeof(mKeyBitmask)), mKeyBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_ABS, sizeof(mAbsBitmask)), mAbsBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_REL, sizeof(mRelBitmask)), mRelBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_SW,  sizeof(mSwBitmask)),  mSwBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_LED, sizeof(mLedBitmask)), mLedBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_FF,  sizeof(mFfBitmask)),  mFfBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGPROP(sizeof(mPropBitmask)), mPropBitmask));

    queryAxisInfo();

    return OK;
}

void EvdevDeviceNode::queryAxisInfo() {
    for (int32_t axis = 0; axis < ABS_MAX; ++axis) {
        if (testBit(axis, mAbsBitmask)) {
            struct input_absinfo info;
            if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGABS(axis), &info))) {
                ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
                        axis, mPath.c_str(), mFd, errno);
                continue;
            }

            mAbsInfo[axis] = std::unique_ptr<AbsoluteAxisInfo>(new AbsoluteAxisInfo{
                    .minValue = info.minimum,
                    .maxValue = info.maximum,
                    .flat = info.flat,
                    .fuzz = info.fuzz,
                    .resolution = info.resolution
                    });
        }
    }
}

bool EvdevDeviceNode::hasKey(int32_t key) const {
    if (key >= 0 && key <= KEY_MAX) {
        return testBit(key, mKeyBitmask);
    }
    return false;
}

bool EvdevDeviceNode::hasKeyInRange(int32_t startKey, int32_t endKey) const {
    return testBitInRange(mKeyBitmask, startKey, endKey);
}

bool EvdevDeviceNode::hasRelativeAxis(int axis) const {
    if (axis >= 0 && axis <= REL_MAX) {
        return testBit(axis, mRelBitmask);
    }
    return false;
}

bool EvdevDeviceNode::hasAbsoluteAxis(int axis) const {
    if (axis >= 0 && axis <= ABS_MAX) {
        return getAbsoluteAxisInfo(axis) != nullptr;
    }
    return false;
}

const AbsoluteAxisInfo* EvdevDeviceNode::getAbsoluteAxisInfo(int32_t axis) const {
    if (axis < 0 || axis > ABS_MAX) {
        return nullptr;
    }

    const auto absInfo = mAbsInfo.find(axis);
    if (absInfo != mAbsInfo.end()) {
        return absInfo->second.get();
    }
    return nullptr;
}

bool EvdevDeviceNode::hasSwitch(int32_t sw) const {
    if (sw >= 0 && sw <= SW_MAX) {
        return testBit(sw, mSwBitmask);
    }
    return false;
}

bool EvdevDeviceNode::hasForceFeedback(int32_t ff) const {
    if (ff >= 0 && ff <= FF_MAX) {
        return testBit(ff, mFfBitmask);
    }
    return false;
}

bool EvdevDeviceNode::hasInputProperty(int property) const {
    if (property >= 0 && property <= INPUT_PROP_MAX) {
        return testBit(property, mPropBitmask);
    }
    return false;
}

int32_t EvdevDeviceNode::getKeyState(int32_t key) const {
    if (key >= 0 && key <= KEY_MAX) {
        if (testBit(key, mKeyBitmask)) {
            uint8_t keyState[sizeofBitArray(KEY_CNT)];
            memset(keyState, 0, sizeof(keyState));
            if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGKEY(sizeof(keyState)), keyState)) >= 0) {
                return testBit(key, keyState) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
            }
        }
    }
    return AKEY_STATE_UNKNOWN;
}

int32_t EvdevDeviceNode::getSwitchState(int32_t sw) const {
    if (sw >= 0 && sw <= SW_MAX) {
        if (testBit(sw, mSwBitmask)) {
            uint8_t swState[sizeofBitArray(SW_CNT)];
            memset(swState, 0, sizeof(swState));
            if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGSW(sizeof(swState)), swState)) >= 0) {
                return testBit(sw, swState) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
            }
        }
    }
    return AKEY_STATE_UNKNOWN;
}

status_t EvdevDeviceNode::getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const {
    *outValue = 0;

    if (axis >= 0 && axis <= ABS_MAX) {
        if (testBit(axis, mAbsBitmask)) {
            struct input_absinfo info;
            if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGABS(axis), &info))) {
                ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
                        axis, mPath.c_str(), mFd, errno);
                return -errno;
            }

            *outValue = info.value;
            return OK;
        }
    }
    return -1;
}

void EvdevDeviceNode::vibrate(nsecs_t duration) {
    ff_effect effect{};
    effect.type = FF_RUMBLE;
    effect.id = mFfEffectId;
    effect.u.rumble.strong_magnitude = 0xc000;
    effect.u.rumble.weak_magnitude = 0xc000;
    effect.replay.length = (duration + 999'999LL) / 1'000'000LL;
    effect.replay.delay = 0;
    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCSFF, &effect))) {
        ALOGW("Could not upload force feedback effect to device %s due to error %d.",
                mPath.c_str(), errno);
        return;
    }
    mFfEffectId = effect.id;

    struct input_event ev{};
    ev.type = EV_FF;
    ev.code = mFfEffectId;
    ev.value = 1;
    size_t written = TEMP_FAILURE_RETRY(write(mFd, &ev, sizeof(ev)));
    if (written != sizeof(ev)) {
        ALOGW("Could not start force feedback effect on device %s due to error %d.",
                mPath.c_str(), errno);
        return;
    }
    mFfEffectPlaying = true;
}

void EvdevDeviceNode::cancelVibrate() {
    if (mFfEffectPlaying) {
        mFfEffectPlaying = false;

        struct input_event ev{};
        ev.type = EV_FF;
        ev.code = mFfEffectId;
        ev.value = 0;
        size_t written = TEMP_FAILURE_RETRY(write(mFd, &ev, sizeof(ev)));
        if (written != sizeof(ev)) {
            ALOGW("Could not stop force feedback effect on device %s due to error %d.",
                    mPath.c_str(), errno);
            return;
        }
    }
}

void EvdevDeviceNode::disableDriverKeyRepeat() {
    unsigned int repeatRate[] = {0, 0};
    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCSREP, repeatRate))) {
        ALOGW("Unable to disable kernel key repeat for %s due to error %d.",
                mPath.c_str(), errno);
    }
}

InputHub::InputHub(const std::shared_ptr<InputCallbackInterface>& cb) :
    mInputCallback(cb) {
    // Determine the type of suspend blocking we can do on this device. There
    // are 3 options, in decreasing order of preference:
    //   1) EPOLLWAKEUP: introduced in Linux kernel 3.5, this flag can be set on
    //   an epoll event to indicate that a wake lock should be held from the
    //   time an fd has data until the next epoll_wait (or the epoll fd is
    //   closed).
    //   2) EVIOCSSUSPENDBLOCK: introduced into the Android kernel's evdev
    //   driver, this ioctl blocks suspend while the event queue for the fd is
    //   not empty. This was never accepted into the mainline kernel, and it was
    //   replaced by EPOLLWAKEUP.
    //   3) explicit wake locks: use acquire_wake_lock to manage suspend
    //   blocking explicitly in the InputHub code.
    //
    // (1) can be checked by simply observing the Linux kernel version. (2)
    // requires an fd from an evdev node, which cannot be done in the InputHub
    // constructor. So we assume (3) unless (1) is true, and we can verify
    // whether (2) is true once we have an evdev fd (and we're not in (1)).
    int major, minor;
    getLinuxRelease(&major, &minor);
    if (major > 3 || (major == 3 && minor >= 5)) {
        ALOGI("Using EPOLLWAKEUP to block suspend while processing input events.");
        mWakeupMechanism = WakeMechanism::EPOLL_WAKEUP;
        mNeedToCheckSuspendBlockIoctl = false;
    }
    if (manageWakeLocks()) {
        acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
    }

    // epoll_create argument is ignored, but it must be > 0.
    mEpollFd = epoll_create(1);
    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);

    mINotifyFd = inotify_init();
    LOG_ALWAYS_FATAL_IF(mINotifyFd < 0, "Could not create inotify instance. errno=%d", errno);

    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    if (mWakeupMechanism == WakeMechanism::EPOLL_WAKEUP) {
        eventItem.events |= EPOLLWAKEUP;
    }
    eventItem.data.u32 = mINotifyFd;
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);

    int wakeFds[2];
    result = pipe(wakeFds);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);

    mWakeEventFd = eventfd(0, EFD_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(mWakeEventFd == -1, "Could not create wake event fd. errno=%d", errno);

    eventItem.data.u32 = mWakeEventFd;
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, &eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance. errno=%d", errno);
}

InputHub::~InputHub() {
    ::close(mEpollFd);
    ::close(mINotifyFd);
    ::close(mWakeEventFd);

    if (manageWakeLocks()) {
        release_wake_lock(WAKE_LOCK_ID);
    }
}

status_t InputHub::registerDevicePath(const std::string& path) {
    ALOGV("registering device path %s", path.c_str());
    int wd = inotify_add_watch(mINotifyFd, path.c_str(), IN_DELETE | IN_CREATE);
    if (wd < 0) {
        ALOGE("Could not add %s to INotify watch. errno=%d", path.c_str(), errno);
        return -errno;
    }
    mWatchedPaths[wd] = path;
    scanDir(path);
    return OK;
}

status_t InputHub::unregisterDevicePath(const std::string& path) {
    int wd = -1;
    for (auto pair : mWatchedPaths) {
        if (pair.second == path) {
            wd = pair.first;
            break;
        }
    }

    if (wd == -1) {
        return BAD_VALUE;
    }
    mWatchedPaths.erase(wd);
    if (inotify_rm_watch(mINotifyFd, wd) != 0) {
        return -errno;
    }
    return OK;
}

status_t InputHub::poll() {
    bool deviceChange = false;

    if (manageWakeLocks()) {
        // Mind the wake lock dance!
        // If we're relying on wake locks, we hold a wake lock at all times
        // except during epoll_wait(). This works due to some subtle
        // choreography. When a device driver has pending (unread) events, it
        // acquires a kernel wake lock. However, once the last pending event
        // has been read, the device driver will release the kernel wake lock.
        // To prevent the system from going to sleep when this happens, the
        // InputHub holds onto its own user wake lock while the client is
        // processing events. Thus the system can only sleep if there are no
        // events pending or currently being processed.
        release_wake_lock(WAKE_LOCK_ID);
    }

    struct epoll_event pendingEventItems[EPOLL_MAX_EVENTS];
    int pollResult = epoll_wait(mEpollFd, pendingEventItems, EPOLL_MAX_EVENTS, NO_TIMEOUT);

    if (manageWakeLocks()) {
        acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
    }

    if (pollResult == 0) {
        ALOGW("epoll_wait should not return 0 with no timeout");
        return UNKNOWN_ERROR;
    }
    if (pollResult < 0) {
        // An error occurred. Return even if it's EINTR, and let the caller
        // restart the poll.
        ALOGE("epoll_wait returned with errno=%d", errno);
        return -errno;
    }

    // pollResult > 0: there are events to process
    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    std::vector<int> removedDeviceFds;
    int inputFd = -1;
    std::shared_ptr<InputDeviceNode> deviceNode;
    for (int i = 0; i < pollResult; ++i) {
        const struct epoll_event& eventItem = pendingEventItems[i];

        int dataFd = static_cast<int>(eventItem.data.u32);
        if (dataFd == mINotifyFd) {
            if (eventItem.events & EPOLLIN) {
                deviceChange = true;
            } else {
                ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
            }
            continue;
        }

        if (dataFd == mWakeEventFd) {
            if (eventItem.events & EPOLLIN) {
                ALOGV("awoken after wake()");
                uint64_t u;
                ssize_t nRead = TEMP_FAILURE_RETRY(read(mWakeEventFd, &u, sizeof(uint64_t)));
                if (nRead != sizeof(uint64_t)) {
                    ALOGW("Could not read event fd; waking anyway.");
                }
            } else {
                ALOGW("Received unexpected epoll event 0x%08x for wake event.",
                        eventItem.events);
            }
            continue;
        }

        // Update the fd and device node when the fd changes. When several
        // events are read back-to-back with the same fd, this saves many reads
        // from the hash table.
        if (inputFd != dataFd) {
            inputFd = dataFd;
            deviceNode = mDeviceNodes[inputFd];
        }
        if (deviceNode == nullptr) {
            ALOGE("could not find device node for fd %d", inputFd);
            continue;
        }
        if (eventItem.events & EPOLLIN) {
            struct input_event ievs[INPUT_MAX_EVENTS];
            for (;;) {
                ssize_t readSize = TEMP_FAILURE_RETRY(read(inputFd, ievs, sizeof(ievs)));
                if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
                    ALOGW("could not get event, removed? (fd: %d, size: %zd errno: %d)",
                            inputFd, readSize, errno);

                    removedDeviceFds.push_back(inputFd);
                    break;
                } else if (readSize < 0) {
                    if (errno != EAGAIN && errno != EINTR) {
                        ALOGW("could not get event. errno=%d", errno);
                    }
                    break;
                } else if (readSize % sizeof(input_event) != 0) {
                    ALOGE("could not get event. wrong size=%zd", readSize);
                    break;
                } else {
                    size_t count = static_cast<size_t>(readSize) / sizeof(struct input_event);
                    for (size_t i = 0; i < count; ++i) {
                        auto& iev = ievs[i];
                        auto when = s2ns(iev.time.tv_sec) + us2ns(iev.time.tv_usec);
                        InputEvent inputEvent = { when, iev.type, iev.code, iev.value };
                        mInputCallback->onInputEvent(deviceNode, inputEvent, now);
                    }
                }
            }
        } else if (eventItem.events & EPOLLHUP) {
            ALOGI("Removing device fd %d due to epoll hangup event.", inputFd);
            removedDeviceFds.push_back(inputFd);
        } else {
            ALOGW("Received unexpected epoll event 0x%08x for device fd %d",
                    eventItem.events, inputFd);
        }
    }

    if (removedDeviceFds.size()) {
        for (auto deviceFd : removedDeviceFds) {
            auto deviceNode = mDeviceNodes[deviceFd];
            if (deviceNode != nullptr) {
                status_t ret = closeNodeByFd(deviceFd);
                if (ret != OK) {
                    ALOGW("Could not close device with fd %d. errno=%d", deviceFd, ret);
                } else {
                    mInputCallback->onDeviceRemoved(deviceNode);
                }
            }
        }
    }

    if (deviceChange) {
        readNotify();
    }

    return OK;
}

status_t InputHub::wake() {
    ALOGV("wake() called");

    uint64_t u = 1;
    ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &u, sizeof(uint64_t)));

    if (nWrite != sizeof(uint64_t) && errno != EAGAIN) {
        ALOGW("Could not write wake signal, errno=%d", errno);
        return -errno;
    }
    return OK;
}

void InputHub::dump(String8& dump) {
    // TODO
}

status_t InputHub::readNotify() {
    char event_buf[512];
    struct inotify_event* event;

    ssize_t res = TEMP_FAILURE_RETRY(read(mINotifyFd, event_buf, sizeof(event_buf)));
    if (res < static_cast<int>(sizeof(*event))) {
        ALOGW("could not get inotify event, %s\n", strerror(errno));
        return -errno;
    }

    size_t event_pos = 0;
    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    while (res >= static_cast<int>(sizeof(*event))) {
        event = reinterpret_cast<struct inotify_event*>(event_buf + event_pos);
        if (event->len) {
            std::string path = mWatchedPaths[event->wd];
            path.append("/").append(event->name);
            ALOGV("inotify event for path %s", path.c_str());

            if (event->mask & IN_CREATE) {
                auto deviceNode = openNode(path);
                if (deviceNode == nullptr) {
                    ALOGE("could not open device node %s. err=%zd", path.c_str(), res);
                } else {
                    mInputCallback->onDeviceAdded(deviceNode);
                }
            } else {
                auto deviceNode = findNodeByPath(path);
                if (deviceNode != nullptr) {
                    status_t ret = closeNode(deviceNode.get());
                    if (ret != OK) {
                        ALOGW("Could not close device %s. errno=%d", path.c_str(), ret);
                    } else {
                        mInputCallback->onDeviceRemoved(deviceNode);
                    }
                } else {
                    ALOGW("could not find device node for %s", path.c_str());
                }
            }
        }
        int event_size = sizeof(*event) + event->len;
        res -= event_size;
        event_pos += event_size;
    }

    return OK;
}

status_t InputHub::scanDir(const std::string& path) {
    auto dir = ::opendir(path.c_str());
    if (dir == nullptr) {
        ALOGE("could not open device path %s to scan for devices. err=%d", path.c_str(), errno);
        return -errno;
    }

    while (auto dirent = readdir(dir)) {
        if (strcmp(dirent->d_name, ".") == 0 ||
            strcmp(dirent->d_name, "..") == 0) {
            continue;
        }
        std::string filename = path + "/" + dirent->d_name;
        auto node = openNode(filename);
        if (node == nullptr) {
            ALOGE("could not open device node %s", filename.c_str());
        } else {
            mInputCallback->onDeviceAdded(node);
        }
    }
    ::closedir(dir);
    return OK;
}

std::shared_ptr<InputDeviceNode> InputHub::openNode(const std::string& path) {
    ALOGV("opening %s...", path.c_str());
    auto evdevNode = std::shared_ptr<EvdevDeviceNode>(EvdevDeviceNode::openDeviceNode(path));
    if (evdevNode == nullptr) {
        return nullptr;
    }

    auto fd = evdevNode->getFd();
    ALOGV("opened %s with fd %d", path.c_str(), fd);
    mDeviceNodes[fd] = evdevNode;
    struct epoll_event eventItem{};
    eventItem.events = EPOLLIN;
    if (mWakeupMechanism == WakeMechanism::EPOLL_WAKEUP) {
        eventItem.events |= EPOLLWAKEUP;
    }
    eventItem.data.u32 = fd;
    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
        ALOGE("Could not add device fd to epoll instance. errno=%d", errno);
        return nullptr;
    }

    if (mNeedToCheckSuspendBlockIoctl) {
#ifndef EVIOCSSUSPENDBLOCK
        // uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels
        // will use an epoll flag instead, so as long as we want to support this
        // feature, we need to be prepared to define the ioctl ourselves.
#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
#endif
        if (TEMP_FAILURE_RETRY(ioctl(fd, EVIOCSSUSPENDBLOCK, 1))) {
            // no wake mechanism, continue using explicit wake locks
            ALOGI("Using explicit wakelocks to block suspend while processing input events.");
        } else {
            mWakeupMechanism = WakeMechanism::LEGACY_EVDEV_SUSPENDBLOCK_IOCTL;
            // release any held wakelocks since we won't need them anymore
            release_wake_lock(WAKE_LOCK_ID);
            ALOGI("Using EVIOCSSUSPENDBLOCK to block suspend while processing input events.");
        }
        mNeedToCheckSuspendBlockIoctl = false;
    }

    return evdevNode;
}

status_t InputHub::closeNode(const InputDeviceNode* node) {
    for (auto pair : mDeviceNodes) {
        if (pair.second.get() == node) {
            return closeNodeByFd(pair.first);
        }
    }
    return BAD_VALUE;
}

status_t InputHub::closeNodeByFd(int fd) {
    status_t ret = OK;
    if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL)) {
        ALOGW("Could not remove device fd from epoll instance. errno=%d", errno);
        ret = -errno;
    }
    mDeviceNodes.erase(fd);
    ::close(fd);
    return ret;
}

std::shared_ptr<InputDeviceNode> InputHub::findNodeByPath(const std::string& path) {
    for (auto pair : mDeviceNodes) {
        if (pair.second->getPath() == path) return pair.second;
    }
    return nullptr;
}

bool InputHub::manageWakeLocks() const {
    return mWakeupMechanism != WakeMechanism::EPOLL_WAKEUP;
}

}  // namespace android
