Merge "Use Transform in InputDispatcher"
diff --git a/headers/media_plugin/media/openmax/OMX_VideoExt.h b/headers/media_plugin/media/openmax/OMX_VideoExt.h
index dc37bbd..e65b224 100644
--- a/headers/media_plugin/media/openmax/OMX_VideoExt.h
+++ b/headers/media_plugin/media/openmax/OMX_VideoExt.h
@@ -321,6 +321,46 @@
     OMX_VIDEO_DolbyVisionLevelmax     = 0x7FFFFFFF
 } OMX_VIDEO_DOLBYVISIONLEVELTYPE;
 
+/** AV1 Profile enum type */
+typedef enum OMX_VIDEO_AV1PROFILETYPE {
+    OMX_VIDEO_AV1ProfileMain8           = 0x00000001,
+    OMX_VIDEO_AV1ProfileMain10          = 0x00000002,
+    OMX_VIDEO_AV1ProfileMain10HDR10     = 0x00001000,
+    OMX_VIDEO_AV1ProfileMain10HDR10Plus = 0x00002000,
+    OMX_VIDEO_AV1ProfileUnknown         = 0x6EFFFFFF,
+    OMX_VIDEO_AV1ProfileMax             = 0x7FFFFFFF
+} OMX_VIDEO_AV1PROFILETYPE;
+
+/** AV1 Level enum type */
+typedef enum OMX_VIDEO_AV1LEVELTYPE {
+    OMX_VIDEO_AV1Level2         = 0x1,
+    OMX_VIDEO_AV1Level21        = 0x2,
+    OMX_VIDEO_AV1Level22        = 0x4,
+    OMX_VIDEO_AV1Level23        = 0x8,
+    OMX_VIDEO_AV1Level3         = 0x10,
+    OMX_VIDEO_AV1Level31        = 0x20,
+    OMX_VIDEO_AV1Level32        = 0x40,
+    OMX_VIDEO_AV1Level33        = 0x80,
+    OMX_VIDEO_AV1Level4         = 0x100,
+    OMX_VIDEO_AV1Level41        = 0x200,
+    OMX_VIDEO_AV1Level42        = 0x400,
+    OMX_VIDEO_AV1Level43        = 0x800,
+    OMX_VIDEO_AV1Level5         = 0x1000,
+    OMX_VIDEO_AV1Level51        = 0x2000,
+    OMX_VIDEO_AV1Level52        = 0x4000,
+    OMX_VIDEO_AV1Level53        = 0x8000,
+    OMX_VIDEO_AV1Level6         = 0x10000,
+    OMX_VIDEO_AV1Level61        = 0x20000,
+    OMX_VIDEO_AV1Level62        = 0x40000,
+    OMX_VIDEO_AV1Level63        = 0x80000,
+    OMX_VIDEO_AV1Level7         = 0x100000,
+    OMX_VIDEO_AV1Level71        = 0x200000,
+    OMX_VIDEO_AV1Level72        = 0x400000,
+    OMX_VIDEO_AV1Level73        = 0x800000,
+    OMX_VIDEO_AV1LevelUnknown   = 0x6EFFFFFF,
+    OMX_VIDEO_AV1LevelMax       = 0x7FFFFFFF
+} OMX_VIDEO_AV1LEVELTYPE;
+
 /**
  * Structure for configuring video compression intra refresh period
  *
diff --git a/include/input/Flags.h b/include/input/Flags.h
index f3198c9..f43829f 100644
--- a/include/input/Flags.h
+++ b/include/input/Flags.h
@@ -16,6 +16,7 @@
 
 #include <android-base/stringprintf.h>
 
+#include <array>
 #include <cstdint>
 #include <optional>
 #include <string>
@@ -28,6 +29,69 @@
 
 namespace android {
 
+namespace details {
+template <typename F, F V>
+constexpr std::optional<std::string_view> enum_value_name() {
+    // Should look something like (but all on one line):
+    //   std::optional<std::string_view>
+    //   android::details::enum_value_name()
+    //   [F = android::test::TestFlags, V = android::test::TestFlags::ONE]
+    std::string_view view = __PRETTY_FUNCTION__;
+    size_t templateStart = view.rfind("[");
+    size_t templateEnd = view.rfind("]");
+    if (templateStart == std::string::npos || templateEnd == std::string::npos) {
+        return std::nullopt;
+    }
+
+    // Extract the template parameters without the enclosing braces.
+    // Example (cont'd): F = android::test::TestFlags, V = android::test::TestFlags::ONE
+    view = view.substr(templateStart + 1, templateEnd - templateStart - 1);
+    size_t valStart = view.rfind("V = ");
+    if (valStart == std::string::npos) {
+        return std::nullopt;
+    }
+
+    // Example (cont'd): V = android::test::TestFlags::ONE
+    view = view.substr(valStart);
+    size_t nameStart = view.rfind("::");
+    if (nameStart == std::string::npos) {
+        return std::nullopt;
+    }
+
+    // Chop off the initial "::"
+    nameStart += 2;
+    return view.substr(nameStart);
+}
+
+template <typename F>
+inline constexpr auto flag_count = sizeof(F) * __CHAR_BIT__;
+
+template <typename F, typename T, T... I>
+constexpr auto generate_flag_values(std::integer_sequence<T, I...> seq) {
+    constexpr int count = seq.size();
+
+    std::array<F, count> values{};
+    for (int i = 0, v = 0; v < count; ++i) {
+        values[v++] = static_cast<F>(T{1} << i);
+    }
+
+    return values;
+}
+
+template <typename F>
+inline constexpr auto flag_values = generate_flag_values<F>(
+        std::make_integer_sequence<std::underlying_type_t<F>, flag_count<F>>{});
+
+template <typename F, std::size_t... I>
+constexpr auto generate_flag_names(std::index_sequence<I...>) noexcept {
+    return std::array<std::optional<std::string_view>, sizeof...(I)>{
+            {enum_value_name<F, flag_values<F>[I]>()...}};
+}
+
+template <typename F>
+inline constexpr auto flag_names =
+        generate_flag_names<F>(std::make_index_sequence<flag_count<F>>{});
+
 // A trait for determining whether a type is specifically an enum class or not.
 template <typename T, bool = std::is_enum_v<T>>
 struct is_enum_class : std::false_type {};
@@ -40,71 +104,149 @@
 
 template <typename T>
 inline constexpr bool is_enum_class_v = is_enum_class<T>::value;
+} // namespace details
+
+template <auto V>
+constexpr auto flag_name() {
+    using F = decltype(V);
+    return details::enum_value_name<F, V>();
+}
+
+template <typename F>
+constexpr std::optional<std::string_view> flag_name(F flag) {
+    using U = std::underlying_type_t<F>;
+    auto idx = __builtin_ctzl(static_cast<U>(flag));
+    return details::flag_names<F>[idx];
+}
 
 /* A class for handling flags defined by an enum or enum class in a type-safe way. */
