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) {
}