/*
 * Copyright 2021 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.
 */

#include "DrmPresenter.h"

#include <cros_gralloc_handle.h>
#include <linux/netlink.h>
#include <sys/socket.h>

using android::base::guest::AutoReadLock;
using android::base::guest::AutoWriteLock;
using android::base::guest::ReadWriteLock;

namespace android {

bool DrmPresenter::init(const HotplugCallback& cb) {
  DEBUG_LOG("%s", __FUNCTION__);

  mHotplugCallback = cb;
  mFd = android::base::unique_fd(open("/dev/dri/card0", O_RDWR | O_CLOEXEC));
  if (mFd < 0) {
    ALOGE("%s HWC2::Error opening DrmPresenter device: %d", __FUNCTION__,
          errno);
    return false;
  }

  int univRet = drmSetClientCap(mFd.get(), DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
  if (univRet) {
    ALOGE("%s: fail to set universal plane %d\n", __FUNCTION__, univRet);
    return false;
  }

  int atomicRet = drmSetClientCap(mFd.get(), DRM_CLIENT_CAP_ATOMIC, 1);
  if (atomicRet) {
    ALOGE("%s: fail to set atomic operation %d, %d\n", __FUNCTION__, atomicRet,
          errno);
    return false;
  }

  {
    AutoWriteLock lock(mStateMutex);
    bool initDrmRet = initDrmElementsLocked();
    if (initDrmRet) {
      ALOGD("%s: Successfully initialized DRM backend", __FUNCTION__);
    } else {
      ALOGE("%s: Failed to initialize DRM backend", __FUNCTION__);
      return false;
    }
  }

  mDrmEventListener = sp<DrmEventListener>::make(*this);
  if (mDrmEventListener->init()) {
    ALOGD("%s: Successfully initialized DRM event listener", __FUNCTION__);
  } else {
    ALOGE("%s: Failed to initialize DRM event listener", __FUNCTION__);
  }
  mDrmEventListener->run("", ANDROID_PRIORITY_URGENT_DISPLAY);

  return true;
}

bool DrmPresenter::initDrmElementsLocked() {
  drmModeRes* res;
  static const int32_t kUmPerInch = 25400;

  res = drmModeGetResources(mFd.get());
  if (res == nullptr) {
    ALOGE("%s HWC2::Error reading drm resources: %d", __FUNCTION__, errno);
    mFd.reset();
    return false;
  }

  ALOGD(
      "drmModeRes count fbs %d crtc %d connector %d encoder %d min w %d max w "
      "%d min h %d max h %d",
      res->count_fbs, res->count_crtcs, res->count_connectors,
      res->count_encoders, res->min_width, res->max_width, res->min_height,
      res->max_height);

  for (uint32_t i = 0; i < res->count_crtcs; i++) {
    DrmCrtc crtc = {};

    drmModeCrtcPtr c = drmModeGetCrtc(mFd.get(), res->crtcs[i]);
    crtc.mId = c->crtc_id;

    drmModeObjectPropertiesPtr crtcProps =
        drmModeObjectGetProperties(mFd.get(), c->crtc_id, DRM_MODE_OBJECT_CRTC);

    for (uint32_t crtcPropsIndex = 0; crtcPropsIndex < crtcProps->count_props;
         crtcPropsIndex++) {
      drmModePropertyPtr crtcProp =
          drmModeGetProperty(mFd.get(), crtcProps->props[crtcPropsIndex]);

      if (!strcmp(crtcProp->name, "OUT_FENCE_PTR")) {
        crtc.mOutFencePtrPropertyId = crtcProp->prop_id;
      } else if (!strcmp(crtcProp->name, "ACTIVE")) {
        crtc.mActivePropertyId = crtcProp->prop_id;
      } else if (!strcmp(crtcProp->name, "MODE_ID")) {
        crtc.mModePropertyId = crtcProp->prop_id;
      }

      drmModeFreeProperty(crtcProp);
    }

    drmModeFreeObjectProperties(crtcProps);

    mCrtcs.push_back(crtc);
  }

  drmModePlaneResPtr planeRes = drmModeGetPlaneResources(mFd.get());
  for (uint32_t i = 0; i < planeRes->count_planes; ++i) {
    DrmPlane plane = {};

    drmModePlanePtr p = drmModeGetPlane(mFd.get(), planeRes->planes[i]);
    plane.mId = p->plane_id;

    ALOGD(
        "%s: plane id: %u crtcid %u fbid %u crtc xy %d %d xy %d %d "
        "possible ctrcs 0x%x",
        __FUNCTION__, p->plane_id, p->crtc_id, p->fb_id, p->crtc_x, p->crtc_y,
        p->x, p->y, p->possible_crtcs);

    drmModeObjectPropertiesPtr planeProps =
        drmModeObjectGetProperties(mFd.get(), plane.mId, DRM_MODE_OBJECT_PLANE);

    for (uint32_t planePropIndex = 0; planePropIndex < planeProps->count_props;
         ++planePropIndex) {
      drmModePropertyPtr planeProp =
          drmModeGetProperty(mFd.get(), planeProps->props[planePropIndex]);

      if (!strcmp(planeProp->name, "CRTC_ID")) {
        plane.mCrtcPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "IN_FENCE_FD")) {
        plane.mInFenceFdPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "FB_ID")) {
        plane.mFbPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "CRTC_X")) {
        plane.mCrtcXPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "CRTC_Y")) {
        plane.mCrtcYPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "CRTC_W")) {
        plane.mCrtcWPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "CRTC_H")) {
        plane.mCrtcHPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "SRC_X")) {
        plane.mSrcXPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "SRC_Y")) {
        plane.mSrcYPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "SRC_W")) {
        plane.mSrcWPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "SRC_H")) {
        plane.mSrcHPropertyId = planeProp->prop_id;
      } else if (!strcmp(planeProp->name, "type")) {
        plane.mTypePropertyId = planeProp->prop_id;
        uint64_t type = planeProp->values[0];
        switch (type) {
          case DRM_PLANE_TYPE_OVERLAY:
            plane.mType = type;
            ALOGD("%s: plane %" PRIu32 " is DRM_PLANE_TYPE_OVERLAY",
                  __FUNCTION__, plane.mId);
            break;
          case DRM_PLANE_TYPE_PRIMARY:
            plane.mType = type;
            ALOGD("%s: plane %" PRIu32 " is DRM_PLANE_TYPE_PRIMARY",
                  __FUNCTION__, plane.mId);
            break;
          default:
            break;
        }
      }

      drmModeFreeProperty(planeProp);
    }

    drmModeFreeObjectProperties(planeProps);

    bool isPrimaryOrOverlay = plane.mType == DRM_PLANE_TYPE_OVERLAY ||
                              plane.mType == DRM_PLANE_TYPE_PRIMARY;
    if (isPrimaryOrOverlay) {
      for (uint32_t j = 0; j < mCrtcs.size(); j++) {
        if ((0x1 << j) & p->possible_crtcs) {
          ALOGD("%s: plane %" PRIu32 " compatible with crtc mask %" PRIu32,
                __FUNCTION__, plane.mId, p->possible_crtcs);
          if (mCrtcs[j].mPlaneId == -1) {
            mCrtcs[j].mPlaneId = plane.mId;
            ALOGD("%s: plane %" PRIu32 " associated with crtc %" PRIu32,
                  __FUNCTION__, plane.mId, j);
            break;
          }
        }
      }
    }

    drmModeFreePlane(p);
    mPlanes[plane.mId] = plane;
  }
  drmModeFreePlaneResources(planeRes);

  for (uint32_t i = 0; i < res->count_connectors; ++i) {
    DrmConnector connector = {};
    connector.mId = res->connectors[i];

    {
      drmModeObjectPropertiesPtr connectorProps = drmModeObjectGetProperties(
          mFd.get(), connector.mId, DRM_MODE_OBJECT_CONNECTOR);

      for (uint32_t connectorPropIndex = 0;
           connectorPropIndex < connectorProps->count_props;
           ++connectorPropIndex) {
        drmModePropertyPtr connectorProp = drmModeGetProperty(
            mFd.get(), connectorProps->props[connectorPropIndex]);
        if (!strcmp(connectorProp->name, "CRTC_ID")) {
          connector.mCrtcPropertyId = connectorProp->prop_id;
        } else if (!strcmp(connectorProp->name, "EDID")) {
          connector.mEdidBlobId =
              connectorProps->prop_values[connectorPropIndex];
        }
        drmModeFreeProperty(connectorProp);
      }

      drmModeFreeObjectProperties(connectorProps);
    }
    {
      drmModeConnector* c = drmModeGetConnector(mFd.get(), connector.mId);
      if (c == nullptr) {
        ALOGE("%s: Failed to get connector %" PRIu32 ": %d", __FUNCTION__,
              connector.mId, errno);
        return false;
      }
      connector.connection = c->connection;
      if (c->count_modes > 0) {
        memcpy(&connector.mMode, &c->modes[0], sizeof(drmModeModeInfo));
        drmModeCreatePropertyBlob(mFd.get(), &connector.mMode,
                                  sizeof(connector.mMode),
                                  &connector.mModeBlobId);

        // Dots per 1000 inches
        connector.dpiX =
            c->mmWidth ? (c->modes[0].hdisplay * kUmPerInch) / (c->mmWidth)
                       : -1;
        // Dots per 1000 inches
        connector.dpiY =
            c->mmHeight ? (c->modes[0].vdisplay * kUmPerInch) / (c->mmHeight)
                        : -1;
      }
      ALOGD("%s connector %" PRIu32 " dpiX %" PRIi32 " dpiY %" PRIi32
            " connection %d",
            __FUNCTION__, connector.mId, connector.dpiX, connector.dpiY,
            connector.connection);

      drmModeFreeConnector(c);

      connector.mRefreshRateAsFloat =
          1000.0f * connector.mMode.clock /
          ((float)connector.mMode.vtotal * (float)connector.mMode.htotal);
      connector.mRefreshRateAsInteger =
          (uint32_t)(connector.mRefreshRateAsFloat + 0.5f);
    }

    mConnectors.push_back(connector);
  }

  drmModeFreeResources(res);
  return true;
}