-template <class F, typename = std::enable_if_t<std::is_enum_v<F>>>
+template <typename F>
 class Flags {
     // F must be an enum or its underlying type is undefined. Theoretically we could specialize this
     // further to avoid this restriction but in general we want to encourage the use of enums
     // anyways.
+    static_assert(std::is_enum_v<F>, "Flags type must be an enum");
     using U = typename std::underlying_type_t<F>;
 
 public:
-    constexpr Flags(F f) : flags(static_cast<U>(f)) {}
-    constexpr Flags() : flags(0) {}
-    constexpr Flags(const Flags<F>& f) : flags(f.flags) {}
+    constexpr Flags(F f) : mFlags(static_cast<U>(f)) {}
+    constexpr Flags() : mFlags(0) {}
+    constexpr Flags(const Flags<F>& f) : mFlags(f.mFlags) {}
 
     // Provide a non-explicit construct for non-enum classes since they easily convert to their
     // underlying types (e.g. when used with bitwise operators). For enum classes, however, we
     // should force them to be explicitly constructed from their underlying types to make full use
     // of the type checker.
     template <typename T = U>
-    constexpr Flags(T t, typename std::enable_if_t<!is_enum_class_v<F>, T>* = nullptr) : flags(t) {}
+    constexpr Flags(T t, typename std::enable_if_t<!details::is_enum_class_v<F>, T>* = nullptr)
+          : mFlags(t) {}
     template <typename T = U>
-    explicit constexpr Flags(T t, typename std::enable_if_t<is_enum_class_v<F>, T>* = nullptr)
-          : flags(t) {}
+    explicit constexpr Flags(T t,
+                             typename std::enable_if_t<details::is_enum_class_v<F>, T>* = nullptr)
+          : mFlags(t) {}
+
+    class Iterator {
+        // The type can't be larger than 64-bits otherwise it won't fit in BitSet64.
+        static_assert(sizeof(U) <= sizeof(uint64_t));
+
+    public:
+        Iterator(Flags<F> flags) : mRemainingFlags(flags.mFlags) { (*this)++; }
+        Iterator() : mRemainingFlags(0), mCurrFlag(static_cast<F>(0)) {}
+
+        // Pre-fix ++
+        Iterator& operator++() {
+            if (mRemainingFlags.isEmpty()) {
+                mCurrFlag = static_cast<F>(0);
+            } else {
+                uint64_t bit = mRemainingFlags.clearLastMarkedBit(); // counts from left
+                const U flag = 1 << (64 - bit - 1);
+                mCurrFlag = static_cast<F>(flag);
+            }
+            return *this;
+        }
+
+        // Post-fix ++
+        Iterator operator++(int) {
+            Iterator iter = *this;
+            ++*this;
+            return iter;
+        }
+
+        bool operator==(Iterator other) const {
+            return mCurrFlag == other.mCurrFlag && mRemainingFlags == other.mRemainingFlags;
+        }
+
+        bool operator!=(Iterator other) const { return !(*this == other); }
+
+        F operator*() { return mCurrFlag; }
+
+        // iterator traits
+
+        // In the future we could make this a bidirectional const iterator instead of a forward
+        // iterator but it doesn't seem worth the added complexity at this point. This could not,
+        // however, be made a non-const iterator as assigning one flag to another is a non-sensical
+        // operation.
+        using iterator_category = std::input_iterator_tag;
+        using value_type = F;
+        // Per the C++ spec, because input iterators are not assignable the iterator's reference
+        // type does not actually need to be a reference. In fact, making it a reference would imply
+        // that modifying it would change the underlying Flags object, which is obviously wrong for
+        // the same reason this can't be a non-const iterator.
+        using reference = F;
+        using difference_type = void;
+        using pointer = void;
+
+    private:
+        BitSet64 mRemainingFlags;
+        F mCurrFlag;
+    };
+
     /*
      * Tests whether the given flag is set.
      */
     bool test(F flag) const {
         U f = static_cast<U>(flag);
-        return (f & flags) == f;
+        return (f & mFlags) == f;
     }
 
     /* Tests whether any of the given flags are set */
-    bool any(Flags<F> f) { return (flags & f.flags) != 0; }
+    bool any(Flags<F> f) { return (mFlags & f.mFlags) != 0; }
 
     /* Tests whether all of the given flags are set */
-    bool all(Flags<F> f) { return (flags & f.flags) == f.flags; }
+    bool all(Flags<F> f) { return (mFlags & f.mFlags) == f.mFlags; }
 
-    Flags<F> operator|(Flags<F> rhs) const { return static_cast<F>(flags | rhs.flags); }
+    Flags<F> operator|(Flags<F> rhs) const { return static_cast<F>(mFlags | rhs.mFlags); }
     Flags<F>& operator|=(Flags<F> rhs) {
-        flags = flags | rhs.flags;
+        mFlags = mFlags | rhs.mFlags;
         return *this;
     }
 
-    Flags<F> operator&(Flags<F> rhs) const { return static_cast<F>(flags & rhs.flags); }
+    Flags<F> operator&(Flags<F> rhs) const { return static_cast<F>(mFlags & rhs.mFlags); }
     Flags<F>& operator&=(Flags<F> rhs) {
-        flags = flags & rhs.flags;
+        mFlags = mFlags & rhs.mFlags;
         return *this;
     }
 
-    Flags<F> operator^(Flags<F> rhs) const { return static_cast<F>(flags ^ rhs.flags); }
+    Flags<F> operator^(Flags<F> rhs) const { return static_cast<F>(mFlags ^ rhs.mFlags); }
     Flags<F>& operator^=(Flags<F> rhs) {
-        flags = flags ^ rhs.flags;
+        mFlags = mFlags ^ rhs.mFlags;
         return *this;
     }
 
-    Flags<F> operator~() { return static_cast<F>(~flags); }
+    Flags<F> operator~() { return static_cast<F>(~mFlags); }
 
-    bool operator==(Flags<F> rhs) const { return flags == rhs.flags; }
+    bool operator==(Flags<F> rhs) const { return mFlags == rhs.mFlags; }
     bool operator!=(Flags<F> rhs) const { return !operator==(rhs); }
 
     Flags<F>& operator=(const Flags<F>& rhs) {
-        flags = rhs.flags;
+        mFlags = rhs.mFlags;
         return *this;
     }
 
+    Iterator begin() const { return Iterator(*this); }
+
+    Iterator end() const { return Iterator(); }
+
     /*
      * Returns the stored set of flags.
      *
@@ -112,24 +254,18 @@
      * the value is no longer necessarily a strict member of the enum since the returned value could
      * be multiple enum variants OR'd together.
      */
-    U get() const { return flags; }
+    U get() const { return mFlags; }
 
-    std::string string() const { return string(defaultStringify); }
-
-    std::string string(std::function<std::optional<std::string>(F)> stringify) const {
-        // The type can't be larger than 64-bits otherwise it won't fit in BitSet64.
-        static_assert(sizeof(U) <= sizeof(uint64_t));
+    std::string string() const {
         std::string result;
         bool first = true;
         U unstringified = 0;
-        for (BitSet64 bits(flags); !bits.isEmpty();) {
-            uint64_t bit = bits.clearLastMarkedBit(); // counts from left
-            const U flag = 1 << (64 - bit - 1);
-            std::optional<std::string> flagString = stringify(static_cast<F>(flag));
+        for (const F f : *this) {
+            std::optional<std::string_view> flagString = flag_name(f);
             if (flagString) {
                 appendFlag(result, flagString.value(), first);
             } else {
-                unstringified |= flag;
+                unstringified |= static_cast<U>(f);
             }
         }
 
@@ -145,10 +281,9 @@
     }
 
 private:
-    U flags;
+    U mFlags;
 
-    static std::optional<std::string> defaultStringify(F) { return std::nullopt; }
-    static void appendFlag(std::string& str, const std::string& flag, bool& first) {
+    static void appendFlag(std::string& str, const std::string_view& flag, bool& first) {
         if (first) {
             first = false;
         } else {
@@ -162,12 +297,12 @@
 // as flags. In order to use these, add them via a `using namespace` declaration.
 namespace flag_operators {
 
-template <typename F, typename = std::enable_if_t<is_enum_class_v<F>>>
+template <typename F, typename = std::enable_if_t<details::is_enum_class_v<F>>>
 inline Flags<F> operator~(F f) {
     using U = typename std::underlying_type_t<F>;
     return static_cast<F>(~static_cast<U>(f));
 }
-template <typename F, typename = std::enable_if_t<is_enum_class_v<F>>>
+template <typename F, typename = std::enable_if_t<details::is_enum_class_v<F>>>
 Flags<F> operator|(F lhs, F rhs) {
     using U = typename std::underlying_type_t<F>;
     return static_cast<F>(static_cast<U>(lhs) | static_cast<U>(rhs));
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 09cebef..24f8e77 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -183,18 +183,6 @@
     }
 };
 
-struct InputChannelInfo : public Parcelable {
-    std::string mName;
-    android::base::unique_fd mFd;
-    sp<IBinder> mToken;
-
-    InputChannelInfo() = default;
-    InputChannelInfo(const std::string& name, android::base::unique_fd fd, sp<IBinder> token)
-          : mName(name), mFd(std::move(fd)), mToken(token){};
-    status_t readFromParcel(const android::Parcel* parcel) override;
-    status_t writeToParcel(android::Parcel* parcel) const override;
-};
-
 /*
  * An input channel consists of a local unix domain socket used to send and receive
  * input messages across processes.  Each channel has a descriptive name for debugging purposes.
@@ -203,14 +191,15 @@
  *
  * The input channel is closed when all references to it are released.
  */
-class InputChannel : public RefBase {
+class InputChannel : public Parcelable {
 public:
-    InputChannel();
+    static std::unique_ptr<InputChannel> create(const std::string& name,
+                                                android::base::unique_fd fd, sp<IBinder> token);
+    InputChannel() = default;
+    InputChannel(const InputChannel& other)
+          : mName(other.mName), mFd(::dup(other.mFd)), mToken(other.mToken){};
+    InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token);
     virtual ~InputChannel();
-
-    static sp<InputChannel> create(const std::string& name, android::base::unique_fd fd,
-                                   sp<IBinder> token);
-
     /**
      * Create a pair of input channels.
      * The two returned input channels are equivalent, and are labeled as "server" and "client"
@@ -219,12 +208,12 @@
      * Return OK on success.
      */
     static status_t openInputChannelPair(const std::string& name,
-            sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel);
+                                         std::unique_ptr<InputChannel>& outServerChannel,
+                                         std::unique_ptr<InputChannel>& outClientChannel);
 
-    inline std::string getName() const { return mInfo.mName; }
-    inline int getFd() const { return mInfo.mFd.get(); }
-    inline sp<IBinder> getToken() const { return mInfo.mToken; }
-    inline InputChannelInfo& getInfo() { return mInfo; }
+    inline std::string getName() const { return mName; }
+    inline const android::base::unique_fd& getFd() const { return mFd; }
+    inline sp<IBinder> getToken() const { return mToken; }
 
     /* Send a message to the other endpoint.
      *
@@ -252,11 +241,10 @@
     status_t receiveMessage(InputMessage* msg);
 
     /* Return a new object that has a duplicate of this channel's fd. */
-    sp<InputChannel> dup() const;
+    std::unique_ptr<InputChannel> dup() const;
 
-    status_t readFromParcel(const android::Parcel* parcel);
-
-    status_t writeToParcel(android::Parcel* parcel) const;
+    status_t readFromParcel(const android::Parcel* parcel) override;
+    status_t writeToParcel(android::Parcel* parcel) const override;
 
     /**
      * The connection token is used to identify the input connection, i.e.
@@ -273,22 +261,23 @@
     sp<IBinder> getConnectionToken() const;
 
     bool operator==(const InputChannel& inputChannel) const {
-        struct stat lhsInfo, rhsInfo;
-        if (fstat(mInfo.mFd.get(), &lhsInfo) != 0) {
+        struct stat lhs, rhs;
+        if (fstat(mFd.get(), &lhs) != 0) {
             return false;
         }
-        if (fstat(inputChannel.getFd(), &rhsInfo) != 0) {
+        if (fstat(inputChannel.getFd(), &rhs) != 0) {
             return false;
         }
         // If file descriptors are pointing to same inode they are duplicated fds.
-        return inputChannel.getName() == getName() &&
-                inputChannel.getConnectionToken() == mInfo.mToken &&
-                lhsInfo.st_ino == rhsInfo.st_ino;
+        return inputChannel.getName() == getName() && inputChannel.getConnectionToken() == mToken &&
+                lhs.st_ino == rhs.st_ino;
     }
 
 private:
-    InputChannel(const std::string& name, android::base::unique_fd fd, sp<IBinder> token);
-    InputChannelInfo mInfo;
+    std::string mName;
+    android::base::unique_fd mFd;
+
+    sp<IBinder> mToken;
 };
 
 /*
@@ -297,13 +286,13 @@
 class InputPublisher {
 public:
     /* Creates a publisher associated with an input channel. */
-    explicit InputPublisher(const sp<InputChannel>& channel);
+    explicit InputPublisher(const std::shared_ptr<InputChannel>& channel);
 
     /* Destroys the publisher and releases its input channel. */
     ~InputPublisher();
 
     /* Gets the underlying input channel. */
-    inline sp<InputChannel> getChannel() { return mChannel; }
+    inline std::shared_ptr<InputChannel> getChannel() { return mChannel; }
 
     /* Publishes a key event to the input channel.
      *
@@ -360,7 +349,7 @@
     status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled);
 
 private:
-    sp<InputChannel> mChannel;
+    std::shared_ptr<InputChannel> mChannel;
 };
 
 /*
@@ -369,13 +358,13 @@
 class InputConsumer {
 public:
     /* Creates a consumer associated with an input channel. */
-    explicit InputConsumer(const sp<InputChannel>& channel);
+    explicit InputConsumer(const std::shared_ptr<InputChannel>& channel);
 
     /* Destroys the consumer and releases its input channel. */
     ~InputConsumer();
 
     /* Gets the underlying input channel. */
-    inline sp<InputChannel> getChannel() { return mChannel; }
+    inline std::shared_ptr<InputChannel> getChannel() { return mChannel; }
 
     /* Consumes an input event from the input channel and copies its contents into
      * an InputEvent object created using the specified factory.
@@ -451,8 +440,7 @@
     // True if touch resampling is enabled.
     const bool mResampleTouch;
 
-    // The input channel.
-    sp<InputChannel> mChannel;
+    std::shared_ptr<InputChannel> mChannel;
 
     // The current input message.
     InputMessage mMsg;
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h
index d82f6fe..8a752c1 100644
--- a/include/input/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -201,8 +201,6 @@
     status_t writeToParcel(android::Parcel* parcel) const override;
 
     status_t readFromParcel(const android::Parcel* parcel) override;
-
-    static std::optional<std::string> flagToString(Flag f);
 };
 
 /*
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index f3861bb..acc1e67 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -32,6 +32,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <mutex>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -73,38 +74,49 @@
 
 sp<ProcessState> ProcessState::self()
 {
-    Mutex::Autolock _l(gProcessMutex);
-    if (gProcess != nullptr) {
-        return gProcess;
-    }
-    gProcess = new ProcessState(kDefaultDriver);
-    return gProcess;
+    return init(kDefaultDriver, false /*requireDefault*/);
 }
 
 sp<ProcessState> ProcessState::initWithDriver(const char* driver)
 {
-    Mutex::Autolock _l(gProcessMutex);
-    if (gProcess != nullptr) {
-        // Allow for initWithDriver to be called repeatedly with the same
-        // driver.
-        if (!strcmp(gProcess->getDriverName().c_str(), driver)) {
-            return gProcess;
-        }
-        LOG_ALWAYS_FATAL("ProcessState was already initialized.");
-    }
-
-    if (access(driver, R_OK) == -1) {
-        ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
-        driver = "/dev/binder";
-    }
-
-    gProcess = new ProcessState(driver);
-    return gProcess;
+    return init(driver, true /*requireDefault*/);
 }
 
 sp<ProcessState> ProcessState::selfOrNull()
 {
-    Mutex::Autolock _l(gProcessMutex);
+    return init(nullptr, false /*requireDefault*/);
+}
+
+sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
+{
+    [[clang::no_destroy]] static sp<ProcessState> gProcess;
+    [[clang::no_destroy]] static std::mutex gProcessMutex;
+
+    if (driver == nullptr) {
+        std::lock_guard<std::mutex> l(gProcessMutex);
+        return gProcess;
+    }
+
+    [[clang::no_destroy]] static std::once_flag gProcessOnce;
+    std::call_once(gProcessOnce, [&](){
+        if (access(driver, R_OK) == -1) {
+            ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
+            driver = "/dev/binder";
+        }
+
+        std::lock_guard<std::mutex> l(gProcessMutex);
+        gProcess = new ProcessState(driver);
+    });
+
+    if (requireDefault) {
+        // Detect if we are trying to initialize with a different driver, and
+        // consider that an error. ProcessState will only be initialized once above.
+        LOG_ALWAYS_FATAL_IF(gProcess->getDriverName() != driver,
+                            "ProcessState was already initialized with %s,"
+                            " can't initialize with %s.",
+                            gProcess->getDriverName().c_str(), driver);
+    }
+
     return gProcess;
 }
 
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index 779ed41..db0f1c7 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -68,9 +68,4 @@
 TextOutput& aout(*new FdTextOutput(STDOUT_FILENO));
 TextOutput& aerr(*new FdTextOutput(STDERR_FILENO));
 
-// ------------ ProcessState.cpp
-
-Mutex& gProcessMutex = *new Mutex;
-sp<ProcessState> gProcess;
-
 }   // namespace android
diff --git a/libs/binder/Static.h b/libs/binder/Static.h
index f8e0ee5..83524e8 100644
--- a/libs/binder/Static.h
+++ b/libs/binder/Static.h
@@ -27,8 +27,4 @@
 // For TextStream.cpp
 extern Vector<int32_t> gTextBuffers;
 
-// For ProcessState.cpp
-extern Mutex& gProcessMutex;
-extern sp<ProcessState> gProcess;
-
 }   // namespace android
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index e57ff1c..9f5346a 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -42,6 +42,8 @@
      * any call to ProcessState::self(). The default is /dev/vndbinder
      * for processes built with the VNDK and /dev/binder for those
      * which are not.
+     *
+     * If this is called with nullptr, the behavior is the same as selfOrNull.
      */
     static  sp<ProcessState>    initWithDriver(const char *driver);
 
@@ -90,6 +92,8 @@
             void setCallRestriction(CallRestriction restriction);
 
 private:
+    static  sp<ProcessState>    init(const char *defaultDriver, bool requireDefault);
+
     friend class IPCThreadState;
     
             explicit            ProcessState(const char* driver);
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 383d591..cca8ddd 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -68,11 +68,12 @@
 public:
     InputSurface(const sp<SurfaceControl> &sc, int width, int height) {
         mSurfaceControl = sc;
-
-        InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
+        std::unique_ptr<InputChannel> clientChannel;
+        InputChannel::openInputChannelPair("testchannels", mServerChannel, clientChannel);
+        mClientChannel = std::move(clientChannel);
 
         mInputFlinger = getInputFlinger();
-        mInputFlinger->registerInputChannel(mServerChannel->getInfo());
+        mInputFlinger->registerInputChannel(*mServerChannel);
 
         populateInputInfo(width, height);
 
@@ -154,7 +155,7 @@
         EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS);
     }
 
-    ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel->getInfo()); }
+    ~InputSurface() { mInputFlinger->unregisterInputChannel(*mServerChannel); }
 
     void doTransaction(std::function<void(SurfaceComposerClient::Transaction&,
                     const sp<SurfaceControl>&)> transactionBody) {
@@ -211,7 +212,8 @@
     }
 public:
     sp<SurfaceControl> mSurfaceControl;
