drm_hwcomposer: Rework autofd

Motivation:

Current implementation of UniqueFd can be used in a different ways,
making analytical tracking of FD lifecycle much harder than it may be.
Keep this part clean is very important, since any wrong code may open
a hard-to-detect runtime bugs and fd leaks, which may accidentally slip
into the production.

Implementation:

1. Combine UniqueFd anf OutputFd into single class.
2. Reduce the API to be minimal and sufficient.
3. Document the API and use cases.
4. Move to utils/UniqueFd.h.
5. dup(fd) was replaced with fcntl(fd, F_DUPFD_CLOEXEC)) to
   address clang-tidy findings. Find more information at [1]

[1]: https://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-dup.html

Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
diff --git a/utils/UniqueFd.h b/utils/UniqueFd.h
new file mode 100644
index 0000000..1a390ba
--- /dev/null
+++ b/utils/UniqueFd.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015, 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.
+ */
+
+#ifndef UNIQUEFD_H_
+#define UNIQUEFD_H_
+
+#include <unistd.h>
+
+#include <memory>
+
+namespace android {
+
+/*
+ * Using UniqueFd:
+ * 1. Create UniqueFd object:
+ *    auto fd_obj = UniqueFd(open("SomeFile", xxx));
+ *
+ * 2. Check whether the fd_obj is empty:
+ *    if (!fd_obj) { return -errno; }
+ *
+ * 3. Accessing the file descriptor:
+ *    int ret = read(fd_obj.Get(), buf, buf_size);
+ *
+ * 4. Closing the file:
+ *    FD will be closed once execution leaves fd_obj scope (on any return,
+ *    exception, destruction of class/struct where object is member, etc.).
+ *    User can also force closing the fd_obj by calling:
+ *      fd_obj = UniqueFd();
+ *      // fd is closed and fd_obj is empty now.
+ *
+ * 5. File descriptor may be transferred to the code, which will close it after
+ *    using. This can be done in 2 ways:
+ *    a. Duplicate the fd, in this case both fds should be closed separately:
+ *      int out_fd = dup(fd_obj.Get();
+ *      ...
+ *      close(out_fd);
+ *    b. Transfer ownership, use this method if you do not need the fd anymore.
+ *      int out_fd = fd_obj.Release();
+ *      // fd_obj is empty now.
+ *      ...
+ *      close(out_fd);
+ *
+ * 6. Transferring fd into another UniqueFD object:
+ *    UniqueFd fd_obj_2 = std::move(fd_obj);
+ *    // fd_obj empty now
+ */
+
+constexpr int kEmptyFd = -1;
+
+class UniqueFd {
+ public:
+  UniqueFd() = default;
+  explicit UniqueFd(int fd) : fd_(fd){};
+
+  auto Release [[nodiscard]] () -> int {
+    return std::exchange(fd_, kEmptyFd);
+  }
+
+  auto Get [[nodiscard]] () const -> int {
+    return fd_;
+  }
+
+  explicit operator bool() const {
+    return fd_ != kEmptyFd;
+  }
+
+  ~UniqueFd() {
+    Set(kEmptyFd);
+  }
+
+  /* Allow move semantics */
+  UniqueFd(UniqueFd &&rhs) noexcept {
+    Set(rhs.Release());
+  }
+
+  auto operator=(UniqueFd &&rhs) noexcept -> UniqueFd & {
+    Set(rhs.Release());
+    return *this;
+  }
+
+  /* Disable copy semantics */
+  UniqueFd(const UniqueFd &) = delete;
+  auto operator=(const UniqueFd &) = delete;
+
+ private:
+  void Set(int new_fd) {
+    if (fd_ != kEmptyFd) {
+      close(fd_);
+    }
+    fd_ = new_fd;
+  }
+
+  int fd_ = kEmptyFd;
+};
+
+}  // namespace android
+
+#endif