void DrmPresenter::resetDrmElementsLocked() {
  for (auto& c : mConnectors) {
    if (c.mModeBlobId) {
      if (drmModeDestroyPropertyBlob(mFd.get(), c.mModeBlobId)) {
        ALOGE("%s: Error destroy PropertyBlob %" PRIu32, __func__,
              c.mModeBlobId);
      }
    }
  }
  mConnectors.clear();
  mCrtcs.clear();
  mPlanes.clear();
}

int DrmPresenter::getDrmFB(hwc_drm_bo_t& bo) {
  int ret = drmPrimeFDToHandle(mFd.get(), bo.prime_fds[0], &bo.gem_handles[0]);
  if (ret) {
    ALOGE("%s: drmPrimeFDToHandle failed: %s (errno %d)", __FUNCTION__,
          strerror(errno), errno);
    return -1;
  }
  ret = drmModeAddFB2(mFd.get(), bo.width, bo.height, bo.format, bo.gem_handles,
                      bo.pitches, bo.offsets, &bo.fb_id, 0);
  if (ret) {
    ALOGE("%s: drmModeAddFB2 failed: %s (errno %d)", __FUNCTION__,
          strerror(errno), errno);
    return -1;
  }
  return 0;
}

int DrmPresenter::clearDrmFB(hwc_drm_bo_t& bo) {
  int ret = 0;
  if (bo.fb_id) {
    if (drmModeRmFB(mFd.get(), bo.fb_id)) {
      ALOGE("%s: drmModeRmFB failed: %s (errno %d)", __FUNCTION__,
            strerror(errno), errno);
    }
    ret = -1;
  }
  if (bo.gem_handles[0]) {
    struct drm_gem_close gem_close = {};
    gem_close.handle = bo.gem_handles[0];
    if (drmIoctl(mFd.get(), DRM_IOCTL_GEM_CLOSE, &gem_close)) {
      ALOGE("%s: DRM_IOCTL_GEM_CLOSE failed: %s (errno %d)", __FUNCTION__,
            strerror(errno), errno);
    }
    ret = -1;
  }
  ALOGV("%s: drm FB %d", __FUNCTION__, bo.fb_id);
  return ret;
}