-    sp<InputChannel> mServerChannel, mClientChannel;
+    std::unique_ptr<InputChannel> mServerChannel;
+    std::shared_ptr<InputChannel> mClientChannel;
     sp<IInputFlinger> mInputFlinger;
 
     InputWindowInfo mInputInfo;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 60ad578..8dcc415 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -241,65 +241,42 @@
     }
 }
 
-// --- InputChannelInfo ---
-
-status_t InputChannelInfo::writeToParcel(android::Parcel* parcel) const {
-    if (parcel == nullptr) {
-        ALOGE("%s: Null parcel", __func__);
-        return BAD_VALUE;
-    }
-    status_t status = parcel->writeStrongBinder(mToken)
-            ?: parcel->writeUtf8AsUtf16(mName) ?: parcel->writeUniqueFileDescriptor(mFd);
-    return status;
-}
-
-status_t InputChannelInfo::readFromParcel(const android::Parcel* parcel) {
-    if (parcel == nullptr) {
-        ALOGE("%s: Null parcel", __func__);
-        return BAD_VALUE;
-    }
-    mToken = parcel->readStrongBinder();
-    status_t status = parcel->readUtf8FromUtf16(&mName) ?: parcel->readUniqueFileDescriptor(&mFd);
-    return status;
-}
-
 // --- InputChannel ---
 
-sp<InputChannel> InputChannel::create(const std::string& name, android::base::unique_fd fd,
-                                      sp<IBinder> token) {
+std::unique_ptr<InputChannel> InputChannel::create(const std::string& name,
+                                                   android::base::unique_fd fd, sp<IBinder> token) {
     const int result = fcntl(fd, F_SETFL, O_NONBLOCK);
     if (result != 0) {
         LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(),
                          strerror(errno));
         return nullptr;
     }
-    return new InputChannel(name, std::move(fd), token);
+    // using 'new' to access a non-public constructor
+    return std::unique_ptr<InputChannel>(new InputChannel(name, std::move(fd), token));
 }
 
-InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd, sp<IBinder> token)
-      : mInfo(name, std::move(fd), token) {
+InputChannel::InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token)
+      : mName(std::move(name)), mFd(std::move(fd)), mToken(std::move(token)) {
     if (DEBUG_CHANNEL_LIFECYCLE) {
-        ALOGD("Input channel constructed: name='%s', fd=%d", mInfo.mName.c_str(), mInfo.mFd.get());
+        ALOGD("Input channel constructed: name='%s', fd=%d", getName().c_str(), getFd().get());
     }
 }
 
-InputChannel::InputChannel() {}
-
 InputChannel::~InputChannel() {
     if (DEBUG_CHANNEL_LIFECYCLE) {
-        ALOGD("Input channel destroyed: name='%s', fd=%d", getName().c_str(), getFd());
+        ALOGD("Input channel destroyed: name='%s', fd=%d", getName().c_str(), getFd().get());
     }
 }
 
 status_t InputChannel::openInputChannelPair(const std::string& name,
-        sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
+                                            std::unique_ptr<InputChannel>& outServerChannel,
+                                            std::unique_ptr<InputChannel>& outClientChannel) {
     int sockets[2];
     if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
         status_t result = -errno;
-        ALOGE("channel '%s' ~ Could not create socket pair.  errno=%d",
-                name.c_str(), errno);
-        outServerChannel.clear();
-        outClientChannel.clear();
+        ALOGE("channel '%s' ~ Could not create socket pair.  errno=%d", name.c_str(), errno);
+        outServerChannel.reset();
+        outClientChannel.reset();
         return result;
     }
 
@@ -399,10 +376,10 @@
     return OK;
 }
 
-sp<InputChannel> InputChannel::dup() const {
+std::unique_ptr<InputChannel> InputChannel::dup() const {
     android::base::unique_fd newFd(::dup(getFd()));
     if (!newFd.ok()) {
-        ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), getName().c_str(),
+        ALOGE("Could not duplicate fd %i for channel %s: %s", getFd().get(), getName().c_str(),
               strerror(errno));
         const bool hitFdLimit = errno == EMFILE || errno == ENFILE;
         // If this process is out of file descriptors, then throwing that might end up exploding
@@ -417,22 +394,30 @@
 }
 
 status_t InputChannel::writeToParcel(android::Parcel* parcel) const {
-    return mInfo.writeToParcel(parcel);
+    if (parcel == nullptr) {
+        ALOGE("%s: Null parcel", __func__);
+        return BAD_VALUE;
+    }
+    return parcel->writeStrongBinder(mToken)
+            ?: parcel->writeUtf8AsUtf16(mName) ?: parcel->writeUniqueFileDescriptor(mFd);
 }
 
 status_t InputChannel::readFromParcel(const android::Parcel* parcel) {
-    return mInfo.readFromParcel(parcel);
+    if (parcel == nullptr) {
+        ALOGE("%s: Null parcel", __func__);
+        return BAD_VALUE;
+    }
+    mToken = parcel->readStrongBinder();
+    return parcel->readUtf8FromUtf16(&mName) ?: parcel->readUniqueFileDescriptor(&mFd);
 }
 
 sp<IBinder> InputChannel::getConnectionToken() const {
-    return mInfo.mToken;
+    return mToken;
 }
 
 // --- InputPublisher ---
 
-InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
-        mChannel(channel) {
-}
+InputPublisher::InputPublisher(const std::shared_ptr<InputChannel>& channel) : mChannel(channel) {}
 
 InputPublisher::~InputPublisher() {
 }
@@ -596,10 +581,8 @@
 
 // --- InputConsumer ---
 
-InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
-        mResampleTouch(isTouchResamplingEnabled()),
-        mChannel(channel), mMsgDeferred(false) {
-}
+InputConsumer::InputConsumer(const std::shared_ptr<InputChannel>& channel)
+      : mResampleTouch(isTouchResamplingEnabled()), mChannel(channel), mMsgDeferred(false) {}
 
 InputConsumer::~InputConsumer() {
 }
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index d5d35e6..116b963 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -208,107 +208,4 @@
 void InputWindowHandle::updateFrom(sp<InputWindowHandle> handle) {
     mInfo = handle->mInfo;
 }
-
-std::optional<std::string> InputWindowInfo::flagToString(Flag flag) {
-    switch (flag) {
-        case InputWindowInfo::Flag::ALLOW_LOCK_WHILE_SCREEN_ON: {
-            return "ALLOW_LOCK_WHILE_SCREEN_ON";
-        }
-        case InputWindowInfo::Flag::DIM_BEHIND: {
-            return "DIM_BEHIND";
-        }
-        case InputWindowInfo::Flag::BLUR_BEHIND: {
-            return "BLUR_BEHIND";
-        }
-        case InputWindowInfo::Flag::NOT_FOCUSABLE: {
-            return "NOT_FOCUSABLE";
-        }
-        case InputWindowInfo::Flag::NOT_TOUCHABLE: {
-            return "NOT_TOUCHABLE";
-        }
-        case InputWindowInfo::Flag::NOT_TOUCH_MODAL: {
-            return "NOT_TOUCH_MODAL";
-        }
-        case InputWindowInfo::Flag::TOUCHABLE_WHEN_WAKING: {
-            return "TOUCHABLE_WHEN_WAKING";
-        }
-        case InputWindowInfo::Flag::KEEP_SCREEN_ON: {
-            return "KEEP_SCREEN_ON";
-        }
-        case InputWindowInfo::Flag::LAYOUT_IN_SCREEN: {
-            return "LAYOUT_IN_SCREEN";
-        }
-        case InputWindowInfo::Flag::LAYOUT_NO_LIMITS: {
-            return "LAYOUT_NO_LIMITS";
-        }
-        case InputWindowInfo::Flag::FULLSCREEN: {
-            return "FULLSCREEN";
-        }
-        case InputWindowInfo::Flag::FORCE_NOT_FULLSCREEN: {
-            return "FORCE_NOT_FULLSCREEN";
-        }
-        case InputWindowInfo::Flag::DITHER: {
-            return "DITHER";
-        }
-        case InputWindowInfo::Flag::SECURE: {
-            return "SECURE";
-        }
-        case InputWindowInfo::Flag::SCALED: {
-            return "SCALED";
-        }
-        case InputWindowInfo::Flag::IGNORE_CHEEK_PRESSES: {
-            return "IGNORE_CHEEK_PRESSES";
-        }
-        case InputWindowInfo::Flag::LAYOUT_INSET_DECOR: {
-            return "LAYOUT_INSET_DECOR";
-        }
-        case InputWindowInfo::Flag::ALT_FOCUSABLE_IM: {
-            return "ALT_FOCUSABLE_IM";
-        }
-        case InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH: {
-            return "WATCH_OUTSIDE_TOUCH";
-        }
-        case InputWindowInfo::Flag::SHOW_WHEN_LOCKED: {
-            return "SHOW_WHEN_LOCKED";
-        }
-        case InputWindowInfo::Flag::SHOW_WALLPAPER: {
-            return "SHOW_WALLPAPER";
-        }
-        case InputWindowInfo::Flag::TURN_SCREEN_ON: {
-            return "TURN_SCREEN_ON";
-        }
-        case InputWindowInfo::Flag::DISMISS_KEYGUARD: {
-            return "DISMISS_KEYGUARD";
-        }
-        case InputWindowInfo::Flag::SPLIT_TOUCH: {
-            return "SPLIT_TOUCH";
-        }
-        case InputWindowInfo::Flag::HARDWARE_ACCELERATED: {
-            return "HARDWARE_ACCELERATED";
-        }
-        case InputWindowInfo::Flag::LAYOUT_IN_OVERSCAN: {
-            return "LAYOUT_IN_OVERSCAN";
-        }
-        case InputWindowInfo::Flag::TRANSLUCENT_STATUS: {
-            return "TRANSLUCENT_STATUS";
-        }
-        case InputWindowInfo::Flag::TRANSLUCENT_NAVIGATION: {
-            return "TRANSLUCENT_NAVIGATION";
-        }
-        case InputWindowInfo::Flag::LOCAL_FOCUS_MODE: {
-            return "LOCAL_FOCUS_MODE";
-        }
-        case InputWindowInfo::Flag::SLIPPERY: {
-            return "SLIPPERY";
-        }
-        case InputWindowInfo::Flag::LAYOUT_ATTACHED_IN_DECOR: {
-            return "LAYOUT_ATTACHED_IN_DECOR";
-        }
-        case InputWindowInfo::Flag::DRAWS_SYSTEM_BAR_BACKGROUNDS: {
-            return "DRAWS_SYSTEM_BAR_BACKGROUNDS";
-        }
-    }
-    return std::nullopt;
-}
-
 } // namespace android
