/*
 * 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 <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 "InputHub.h"

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

#include <utils/Log.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);
    ALOGV("effective capabilities: %08x %08x", capdata[0].effective, capdata[1].effective);
    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 hasRelativeAxis(int axis) const override;
    virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) 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 status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const override;

    virtual void vibrate(nsecs_t duration) override;
    virtual void cancelVibrate(int32_t deviceId) 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::hasRelativeAxis(int axis) const {
    if (axis >= 0 && axis <= REL_MAX) {
        return testBit(axis, mRelBitmask);
    }
    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::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(int32_t deviceId) {
    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(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: %d 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=%d", 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) {
                std::shared_ptr<InputDeviceNode> deviceNode;
                status_t res = openNode(path, &deviceNode);
                if (res != OK) {
                    ALOGE("could not open device node %s. err=%d", path.c_str(), res);
                } else {
                    mInputCallback->onDeviceAdded(deviceNode);
                }
            } else {
                auto deviceNode = findNodeByPath(path);
                if (deviceNode != nullptr) {
                    status_t ret = closeNode(deviceNode);
                    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;
        std::shared_ptr<InputDeviceNode> node;
        if (openNode(filename, &node) != OK) {
            ALOGE("could not open device node %s", filename.c_str());
        } else {
            mInputCallback->onDeviceAdded(node);
        }
    }
    ::closedir(dir);
    return OK;
}

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

    auto fd = evdevNode->getFd();
    ALOGV("opened %s with fd %d", path.c_str(), fd);
    *outNode = std::static_pointer_cast<InputDeviceNode>(evdevNode);
    mDeviceNodes[fd] = *outNode;
    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 -errno;
    }

    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 OK;
}

status_t InputHub::closeNode(const std::shared_ptr<InputDeviceNode>& node) {
    for (auto pair : mDeviceNodes) {
        if (pair.second.get() == node.get()) {
            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