bool DrmPresenter::handleHotplug() {
  std::vector<DrmConnector> oldConnectors(mConnectors);
  {
    AutoReadLock lock(mStateMutex);
    oldConnectors.assign(mConnectors.begin(), mConnectors.end());
  }
  {
    AutoWriteLock lock(mStateMutex);
    resetDrmElementsLocked();
    if (!initDrmElementsLocked()) {
      ALOGE(
          "%s: failed to initialize drm elements during hotplug. Displays may "
          "not function correctly!",
          __FUNCTION__);
      return false;
    }
  }

  AutoReadLock lock(mStateMutex);
  for (int i = 0; i < mConnectors.size(); i++) {
    bool changed =
        oldConnectors[i].dpiX != mConnectors[i].dpiX ||
        oldConnectors[i].dpiY != mConnectors[i].dpiY ||
        oldConnectors[i].connection != mConnectors[i].connection ||
        oldConnectors[i].mMode.hdisplay != mConnectors[i].mMode.hdisplay ||
        oldConnectors[i].mMode.vdisplay != mConnectors[i].mMode.vdisplay;
    if (changed) {
      if (i == 0) {
        ALOGE(
            "%s: Ignoring changes to display:0 which is not configurable by "
            "multi-display interface.",
            __FUNCTION__);
        continue;
      }

      bool connected =
          mConnectors[i].connection == DRM_MODE_CONNECTED ? true : false;
      if (mHotplugCallback) {
        mHotplugCallback(connected, i, mConnectors[i].mMode.hdisplay,
                         mConnectors[i].mMode.vdisplay, mConnectors[i].dpiX,
                         mConnectors[i].dpiY,
                         mConnectors[i].mRefreshRateAsInteger);
      }
    }
  }
  return true;
}