diff --git a/libs/input/android/InputChannelInfo.aidl b/libs/input/android/InputChannel.aidl
similarity index 91%
rename from libs/input/android/InputChannelInfo.aidl
rename to libs/input/android/InputChannel.aidl
index 2e83b96..c2d1112 100644
--- a/libs/input/android/InputChannelInfo.aidl
+++ b/libs/input/android/InputChannel.aidl
@@ -17,4 +17,4 @@
 
 package android;
 
-parcelable InputChannelInfo cpp_header "input/InputTransport.h";
+parcelable InputChannel cpp_header "input/InputTransport.h";
diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl
index 8b7c4fc..44bb66d 100644
--- a/libs/input/android/os/IInputFlinger.aidl
+++ b/libs/input/android/os/IInputFlinger.aidl
@@ -16,7 +16,7 @@
 
 package android.os;
 
-import android.InputChannelInfo;
+import android.InputChannel;
 import android.InputWindowInfo;
 import android.os.ISetInputWindowsListener;
 
@@ -29,6 +29,6 @@
     // shouldn't be a concern.
     oneway void setInputWindows(in InputWindowInfo[] inputHandles,
             in @nullable ISetInputWindowsListener setInputWindowsListener);
-    void registerInputChannel(in InputChannelInfo info);
-    void unregisterInputChannel(in InputChannelInfo info);
+    void registerInputChannel(in InputChannel channel);
+    void unregisterInputChannel(in InputChannel channel);
 }
diff --git a/libs/input/tests/Flags_test.cpp b/libs/input/tests/Flags_test.cpp
index 800404d..0dbb4cf 100644
--- a/libs/input/tests/Flags_test.cpp
+++ b/libs/input/tests/Flags_test.cpp
@@ -25,30 +25,6 @@
 
 enum class TestFlags { ONE = 0x1, TWO = 0x2, THREE = 0x4 };
 
-static std::optional<std::string> toStringComplete(TestFlags f) {
-    switch (f) {
-        case TestFlags::ONE:
-            return "ONE";
-        case TestFlags::TWO:
-            return "TWO";
-        case TestFlags::THREE:
-            return "THREE";
-    }
-    return std::nullopt;
-}
-
-static std::optional<std::string> toStringIncomplete(TestFlags f) {
-    switch (f) {
-        case TestFlags::ONE:
-            return "ONE";
-        case TestFlags::TWO:
-            return "TWO";
-        case TestFlags::THREE:
-        default:
-            return std::nullopt;
-    }
-}
-
 TEST(Flags, Test) {
     Flags<TestFlags> flags = TestFlags::ONE;
     ASSERT_TRUE(flags.test(TestFlags::ONE));
@@ -172,29 +148,75 @@
     ASSERT_NE(flags1, flags2);
 }
 
-TEST(Flags, String_NoFlagsWithDefaultStringify) {
+TEST(Flags, String_NoFlags) {
     Flags<TestFlags> flags;
     ASSERT_EQ(flags.string(), "0x0");
 }
 
-TEST(Flags, String_NoFlagsWithNonDefaultStringify) {
+TEST(Flags, String_KnownValues) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
+    ASSERT_EQ(flags.string(), "ONE | TWO");
+}
+
+TEST(Flags, String_UnknownValues) {
+    auto flags = Flags<TestFlags>(0b1011);
+    ASSERT_EQ(flags.string(), "ONE | TWO | 0x00000008");
+}
+
+TEST(FlagsIterator, IteratesOverAllFlags) {
+    Flags<TestFlags> flags1 = TestFlags::ONE | TestFlags::TWO;
+    Flags<TestFlags> flags2;
+    for (TestFlags f : flags1) {
+        flags2 |= f;
+    }
+    ASSERT_EQ(flags2, flags1);
+}
+
+TEST(FlagsIterator, IteratesInExpectedOrder) {
+    const std::vector<TestFlags> flagOrder = {TestFlags::ONE, TestFlags::TWO};
     Flags<TestFlags> flags;
-    ASSERT_EQ(flags.string(toStringComplete), "0x0");
-}
+    for (TestFlags f : flagOrder) {
+        flags |= f;
+    }
 
-TEST(Flags, String_WithDefaultStringify) {
+    size_t idx = 0;
+    auto iter = flags.begin();
+    while (iter != flags.end() && idx < flagOrder.size()) {
+        // Make sure the order is what we expect
+        ASSERT_EQ(*iter, flagOrder[idx]);
+        iter++;
+        idx++;
+    }
+    ASSERT_EQ(iter, flags.end());
+}
+TEST(FlagsIterator, PostFixIncrement) {
     Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
-    ASSERT_EQ(flags.string(), "0x00000003");
+    auto iter = flags.begin();
+    ASSERT_EQ(*(iter++), TestFlags::ONE);
+    ASSERT_EQ(*iter, TestFlags::TWO);
+    ASSERT_EQ(*(iter++), TestFlags::TWO);
+    ASSERT_EQ(iter, flags.end());
 }
 
-TEST(Flags, String_WithCompleteStringify) {
+TEST(FlagsIterator, PreFixIncrement) {
     Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
-    ASSERT_EQ(flags.string(toStringComplete), "ONE | TWO");
+    auto iter = flags.begin();
+    ASSERT_EQ(*++iter, TestFlags::TWO);
+    ASSERT_EQ(++iter, flags.end());
 }
 
-TEST(Flags, String_WithIncompleteStringify) {
-    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
-    ASSERT_EQ(flags.string(toStringIncomplete), "ONE | 0x00000004");
+TEST(FlagNames, RuntimeFlagName) {
+    TestFlags f = TestFlags::ONE;
+    ASSERT_EQ(flag_name(f), "ONE");
+}
+
+TEST(FlagNames, RuntimeUnknownFlagName) {
+    TestFlags f = static_cast<TestFlags>(0x8);
+    ASSERT_EQ(flag_name(f), std::nullopt);
+}
+
+TEST(FlagNames, CompileTimeFlagName) {
+    static_assert(flag_name<TestFlags::TWO>() == "TWO");
 }
 
 } // namespace android::test
\ No newline at end of file
diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp
index 4187ca9..0661261 100644
--- a/libs/input/tests/InputChannel_test.cpp
+++ b/libs/input/tests/InputChannel_test.cpp
@@ -33,9 +33,6 @@
 namespace android {
 
 class InputChannelTest : public testing::Test {
-protected:
-    virtual void SetUp() { }
-    virtual void TearDown() { }
 };
 
 
@@ -47,7 +44,7 @@
 
     android::base::unique_fd sendFd(pipe.sendFd);
 
-    sp<InputChannel> inputChannel =
+    std::unique_ptr<InputChannel> inputChannel =
             InputChannel::create("channel name", std::move(sendFd), new BBinder());
 
     EXPECT_NE(inputChannel, nullptr) << "channel should be successfully created";
@@ -62,14 +59,14 @@
 TEST_F(InputChannelTest, SetAndGetToken) {
     Pipe pipe;
     sp<IBinder> token = new BBinder();
-    sp<InputChannel> channel =
+    std::unique_ptr<InputChannel> channel =
             InputChannel::create("test channel", android::base::unique_fd(pipe.sendFd), token);
 
     EXPECT_EQ(token, channel->getConnectionToken());
 }
 
 TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) {
-    sp<InputChannel> serverChannel, clientChannel;
+    std::unique_ptr<InputChannel> serverChannel, clientChannel;
 
     status_t result = InputChannel::openInputChannelPair("channel name",
             serverChannel, clientChannel);
@@ -120,7 +117,7 @@
 }
 
 TEST_F(InputChannelTest, ReceiveSignal_WhenNoSignalPresent_ReturnsAnError) {
-    sp<InputChannel> serverChannel, clientChannel;
+    std::unique_ptr<InputChannel> serverChannel, clientChannel;
 
     status_t result = InputChannel::openInputChannelPair("channel name",
             serverChannel, clientChannel);
@@ -134,7 +131,7 @@
 }
 
 TEST_F(InputChannelTest, ReceiveSignal_WhenPeerClosed_ReturnsAnError) {
-    sp<InputChannel> serverChannel, clientChannel;
+    std::unique_ptr<InputChannel> serverChannel, clientChannel;
 
     status_t result = InputChannel::openInputChannelPair("channel name",
             serverChannel, clientChannel);
@@ -142,7 +139,7 @@
     ASSERT_EQ(OK, result)
             << "should have successfully opened a channel pair";
 
-    serverChannel.clear(); // close server channel
+    serverChannel.reset(); // close server channel
 
     InputMessage msg;
     EXPECT_EQ(DEAD_OBJECT, clientChannel->receiveMessage(&msg))
@@ -150,7 +147,7 @@
 }
 
 TEST_F(InputChannelTest, SendSignal_WhenPeerClosed_ReturnsAnError) {
-    sp<InputChannel> serverChannel, clientChannel;
+    std::unique_ptr<InputChannel> serverChannel, clientChannel;
 
     status_t result = InputChannel::openInputChannelPair("channel name",
             serverChannel, clientChannel);
@@ -158,7 +155,7 @@
     ASSERT_EQ(OK, result)
             << "should have successfully opened a channel pair";
 
-    serverChannel.clear(); // close server channel
+    serverChannel.reset(); // close server channel
 
     InputMessage msg;
     msg.header.type = InputMessage::Type::KEY;
@@ -167,7 +164,7 @@
 }
 
 TEST_F(InputChannelTest, SendAndReceive_MotionClassification) {
-    sp<InputChannel> serverChannel, clientChannel;
+    std::unique_ptr<InputChannel> serverChannel, clientChannel;
     status_t result = InputChannel::openInputChannelPair("channel name",
             serverChannel, clientChannel);
     ASSERT_EQ(OK, result)
@@ -199,7 +196,7 @@
 }
 
 TEST_F(InputChannelTest, InputChannelParcelAndUnparcel) {
-    sp<InputChannel> serverChannel, clientChannel;
+    std::unique_ptr<InputChannel> serverChannel, clientChannel;
 
     status_t result =
             InputChannel::openInputChannelPair("channel parceling", serverChannel, clientChannel);
@@ -218,14 +215,14 @@
 }
 
 TEST_F(InputChannelTest, DuplicateChannelAndAssertEqual) {
-    sp<InputChannel> serverChannel, clientChannel;
+    std::unique_ptr<InputChannel> serverChannel, clientChannel;
 
     status_t result =
             InputChannel::openInputChannelPair("channel dup", serverChannel, clientChannel);
 
     ASSERT_EQ(OK, result) << "should have successfully opened a channel pair";
 
-    sp<InputChannel> dupChan = serverChannel->dup();
+    std::unique_ptr<InputChannel> dupChan = serverChannel->dup();
 
     EXPECT_EQ(*serverChannel == *dupChan, true) << "inputchannel should be equal after duplication";
 }
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 8e2eec8..5ddc858 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -30,33 +30,21 @@
 
 class InputPublisherAndConsumerTest : public testing::Test {
 protected:
-    sp<InputChannel> serverChannel, clientChannel;
-    InputPublisher* mPublisher;
-    InputConsumer* mConsumer;
+    std::shared_ptr<InputChannel> mServerChannel, mClientChannel;
+    std::unique_ptr<InputPublisher> mPublisher;
+    std::unique_ptr<InputConsumer> mConsumer;
     PreallocatedInputEventFactory mEventFactory;
 
-    virtual void SetUp() {
+    void SetUp() override {
+        std::unique_ptr<InputChannel> serverChannel, clientChannel;
         status_t result = InputChannel::openInputChannelPair("channel name",
                 serverChannel, clientChannel);
         ASSERT_EQ(OK, result);
+        mServerChannel = std::move(serverChannel);
+        mClientChannel = std::move(clientChannel);
 
-        mPublisher = new InputPublisher(serverChannel);
-        mConsumer = new InputConsumer(clientChannel);
-    }
-
-    virtual void TearDown() {
-        if (mPublisher) {
-            delete mPublisher;
-            mPublisher = nullptr;
-        }
-
-        if (mConsumer) {
-            delete mConsumer;
-            mConsumer = nullptr;
-        }
-
-        serverChannel.clear();
-        clientChannel.clear();
+        mPublisher = std::make_unique<InputPublisher>(mServerChannel);
+        mConsumer = std::make_unique<InputConsumer>(mClientChannel);
     }
 
     void PublishAndConsumeKeyEvent();
@@ -65,8 +53,8 @@
 };
 
 TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) {
-    EXPECT_EQ(serverChannel.get(), mPublisher->getChannel().get());
-    EXPECT_EQ(clientChannel.get(), mConsumer->getChannel().get());
+    EXPECT_EQ(mServerChannel.get(), mPublisher->getChannel().get());
+    EXPECT_EQ(mClientChannel.get(), mConsumer->getChannel().get());
 }
 
 void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() {
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 5930f0a..d1a3e9a 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -100,6 +100,7 @@
         "InputListener.cpp",
         "InputReaderBase.cpp",
         "InputThread.cpp",
+        "VibrationElement.cpp"
     ],
 }
 
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index c5f60ad..088c6f1 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -119,7 +119,7 @@
 }
 
 // Used by tests only.