std::tuple<HWC2::Error, base::unique_fd> DrmPresenter::flushToDisplay(
    int display, hwc_drm_bo_t& bo, base::borrowed_fd inSyncFd) {
  AutoReadLock lock(mStateMutex);

  DrmConnector& connector = mConnectors[display];
  DrmCrtc& crtc = mCrtcs[display];

  HWC2::Error error = HWC2::Error::None;

  drmModeAtomicReqPtr pset = drmModeAtomicAlloc();

  int ret;

  if (!crtc.mDidSetCrtc) {
    DEBUG_LOG("%s: Setting crtc.\n", __FUNCTION__);
    ret = drmModeAtomicAddProperty(pset, crtc.mId, crtc.mActivePropertyId, 1);
    if (ret < 0) {
      ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
    }
    ret = drmModeAtomicAddProperty(pset, crtc.mId, crtc.mModePropertyId,
                                   connector.mModeBlobId);
    if (ret < 0) {
      ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
    }
    ret = drmModeAtomicAddProperty(pset, connector.mId,
                                   connector.mCrtcPropertyId, crtc.mId);
    if (ret < 0) {
      ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
    }

    crtc.mDidSetCrtc = true;
  } else {
    DEBUG_LOG("%s: Already set crtc\n", __FUNCTION__);
  }

  int rawOutSyncFd;
  uint64_t outSyncFdUint =
      static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&rawOutSyncFd));

  ret = drmModeAtomicAddProperty(pset, crtc.mId, crtc.mOutFencePtrPropertyId,
                                 outSyncFdUint);
  if (ret < 0) {
    ALOGE("%s:%d: set OUT_FENCE_PTR failed %d errno %d\n", __FUNCTION__,
          __LINE__, ret, errno);
  }

  if (crtc.mPlaneId == -1) {
    ALOGE("%s:%d: no plane available for crtc id %" PRIu32, __FUNCTION__,
          __LINE__, crtc.mId);
    return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
  }

  DrmPlane& plane = mPlanes[crtc.mPlaneId];

  DEBUG_LOG("%s: set plane: plane id %d crtc id %d fbid %d bo w h %d %d\n",
            __FUNCTION__, plane.mId, crtc.mId, bo.fb_id, bo.width, bo.height);

  ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcPropertyId,
                                 crtc.mId);
  if (ret < 0) {
    ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
  }
  ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mInFenceFdPropertyId,
                                 inSyncFd.get());
  if (ret < 0) {
    ALOGE("%s:%d: set IN_FENCE_FD failed %d errno %d\n", __FUNCTION__, __LINE__,
          ret, errno);
  }
  ret =
      drmModeAtomicAddProperty(pset, plane.mId, plane.mFbPropertyId, bo.fb_id);
  if (ret < 0) {
    ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
  }
  ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcXPropertyId, 0);
  if (ret < 0) {
    ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
  }
  ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcYPropertyId, 0);
  if (ret < 0) {
    ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
  }
  ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcWPropertyId,
                                 bo.width);
  if (ret < 0) {
    ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
  }
  ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcHPropertyId,
                                 bo.height);
  if (ret < 0) {
    ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
  }
  ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mSrcXPropertyId, 0);
  if (ret < 0) {
    ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
  }
  ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mSrcYPropertyId, 0);
  if (ret < 0) {
    ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
  }
  ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mSrcWPropertyId,
                                 bo.width << 16);
  if (ret < 0) {
    ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
  }
  ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mSrcHPropertyId,
                                 bo.height << 16);
  if (ret < 0) {
    ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
  }

  uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
  ret = drmModeAtomicCommit(mFd.get(), pset, flags, 0);

  if (ret) {
    ALOGE("%s: Atomic commit failed with %d %d\n", __FUNCTION__, ret, errno);
    error = HWC2::Error::NoResources;
  }
  base::unique_fd outSyncFd(rawOutSyncFd);

  if (pset) {
    drmModeAtomicFree(pset);
  }

  DEBUG_LOG("%s: out fence: %d\n", __FUNCTION__, outSyncFd.get());
  return std::make_tuple(error, std::move(outSyncFd));
}

std::optional<std::vector<uint8_t>> DrmPresenter::getEdid(uint32_t id) {
  AutoReadLock lock(mStateMutex);

  if (mConnectors[id].mEdidBlobId == -1) {
    ALOGW("%s: EDID not supported", __func__);
    return std::nullopt;
  }
  drmModePropertyBlobPtr blob =
      drmModeGetPropertyBlob(mFd.get(), mConnectors[id].mEdidBlobId);
  if (!blob) {
    ALOGE("%s: fail to read EDID from DRM", __func__);
    return std::nullopt;
  }

  std::vector<uint8_t> edid;
  uint8_t* start = static_cast<uint8_t*>(blob->data);
  edid.insert(edid.begin(), start, start + blob->length);

  drmModeFreePropertyBlob(blob);

  return edid;
}

DrmBuffer::DrmBuffer(const native_handle_t* handle, DrmPresenter& DrmPresenter)
    : mDrmPresenter(DrmPresenter), mBo({}) {
  if (!convertBoInfo(handle)) {
    mDrmPresenter.getDrmFB(mBo);
  }
}

DrmBuffer::~DrmBuffer() { mDrmPresenter.clearDrmFB(mBo); }

int DrmBuffer::convertBoInfo(const native_handle_t* handle) {
  cros_gralloc_handle* gr_handle = (cros_gralloc_handle*)handle;
  if (!gr_handle) {
    ALOGE("%s: Null buffer handle", __FUNCTION__);
    return -1;
  }
  mBo.width = gr_handle->width;
  mBo.height = gr_handle->height;
  mBo.hal_format = gr_handle->droid_format;
  mBo.format = gr_handle->format;
  mBo.usage = gr_handle->usage;
  mBo.prime_fds[0] = gr_handle->fds[0];
  mBo.pitches[0] = gr_handle->strides[0];
  return 0;
}