-binder::Status InputManager::registerInputChannel(const InputChannelInfo& info) {
+binder::Status InputManager::registerInputChannel(const InputChannel& channel) {
     IPCThreadState* ipc = IPCThreadState::self();
     const int uid = ipc->getCallingUid();
     if (uid != AID_SHELL && uid != AID_ROOT) {
@@ -127,15 +127,12 @@
                 "from non shell/root entity (PID: %d)", ipc->getCallingPid());
         return binder::Status::ok();
     }
-    android::base::unique_fd newFd(::dup(info.mFd));
-    sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
-    mDispatcher->registerInputChannel(channel);
+
+    mDispatcher->registerInputChannel(channel.dup());
     return binder::Status::ok();
 }
 
-binder::Status InputManager::unregisterInputChannel(const InputChannelInfo& info) {
-    android::base::unique_fd newFd(::dup(info.mFd));
-    sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
+binder::Status InputManager::unregisterInputChannel(const InputChannel& channel) {
     mDispatcher->unregisterInputChannel(channel);
     return binder::Status::ok();
 }
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 4993b54..0503e81 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -108,8 +108,8 @@
             const std::vector<InputWindowInfo>& handles,
             const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
 
-    binder::Status registerInputChannel(const InputChannelInfo& info) override;
-    binder::Status unregisterInputChannel(const InputChannelInfo& info) override;
+    binder::Status registerInputChannel(const InputChannel& channel) override;
+    binder::Status unregisterInputChannel(const InputChannel& channel) override;
 
 private:
     sp<InputReaderInterface> mReader;
diff --git a/services/inputflinger/VibrationElement.cpp b/services/inputflinger/VibrationElement.cpp
new file mode 100644
index 0000000..a69f5d0
--- /dev/null
+++ b/services/inputflinger/VibrationElement.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 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 "VibrationElement.h"
+
+#include <android-base/stringprintf.h>
+
+#include <algorithm>
+#include <cinttypes>
+
+using android::base::StringPrintf;
+
+namespace android {
+
+// The sentinel to use the default amplitude
+static const int DEFAULT_AMPLITUDE = -1;
+
+// The vibration magnitude for the "DEFAULT_AMPLITUDE" magnitude constant.
+static const uint16_t DEFAULT_MAGNITUDE = 0xc000;
+
+void VibrationElement::dump(std::string& dump) const {
+    dump += StringPrintf("[duration=%lldms, channels=[", duration.count());
+
+    if (channels.size()) {
+        dump += std::to_string(channels[0]);
+        std::for_each(channels.begin() + 1, channels.end(), [&dump](int channel) {
+            dump += ", ";
+            dump += std::to_string(channel);
+        });
+    }
+    dump += "]]";
+}
+
+uint16_t VibrationElement::getChannel(int id) const {
+    if (id >= (int)channels.size()) {
+        return 0;
+    }
+
+    // android framework uses DEFAULT_AMPLITUDE to signal that the vibration
+    // should use some built-in default value, denoted here as DEFAULT_MAGNITUDE
+    if (channels[id] == DEFAULT_AMPLITUDE) {
+        return DEFAULT_MAGNITUDE;
+    }
+
+    // convert range [0,255] to [0,65535] (android framework to linux ff ranges)
+    return ((uint16_t)channels[id]) << 8;
+}
+
+bool VibrationElement::isOn() const {
+    return std::any_of(channels.begin(), channels.end(),
+                       [](uint16_t channel) { return channel != 0; });
+}
+
+} // namespace android
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index a15b7b2..1914a38 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -128,14 +128,17 @@
 protected:
     explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher, const std::string name)
           : mDispatcher(dispatcher) {
-        InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
+        std::unique_ptr<InputChannel> serverChannel, clientChannel;
+        InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
+        mServerChannel = std::move(serverChannel);
+        mClientChannel = std::move(clientChannel);
         mConsumer = std::make_unique<InputConsumer>(mClientChannel);
     }
 
     virtual ~FakeInputReceiver() {}
 
     sp<InputDispatcher> mDispatcher;
-    sp<InputChannel> mServerChannel, mClientChannel;
+    std::shared_ptr<InputChannel> mServerChannel, mClientChannel;
     std::unique_ptr<InputConsumer> mConsumer;
     PreallocatedInputEventFactory mEventFactory;
 };
diff --git a/services/inputflinger/dispatcher/Connection.cpp b/services/inputflinger/dispatcher/Connection.cpp
index f5ea563..cee9c39 100644
--- a/services/inputflinger/dispatcher/Connection.cpp
+++ b/services/inputflinger/dispatcher/Connection.cpp
@@ -20,7 +20,7 @@
 
 namespace android::inputdispatcher {
 
-Connection::Connection(const sp<InputChannel>& inputChannel, bool monitor,
+Connection::Connection(const std::shared_ptr<InputChannel>& inputChannel, bool monitor,
                        const IdGenerator& idGenerator)
       : status(STATUS_NORMAL),
         inputChannel(inputChannel),
diff --git a/services/inputflinger/dispatcher/Connection.h b/services/inputflinger/dispatcher/Connection.h
index 3b33f29..c4262ad 100644
--- a/services/inputflinger/dispatcher/Connection.h
+++ b/services/inputflinger/dispatcher/Connection.h
@@ -42,7 +42,7 @@
     };
 
     Status status;
-    sp<InputChannel> inputChannel; // never null
+    std::shared_ptr<InputChannel> inputChannel; // never null
     bool monitor;
     InputPublisher inputPublisher;
     InputState inputState;
@@ -59,7 +59,8 @@
     // yet received a "finished" response from the application.
     std::deque<DispatchEntry*> waitQueue;
 
-    Connection(const sp<InputChannel>& inputChannel, bool monitor, const IdGenerator& idGenerator);
+    Connection(const std::shared_ptr<InputChannel>& inputChannel, bool monitor,
+               const IdGenerator& idGenerator);
 
     inline const std::string getInputChannelName() const { return inputChannel->getName(); }
 
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index 5dfcdd1..e5b36f4 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -259,7 +259,7 @@
     int32_t userActivityEventType;
     uint32_t seq;
     bool handled;
-    sp<InputChannel> inputChannel;
+    std::shared_ptr<InputChannel> inputChannel;
     sp<IBinder> oldToken;
     sp<IBinder> newToken;
 };
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index a4538bb..bfaab3c 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -426,7 +426,7 @@
 
     while (!mConnectionsByFd.empty()) {
         sp<Connection> connection = mConnectionsByFd.begin()->second;
-        unregisterInputChannel(connection->inputChannel);
+        unregisterInputChannel(*connection->inputChannel);
     }
 }
 
@@ -1098,7 +1098,7 @@
 }
 
 void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) {
-    sp<InputChannel> channel = getInputChannelLocked(entry->connectionToken);
+    std::shared_ptr<InputChannel> channel = getInputChannelLocked(entry->connectionToken);
     if (channel == nullptr) {
         return; // Window has gone away
     }
@@ -2022,7 +2022,8 @@
 
     if (it == inputTargets.end()) {
         InputTarget inputTarget;
-        sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
+        std::shared_ptr<InputChannel> inputChannel =
+                getInputChannelLocked(windowHandle->getToken());
         if (inputChannel == nullptr) {
             ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str());
             return;
@@ -2836,7 +2837,7 @@
         }
 
         // Unregister the channel.
-        d->unregisterInputChannelLocked(connection->inputChannel, notify);
+        d->unregisterInputChannelLocked(*connection->inputChannel, notify);
         return 0; // remove the callback
     }             // release lock
 }
@@ -2866,7 +2867,7 @@
 }
 
 void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