std::tuple<HWC2::Error, base::unique_fd> DrmBuffer::flushToDisplay(
    int display, base::borrowed_fd inWaitSyncFd) {
  return mDrmPresenter.flushToDisplay(display, mBo, inWaitSyncFd);
}

DrmPresenter::DrmEventListener::DrmEventListener(DrmPresenter& presenter)
    : mPresenter(presenter) {}

DrmPresenter::DrmEventListener::~DrmEventListener() {}

bool DrmPresenter::DrmEventListener::init() {
  mEventFd = android::base::unique_fd(
      socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT));
  if (!mEventFd.ok()) {
    ALOGE("Failed to open uevent socket: %s", strerror(errno));
    return false;
  }
  struct sockaddr_nl addr;
  memset(&addr, 0, sizeof(addr));
  addr.nl_family = AF_NETLINK;
  addr.nl_pid = 0;
  addr.nl_groups = 0xFFFFFFFF;

  int ret = bind(mEventFd, (struct sockaddr*)&addr, sizeof(addr));
  if (ret) {
    ALOGE("Failed to bind uevent socket: %s", strerror(errno));
    return false;
  }

  FD_ZERO(&mMonitoredFds);
  FD_SET(mPresenter.mFd.get(), &mMonitoredFds);
  FD_SET(mEventFd.get(), &mMonitoredFds);
  mMaxFd = std::max(mPresenter.mFd.get(), mEventFd.get());

  return true;
}

bool DrmPresenter::DrmEventListener::threadLoop() {
  int ret;
  do {
    ret = select(mMaxFd + 1, &mMonitoredFds, NULL, NULL, NULL);
  } while (ret == -1 && errno == EINTR);

  // if (FD_ISSET(mPresenter.mFd, &mFds)) {
  //   TODO: handle drm related events
  // }

  if (FD_ISSET(mEventFd.get(), &mMonitoredFds)) {
    eventThreadLoop();
  }
  return true;
}

void DrmPresenter::DrmEventListener::eventThreadLoop() {
  char buffer[1024];
  int ret;

  struct timespec ts;
  uint64_t timestamp = 0;
  ret = clock_gettime(CLOCK_MONOTONIC, &ts);
  if (!ret) {
    timestamp = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
  } else {
    ALOGE("Failed to get monotonic clock on hotplug %d", ret);
  }

  while (true) {
    ret = read(mEventFd.get(), &buffer, sizeof(buffer));
    if (ret == 0) {
      return;
    } else if (ret < 0) {
      ALOGE("Got error reading uevent %d", ret);
      return;
    }

    bool drmEvent = false, hotplugEvent = false;
    for (int i = 0; i < ret;) {
      char* event = buffer + i;
      if (strcmp(event, "DEVTYPE=drm_minor")) {
        drmEvent = true;
      } else if (strcmp(event, "HOTPLUG=1")) {
        hotplugEvent = true;
      }

      i += strlen(event) + 1;
    }

    if (drmEvent && hotplugEvent) {
      processHotplug(timestamp);
    }
  }
}

void DrmPresenter::DrmEventListener::processHotplug(uint64_t timestamp) {
  ALOGD("DrmEventListener detected hotplug event %" PRIu64, timestamp);
  mPresenter.handleHotplug();
}
}  // namespace android