-        const sp<InputChannel>& channel, const CancelationOptions& options) {
+        const std::shared_ptr<InputChannel>& channel, const CancelationOptions& options) {
     sp<Connection> connection = getConnectionLocked(channel->getConnectionToken());
     if (connection == nullptr) {
         return;
@@ -3680,7 +3681,8 @@
     return false;
 }
 
-sp<InputChannel> InputDispatcher::getInputChannelLocked(const sp<IBinder>& token) const {
+std::shared_ptr<InputChannel> InputDispatcher::getInputChannelLocked(
+        const sp<IBinder>& token) const {
     size_t count = mInputChannelsByToken.count(token);
     if (count == 0) {
         return nullptr;
@@ -3805,7 +3807,7 @@
                 ALOGD("Focus left window: %s in display %" PRId32,
                       oldFocusedWindowHandle->getName().c_str(), displayId);
             }
-            sp<InputChannel> focusedInputChannel =
+            std::shared_ptr<InputChannel> focusedInputChannel =
                     getInputChannelLocked(oldFocusedWindowHandle->getToken());
             if (focusedInputChannel != nullptr) {
                 CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
@@ -3840,7 +3842,7 @@
                     ALOGD("Touched window was removed: %s in display %" PRId32,
                           touchedWindow.windowHandle->getName().c_str(), displayId);
                 }
-                sp<InputChannel> touchedInputChannel =
+                std::shared_ptr<InputChannel> touchedInputChannel =
                         getInputChannelLocked(touchedWindow.windowHandle->getToken());
                 if (touchedInputChannel != nullptr) {
                     CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
@@ -3919,7 +3921,7 @@
             sp<InputWindowHandle> oldFocusedWindowHandle =
                     getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
             if (oldFocusedWindowHandle != nullptr) {
-                sp<InputChannel> inputChannel =
+                std::shared_ptr<InputChannel> inputChannel =
                         getInputChannelLocked(oldFocusedWindowHandle->getToken());
                 if (inputChannel != nullptr) {
                     CancelationOptions
@@ -4217,8 +4219,7 @@
                                          toString(windowInfo->hasWallpaper),
                                          toString(windowInfo->visible),
                                          toString(windowInfo->canReceiveKeys),
-                                         windowInfo->flags.string(InputWindowInfo::flagToString)
-                                                 .c_str(),
+                                         windowInfo->flags.string().c_str(),
                                          static_cast<int32_t>(windowInfo->type),
                                          windowInfo->frameLeft, windowInfo->frameTop,
                                          windowInfo->frameRight, windowInfo->frameBottom,
@@ -4366,13 +4367,13 @@
     const size_t numMonitors = monitors.size();
     for (size_t i = 0; i < numMonitors; i++) {
         const Monitor& monitor = monitors[i];
-        const sp<InputChannel>& channel = monitor.inputChannel;
+        const std::shared_ptr<InputChannel>& channel = monitor.inputChannel;
         dump += StringPrintf(INDENT2 "%zu: '%s', ", i, channel->getName().c_str());
         dump += "\n";
     }
 }
 
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
+status_t InputDispatcher::registerInputChannel(const std::shared_ptr<InputChannel>& inputChannel) {
 #if DEBUG_REGISTRATION
     ALOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().c_str());
 #endif
@@ -4400,7 +4401,7 @@
     return OK;
 }
 
-status_t InputDispatcher::registerInputMonitor(const sp<InputChannel>& inputChannel,
+status_t InputDispatcher::registerInputMonitor(const std::shared_ptr<InputChannel>& inputChannel,
                                                int32_t displayId, bool isGestureMonitor) {
     { // acquire lock
         std::scoped_lock _l(mLock);
@@ -4432,9 +4433,9 @@
     return OK;
 }
 
-status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
+status_t InputDispatcher::unregisterInputChannel(const InputChannel& inputChannel) {
 #if DEBUG_REGISTRATION
-    ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().c_str());
+    ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel.getName().c_str());
 #endif
 
     { // acquire lock
@@ -4452,23 +4453,23 @@
     return OK;
 }
 
-status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel,
+status_t InputDispatcher::unregisterInputChannelLocked(const InputChannel& inputChannel,
                                                        bool notify) {
-    sp<Connection> connection = getConnectionLocked(inputChannel->getConnectionToken());
+    sp<Connection> connection = getConnectionLocked(inputChannel.getConnectionToken());
     if (connection == nullptr) {
         ALOGW("Attempted to unregister already unregistered input channel '%s'",
-              inputChannel->getName().c_str());
+              inputChannel.getName().c_str());
         return BAD_VALUE;
     }
 
     removeConnectionLocked(connection);
-    mInputChannelsByToken.erase(inputChannel->getConnectionToken());
+    mInputChannelsByToken.erase(inputChannel.getConnectionToken());
 
     if (connection->monitor) {
         removeMonitorChannelLocked(inputChannel);
     }
 
-    mLooper->removeFd(inputChannel->getFd());
+    mLooper->removeFd(inputChannel.getFd());
 
     nsecs_t currentTime = now();
     abortBrokenDispatchCycleLocked(currentTime, connection, notify);
@@ -4477,19 +4478,19 @@
     return OK;
 }
 
-void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) {
+void InputDispatcher::removeMonitorChannelLocked(const InputChannel& inputChannel) {
     removeMonitorChannelLocked(inputChannel, mGlobalMonitorsByDisplay);
     removeMonitorChannelLocked(inputChannel, mGestureMonitorsByDisplay);
 }
 
 void InputDispatcher::removeMonitorChannelLocked(
-        const sp<InputChannel>& inputChannel,
+        const InputChannel& inputChannel,
         std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) {
     for (auto it = monitorsByDisplay.begin(); it != monitorsByDisplay.end();) {
         std::vector<Monitor>& monitors = it->second;
         const size_t numMonitors = monitors.size();
         for (size_t i = 0; i < numMonitors; i++) {
-            if (monitors[i].inputChannel == inputChannel) {
+            if (*monitors[i].inputChannel == inputChannel) {
                 monitors.erase(monitors.begin() + i);
                 break;
             }
@@ -4540,7 +4541,8 @@
         options.deviceId = deviceId;
         options.displayId = displayId;
         for (const TouchedWindow& window : state.windows) {
-            sp<InputChannel> channel = getInputChannelLocked(window.windowHandle->getToken());
+            std::shared_ptr<InputChannel> channel =
+                    getInputChannelLocked(window.windowHandle->getToken());
             if (channel != nullptr) {
                 synthesizeCancelationEventsForInputChannelLocked(channel, options);
             }
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 824bbf5..ba7ace0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -124,10 +124,11 @@
     virtual bool transferTouchFocus(const sp<IBinder>& fromToken,
                                     const sp<IBinder>& toToken) override;
 
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) override;
-    virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel, int32_t displayId,
-                                          bool isGestureMonitor) override;
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) override;
+    virtual status_t registerInputChannel(
+            const std::shared_ptr<InputChannel>& inputChannel) override;
+    virtual status_t registerInputMonitor(const std::shared_ptr<InputChannel>& inputChannel,
+                                          int32_t displayId, bool isGestureMonitor) override;
+    virtual status_t unregisterInputChannel(const InputChannel& inputChannel) override;
     virtual status_t pilferPointers(const sp<IBinder>& token) override;
 
 private:
@@ -210,8 +211,8 @@
             return std::hash<IBinder*>{}(b.get());
         }
     };
-    std::unordered_map<sp<IBinder>, sp<InputChannel>, IBinderHash> mInputChannelsByToken
-            GUARDED_BY(mLock);
+    std::unordered_map<sp<IBinder>, std::shared_ptr<InputChannel>, IBinderHash>
+            mInputChannelsByToken GUARDED_BY(mLock);
 
     // Finds the display ID of the gesture monitor identified by the provided token.
     std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token)
@@ -301,7 +302,8 @@
             REQUIRES(mLock);
     sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken) const
             REQUIRES(mLock);
-    sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const REQUIRES(mLock);
+    std::shared_ptr<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const
+            REQUIRES(mLock);
     bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
 
     /*
@@ -459,8 +461,8 @@
     void synthesizeCancelationEventsForMonitorsLocked(
             const CancelationOptions& options,
             std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock);
-    void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
-                                                          const CancelationOptions& options)
+    void synthesizeCancelationEventsForInputChannelLocked(
+            const std::shared_ptr<InputChannel>& channel, const CancelationOptions& options)
             REQUIRES(mLock);
     void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
                                                         const CancelationOptions& options)
@@ -481,11 +483,11 @@
     void logDispatchStateLocked() REQUIRES(mLock);
 
     // Registration.
-    void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) REQUIRES(mLock);
+    void removeMonitorChannelLocked(const InputChannel& inputChannel) REQUIRES(mLock);
     void removeMonitorChannelLocked(
-            const sp<InputChannel>& inputChannel,
+            const InputChannel& inputChannel,
             std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock);
-    status_t unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, bool notify)
+    status_t unregisterInputChannelLocked(const InputChannel& inputChannel, bool notify)
             REQUIRES(mLock);
 
     // Interesting events that we might like to log or tell the framework about.
diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h
index 4287538..debf805 100644
--- a/services/inputflinger/dispatcher/InputTarget.h
+++ b/services/inputflinger/dispatcher/InputTarget.h
@@ -91,7 +91,7 @@
     };
 
     // The input channel to be targeted.
-    sp<InputChannel> inputChannel;
+    std::shared_ptr<InputChannel> inputChannel;
 
     // Flags for the input target.
     int32_t flags = 0;
diff --git a/services/inputflinger/dispatcher/Monitor.cpp b/services/inputflinger/dispatcher/Monitor.cpp
index 289b084..b347674 100644
--- a/services/inputflinger/dispatcher/Monitor.cpp
+++ b/services/inputflinger/dispatcher/Monitor.cpp
@@ -19,7 +19,7 @@
 namespace android::inputdispatcher {
 
 // --- Monitor ---
-Monitor::Monitor(const sp<InputChannel>& inputChannel) : inputChannel(inputChannel) {}
+Monitor::Monitor(const std::shared_ptr<InputChannel>& inputChannel) : inputChannel(inputChannel) {}
 
 // --- TouchedMonitor ---
 TouchedMonitor::TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset)
diff --git a/services/inputflinger/dispatcher/Monitor.h b/services/inputflinger/dispatcher/Monitor.h
index b67c9eb..fc0b020 100644
--- a/services/inputflinger/dispatcher/Monitor.h
+++ b/services/inputflinger/dispatcher/Monitor.h
@@ -22,9 +22,9 @@
 namespace android::inputdispatcher {
 
 struct Monitor {
-    sp<InputChannel> inputChannel; // never null
+    std::shared_ptr<InputChannel> inputChannel; // never null
 
-    explicit Monitor(const sp<InputChannel>& inputChannel);
+    explicit Monitor(const std::shared_ptr<InputChannel>& inputChannel);
 };
 
 // For tracking the offsets we need to apply when adding gesture monitor targets.
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index f25131c..272b0a6 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -152,7 +152,7 @@
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0;
+    virtual status_t registerInputChannel(const std::shared_ptr<InputChannel>& inputChannel) = 0;
 
     /* Registers input channels to be used to monitor input events.
      *
@@ -162,14 +162,14 @@
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel, int32_t displayId,
-                                          bool gestureMonitor) = 0;
+    virtual status_t registerInputMonitor(const std::shared_ptr<InputChannel>& inputChannel,
+                                          int32_t displayId, bool gestureMonitor) = 0;
 
     /* Unregister input channels that will no longer receive input events.
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
+    virtual status_t unregisterInputChannel(const InputChannel& inputChannel) = 0;
 
     /* Allows an input monitor steal the current pointer stream away from normal input windows.
      *
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index 9364a2a..cd655e0 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -48,8 +48,8 @@
                                    const sp<ISetInputWindowsListener>&) {
         return binder::Status::ok();
     }
-    binder::Status registerInputChannel(const InputChannelInfo&) { return binder::Status::ok(); }
-    binder::Status unregisterInputChannel(const InputChannelInfo&) { return binder::Status::ok(); }
+    binder::Status registerInputChannel(const InputChannel&) { return binder::Status::ok(); }
+    binder::Status unregisterInputChannel(const InputChannel&) { return binder::Status::ok(); }
 
 private:
     virtual ~InputFlinger();
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 0fa8787..5a832e7 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -17,23 +17,24 @@
 #ifndef _UI_INPUT_READER_BASE_H
 #define _UI_INPUT_READER_BASE_H
 
-#include "PointerControllerInterface.h"
-
 #include <input/DisplayViewport.h>
 #include <input/Input.h>
 #include <input/InputDevice.h>
 #include <input/VelocityControl.h>
 #include <input/VelocityTracker.h>
+#include <stddef.h>
+#include <unistd.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
-#include <stddef.h>
-#include <unistd.h>
 #include <optional>
 #include <set>
 #include <unordered_map>
 #include <vector>
 
+#include "PointerControllerInterface.h"
+#include "VibrationElement.h"
+
 // Maximum supported size of a vibration pattern.
 // Must be at least 2.
 #define MAX_VIBRATE_PATTERN_SIZE 100
@@ -41,6 +42,7 @@
 // Maximum allowable delay value in a vibration pattern before
 // which the delay will be truncated.
 #define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL)
+#define MAX_VIBRATE_PATTERN_DELAY_MSECS (1000000 * 1000LL)
 
 namespace android {
 
@@ -104,8 +106,8 @@
     virtual void requestRefreshConfiguration(uint32_t changes) = 0;
 
     /* Controls the vibrator of a particular input device. */
-    virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
-            ssize_t repeat, int32_t token) = 0;
+    virtual void vibrate(int32_t deviceId, const std::vector<VibrationElement>& pattern,
+                         ssize_t repeat, int32_t token) = 0;
     virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0;
 
     /* Return true if the device can send input events to the specified display. */
diff --git a/services/inputflinger/include/VibrationElement.h b/services/inputflinger/include/VibrationElement.h
new file mode 100644
index 0000000..8a134ee
--- /dev/null
+++ b/services/inputflinger/include/VibrationElement.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 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 _VIBRATION_ELEMENT_H
+#define _VIBRATION_ELEMENT_H
+
+#include <chrono>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace android {
+
+/*
+ * Describes a rumble effect
+ */
+struct VibrationElement {
+    std::chrono::milliseconds duration;
+    std::vector<int> channels;
+
+    void dump(std::string& dump) const;
+    uint16_t getChannel(int id) const;
+    bool isOn() const;
+};
+
+} // namespace android
+
+#endif // _VIBRATION_ELEMENT_H
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index fe428f1..cef2b4c 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -702,7 +702,7 @@
           identifier.descriptor.c_str());
 }
 
-void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
+void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
     if (device != nullptr && device->hasValidFd()) {
@@ -710,9 +710,10 @@
         memset(&effect, 0, sizeof(effect));
         effect.type = FF_RUMBLE;
         effect.id = device->ffEffectId;
-        effect.u.rumble.strong_magnitude = 0xc000;
-        effect.u.rumble.weak_magnitude = 0xc000;
-        effect.replay.length = (duration + 999999LL) / 1000000LL;
+        // evdev FF_RUMBLE effect only supports two channels of vibration.
+        effect.u.rumble.strong_magnitude = element.getChannel(0);
+        effect.u.rumble.weak_magnitude = element.getChannel(1);
+        effect.replay.length = element.duration.count();
         effect.replay.delay = 0;
         if (ioctl(device->fd, EVIOCSFF, &effect)) {
             ALOGW("Could not upload force feedback effect to device %s due to error %d.",
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 4b19e5e..b4eaf7f 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -424,10 +424,10 @@
     return result;
 }
 
-void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+void InputDevice::vibrate(const std::vector<VibrationElement>& pattern, ssize_t repeat,
                           int32_t token) {
-    for_each_mapper([pattern, patternSize, repeat, token](InputMapper& mapper) {
-        mapper.vibrate(pattern, patternSize, repeat, token);
+    for_each_mapper([pattern, repeat, token](InputMapper& mapper) {
+        mapper.vibrate(pattern, repeat, token);
     });
 }
 
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 06e3743..16fe865 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -559,12 +559,12 @@
     }
 }
 
-void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
+void InputReader::vibrate(int32_t deviceId, const std::vector<VibrationElement>& pattern,
                           ssize_t repeat, int32_t token) {
     AutoMutex _l(mLock);
     InputDevice* device = findInputDevice(deviceId);
     if (device) {
-        device->vibrate(pattern, patternSize, repeat, token);
+        device->vibrate(pattern, repeat, token);
     }
 }
 
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index baff6e3..c5dfcfd 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -27,6 +27,8 @@
 #include <input/KeyLayoutMap.h>
 #include <input/Keyboard.h>
 #include <input/VirtualKeyMap.h>
+#include <linux/input.h>
+#include <sys/epoll.h>
 #include <utils/BitSet.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
@@ -35,10 +37,8 @@
 #include <utils/Mutex.h>
 #include <utils/PropertyMap.h>
 
-#include <linux/input.h>
-#include <sys/epoll.h>
-
 #include "TouchVideoDevice.h"
+#include "VibrationElement.h"
 
 namespace android {
 
@@ -228,7 +228,7 @@
     virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) = 0;
 
     /* Control the vibrator. */
-    virtual void vibrate(int32_t deviceId, nsecs_t duration) = 0;
+    virtual void vibrate(int32_t deviceId, const VibrationElement& effect) = 0;
     virtual void cancelVibrate(int32_t deviceId) = 0;
 
     /* Requests the EventHub to reopen all input devices on the next call to getEvents(). */
@@ -374,7 +374,7 @@
     virtual bool setKeyboardLayoutOverlay(int32_t deviceId,
                                           const sp<KeyCharacterMap>& map) override;
 
-    virtual void vibrate(int32_t deviceId, nsecs_t duration) override;
+    virtual void vibrate(int32_t deviceId, const VibrationElement& effect) override;
     virtual void cancelVibrate(int32_t deviceId) override;
 
     virtual void requestReopenDevices() override;
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 71313fc..6cb86bd 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -81,7 +81,7 @@
     int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
     bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes,
                                uint8_t* outFlags);
-    void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
+    void vibrate(const std::vector<VibrationElement>& pattern, ssize_t repeat, int32_t token);
     void cancelVibrate(int32_t token);
     void cancelTouch(nsecs_t when);
 
@@ -262,7 +262,9 @@
     inline bool setKeyboardLayoutOverlay(const sp<KeyCharacterMap>& map) {
         return mEventHub->setKeyboardLayoutOverlay(mId, map);
     }
-    inline void vibrate(nsecs_t duration) { return mEventHub->vibrate(mId, duration); }
+    inline void vibrate(const VibrationElement& element) {
+        return mEventHub->vibrate(mId, element);
+    }
     inline void cancelVibrate() { return mEventHub->cancelVibrate(mId); }
 
     inline bool hasAbsoluteAxis(int32_t code) const {
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 108b9c2..9cb2052 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -78,7 +78,7 @@
 
     virtual void requestRefreshConfiguration(uint32_t changes) override;
 
-    virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
+    virtual void vibrate(int32_t deviceId, const std::vector<VibrationElement>& pattern,
                          ssize_t repeat, int32_t token) override;
     virtual void cancelVibrate(int32_t deviceId, int32_t token) override;
 
diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp
index a8fe39a..1db829f 100644
--- a/services/inputflinger/reader/mapper/InputMapper.cpp
+++ b/services/inputflinger/reader/mapper/InputMapper.cpp
@@ -56,7 +56,7 @@
     return false;
 }
 
-void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+void InputMapper::vibrate(const std::vector<VibrationElement>& pattern, ssize_t repeat,
                           int32_t token) {}
 
 void InputMapper::cancelVibrate(int32_t token) {}
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index 949c7ea..d9fc5cc 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -22,6 +22,7 @@
 #include "InputListener.h"
 #include "InputReaderContext.h"
 #include "StylusState.h"
+#include "VibrationElement.h"
 
 namespace android {
 
@@ -62,7 +63,8 @@
     virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
     virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
                                        const int32_t* keyCodes, uint8_t* outFlags);
-    virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
+    virtual void vibrate(const std::vector<VibrationElement>& pattern, ssize_t repeat,
+                         int32_t token);
     virtual void cancelVibrate(int32_t token);
     virtual void cancelTouch(nsecs_t when);
 
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
index 7665680..8c1e224 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
@@ -39,23 +39,17 @@
     // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
 }
 
-void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+void VibratorInputMapper::vibrate(const std::vector<VibrationElement>& pattern, ssize_t repeat,
                                   int32_t token) {
 #if DEBUG_VIBRATOR
     std::string patternStr;
-    for (size_t i = 0; i < patternSize; i++) {
-        if (i != 0) {
-            patternStr += ", ";
-        }
-        patternStr += StringPrintf("%" PRId64, pattern[i]);
-    }
+    dumpPattern(patternStr);
     ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d", getDeviceId(),
           patternStr.c_str(), repeat, token);
 #endif
 
     mVibrating = true;
-    memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
-    mPatternSize = patternSize;
+    mPattern = pattern;
     mRepeat = repeat;
     mToken = token;
     mIndex = -1;
@@ -85,7 +79,7 @@
 
 void VibratorInputMapper::nextStep() {
     mIndex += 1;
-    if (size_t(mIndex) >= mPatternSize) {
+    if (size_t(mIndex) >= mPattern.size()) {
         if (mRepeat < 0) {
             // We are done.
             stopVibrating();
@@ -94,13 +88,15 @@
         mIndex = mRepeat;
     }
 
-    bool vibratorOn = mIndex & 1;
-    nsecs_t duration = mPattern[mIndex];
-    if (vibratorOn) {
+    const VibrationElement& element = mPattern[mIndex];
+    if (element.isOn()) {
 #if DEBUG_VIBRATOR
-        ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
+        std::string description;
+        element.dump(description);
+        ALOGD("nextStep: sending vibrate deviceId=%d, element=%s", getDeviceId(),
+              description.c_str());
 #endif
-        getDeviceContext().vibrate(duration);
+        getDeviceContext().vibrate(element);
     } else {
 #if DEBUG_VIBRATOR
         ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
@@ -108,10 +104,12 @@
         getDeviceContext().cancelVibrate();
     }
     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-    mNextStepTime = now + duration;
+    std::chrono::nanoseconds duration =
+            std::chrono::duration_cast<std::chrono::nanoseconds>(element.duration);
+    mNextStepTime = now + duration.count();
     getContext()->requestTimeoutAtTime(mNextStepTime);
 #if DEBUG_VIBRATOR
-    ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
+    ALOGD("nextStep: scheduled timeout in %lldms", element.duration.count());
 #endif
 }
 
@@ -126,6 +124,25 @@
 void VibratorInputMapper::dump(std::string& dump) {
     dump += INDENT2 "Vibrator Input Mapper:\n";
     dump += StringPrintf(INDENT3 "Vibrating: %s\n", toString(mVibrating));
+    if (mVibrating) {
+        dump += INDENT3 "Pattern: ";
+        dumpPattern(dump);
+        dump += "\n";
+        dump += StringPrintf(INDENT3 "Repeat Index: %zd\n", mRepeat);
+    }
+}
+
+void VibratorInputMapper::dumpPattern(std::string& dump) const {
+    dump += "[";
+
+    if (mPattern.size() > 0) {
+        mPattern[0].dump(dump);
+        std::for_each(mPattern.begin() + 1, mPattern.end(), [&dump](const auto& element) {
+            dump += ", ";
+            element.dump(dump);
+        });
+    }
+    dump += "]";
 }
 
 } // namespace android
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.h b/services/inputflinger/reader/mapper/VibratorInputMapper.h
index f69fdde..bfa5ec1 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.h
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.h
@@ -30,7 +30,7 @@
     virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo) override;
     virtual void process(const RawEvent* rawEvent) override;
 
-    virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
+    virtual void vibrate(const std::vector<VibrationElement>& pattern, ssize_t repeat,
                          int32_t token) override;
     virtual void cancelVibrate(int32_t token) override;
     virtual void timeoutExpired(nsecs_t when) override;
@@ -38,13 +38,13 @@
 
 private:
     bool mVibrating;
-    nsecs_t mPattern[MAX_VIBRATE_PATTERN_SIZE];
-    size_t mPatternSize;
+    std::vector<VibrationElement> mPattern;
     ssize_t mRepeat;
     int32_t mToken;
     ssize_t mIndex;
     nsecs_t mNextStepTime;
 
+    void dumpPattern(std::string& dump) const;
     void nextStep();
     void stopVibrating();
 };
diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl
index 1edc089..755373b 100644
--- a/services/inputflinger/tests/IInputFlingerQuery.aidl
+++ b/services/inputflinger/tests/IInputFlingerQuery.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-import android.InputChannelInfo;
+import android.InputChannel;
 import android.InputWindowInfo;
 import android.os.ISetInputWindowsListener;
 
@@ -23,5 +23,5 @@
 {
     /* Test interfaces */
     void getInputWindows(out InputWindowInfo[] inputHandles);
-    void getInputChannels(out InputChannelInfo[] infos);
+    void getInputChannels(out InputChannel[] channels);
 }
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index cee66a7..4cf4909 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -602,7 +602,8 @@
 
 class FakeInputReceiver {
 public:
-    explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
+    explicit FakeInputReceiver(const std::shared_ptr<InputChannel>& clientChannel,
+                               const std::string name)
           : mName(name) {
         mConsumer = std::make_unique<InputConsumer>(clientChannel);
     }
@@ -754,11 +755,11 @@
                      int32_t displayId, sp<IBinder> token = nullptr)
           : mName(name) {
         if (token == nullptr) {
-            sp<InputChannel> serverChannel, clientChannel;
+            std::unique_ptr<InputChannel> serverChannel, clientChannel;
             InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
-            mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
-            dispatcher->registerInputChannel(serverChannel);
+            mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(clientChannel), name);
             token = serverChannel->getConnectionToken();
+            dispatcher->registerInputChannel(std::move(serverChannel));
         }
 
         inputApplicationHandle->updateInfo();
@@ -1766,10 +1767,10 @@
 public:
     FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
                         int32_t displayId, bool isGestureMonitor = false) {
-        sp<InputChannel> serverChannel, clientChannel;
+        std::unique_ptr<InputChannel> serverChannel, clientChannel;
         InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
-        mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
-        dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
+        mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(clientChannel), name);
+        dispatcher->registerInputMonitor(std::move(serverChannel), displayId, isGestureMonitor);
     }
 
     sp<IBinder> getToken() { return mInputReceiver->getToken(); }
diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp
index f661bba..ce82d28 100644
--- a/services/inputflinger/tests/InputFlingerService_test.cpp
+++ b/services/inputflinger/tests/InputFlingerService_test.cpp
@@ -113,7 +113,7 @@
 
 private:
     sp<SetInputWindowsListener> mSetInputWindowsListener;
-    sp<InputChannel> mServerChannel, mClientChannel;
+    std::unique_ptr<InputChannel> mServerChannel, mClientChannel;
     InputWindowInfo mInfo;
     std::mutex mLock;
     std::condition_variable mSetInputWindowsFinishedCondition;
@@ -136,7 +136,7 @@
     void checkFdFlags(const android::base::unique_fd& fd);
 
     binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles);
-    binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos);
+    binder::Status getInputChannels(std::vector<::android::InputChannel>* channels);
 
     status_t dump(int fd, const Vector<String16>& args) override;
 
@@ -144,20 +144,20 @@
             const std::vector<InputWindowInfo>& handles,
             const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
 
-    binder::Status registerInputChannel(const InputChannelInfo& channel) override;
-    binder::Status unregisterInputChannel(const InputChannelInfo& channel) override;
+    binder::Status registerInputChannel(const InputChannel& channel) override;
+    binder::Status unregisterInputChannel(const InputChannel& channel) override;
 
 private:
     mutable Mutex mLock;
     std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mHandlesPerDisplay;
-    std::vector<sp<InputChannel>> mInputChannels;
+    std::vector<std::shared_ptr<InputChannel>> mInputChannels;
 };
 
 class TestInputQuery : public BnInputFlingerQuery {
 public:
     TestInputQuery(sp<android::TestInputManager> manager) : mManager(manager){};
     binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override;
-    binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos) override;
+    binder::Status getInputChannels(std::vector<::android::InputChannel>* channels) override;
 
 private:
     sp<android::TestInputManager> mManager;
@@ -168,8 +168,8 @@
     return mManager->getInputWindows(inputHandles);
 }
 
-binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannelInfo>* infos) {
-    return mManager->getInputChannels(infos);
+binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannel>* channels) {
+    return mManager->getInputChannels(channels);
 }
 
 binder::Status SetInputWindowsListener::onSetInputWindowsFinished() {
@@ -200,27 +200,23 @@
     EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK);
 }
 
-binder::Status TestInputManager::registerInputChannel(const InputChannelInfo& info) {
+binder::Status TestInputManager::registerInputChannel(const InputChannel& channel) {
     AutoMutex _l(mLock);
     // check Fd flags
-    checkFdFlags(info.mFd);
+    checkFdFlags(channel.getFd());
 
-    android::base::unique_fd newFd(::dup(info.mFd));
-    sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
-    mInputChannels.push_back(channel);
+    mInputChannels.push_back(channel.dup());
 
     return binder::Status::ok();
 }
 
-binder::Status TestInputManager::unregisterInputChannel(const InputChannelInfo& info) {
+binder::Status TestInputManager::unregisterInputChannel(const InputChannel& channel) {
     AutoMutex _l(mLock);
     // check Fd flags
-    checkFdFlags(info.mFd);
-    android::base::unique_fd newFd(::dup(info.mFd));
-    sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
+    checkFdFlags(channel.getFd());
 
     auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(),
-                           [&](sp<InputChannel>& it) { return *it == *channel; });
+                           [&](std::shared_ptr<InputChannel>& c) { return *c == channel; });
     if (it != mInputChannels.end()) {
         mInputChannels.erase(it);
     }
@@ -247,11 +243,10 @@
     return binder::Status::ok();
 }
 
-binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannelInfo>* infos) {
-    infos->clear();
-    for (auto& channel : mInputChannels) {
-        auto chanDup = channel->dup();
-        infos->push_back(std::move(chanDup->getInfo()));
+binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannel>* channels) {
+    channels->clear();
+    for (std::shared_ptr<InputChannel>& channel : mInputChannels) {
+        channels->push_back(*channel);
     }
     return binder::Status::ok();
 }
@@ -320,12 +315,6 @@
     mService->setInputWindows(infos, mSetInputWindowsListener);
     // Verify listener call
     EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout);
-    // Verify input windows from service
-    std::vector<::android::InputWindowInfo> inputHandles;
-    mQuery->getInputWindows(&inputHandles);
-    for (auto& inputInfo : inputHandles) {
-        verifyInputWindowInfo(inputInfo);
-    }
 }
 
 /**
@@ -334,54 +323,57 @@
 TEST_F(InputFlingerServiceTest, InputWindow_SetInputWindows) {
     std::vector<InputWindowInfo> infos = {getInfo()};
     setInputWindowsByInfos(infos);
+
+    // Verify input windows from service
+    std::vector<::android::InputWindowInfo> windowInfos;
+    mQuery->getInputWindows(&windowInfos);
+    for (const ::android::InputWindowInfo& windowInfo : windowInfos) {
+        verifyInputWindowInfo(windowInfo);
+    }
 }
 
 /**
  *  Test InputFlinger service interface registerInputChannel
  */
 TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) {
-    sp<InputChannel> serverChannel, clientChannel;
+    std::unique_ptr<InputChannel> serverChannel, clientChannel;
 
     InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
-    mService->registerInputChannel(serverChannel->getInfo());
+    mService->registerInputChannel(*serverChannel);
 
-    std::vector<::android::InputChannelInfo> infos(2);
-    mQuery->getInputChannels(&infos);
-    EXPECT_EQ(infos.size(), 1UL);
+    std::vector<::android::InputChannel> channels;
+    mQuery->getInputChannels(&channels);
+    ASSERT_EQ(channels.size(), 1UL);
+    EXPECT_EQ(channels[0], *serverChannel);
 
-    auto& info = infos[0];
-    android::base::unique_fd newFd(::dup(info.mFd));
-    sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
-    EXPECT_EQ(*channel, *serverChannel);
-
-    mService->unregisterInputChannel(serverChannel->getInfo());
-    mQuery->getInputChannels(&infos);
-    EXPECT_EQ(infos.size(), 0UL);
+    mService->unregisterInputChannel(*serverChannel);
+    mQuery->getInputChannels(&channels);
+    EXPECT_EQ(channels.size(), 0UL);
 }
 
 /**
  *  Test InputFlinger service interface registerInputChannel with invalid cases
  */
 TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) {
-    sp<InputChannel> serverChannel, clientChannel;
+    std::unique_ptr<InputChannel> serverChannel, clientChannel;
     InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
 
-    std::vector<::android::InputChannelInfo> infos(2);
-    mQuery->getInputChannels(&infos);
-    EXPECT_EQ(infos.size(), 0UL);
+    std::vector<::android::InputChannel> channels;
+    mQuery->getInputChannels(&channels);
+    EXPECT_EQ(channels.size(), 0UL);
 
-    mService->registerInputChannel(InputChannelInfo());
-    mService->unregisterInputChannel(clientChannel->getInfo());
+    mService->registerInputChannel(InputChannel());
+    mService->unregisterInputChannel(*clientChannel);
 
-    mService->registerInputChannel(serverChannel->getInfo());
-    mService->registerInputChannel(clientChannel->getInfo());
-    mQuery->getInputChannels(&infos);
-    EXPECT_EQ(infos.size(), 2UL);
+    mService->registerInputChannel(*serverChannel);
+    mService->registerInputChannel(*clientChannel);
+    mQuery->getInputChannels(&channels);
+    EXPECT_EQ(channels.size(), 2UL);
 
-    mService->unregisterInputChannel(clientChannel->getInfo());
-    mService->unregisterInputChannel(serverChannel->getInfo());
-    mQuery->getInputChannels(&infos);
-    EXPECT_EQ(infos.size(), 0UL);
+    mService->unregisterInputChannel(*clientChannel);
+    mService->unregisterInputChannel(*serverChannel);
+    mQuery->getInputChannels(&channels);
+    EXPECT_EQ(channels.size(), 0UL);
 }
 
 } // namespace android
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index b2c16d0..21dd3c7 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -821,8 +821,7 @@
         return false;
     }
 
-    virtual void vibrate(int32_t, nsecs_t) {
-    }
+    virtual void vibrate(int32_t, const VibrationElement&) {}
 
     virtual void cancelVibrate(int32_t) {
     }