Merge "Add setFocusedWindow function stub"
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 f337d00..24f8e77 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -193,7 +193,7 @@
*/
class InputChannel : public Parcelable {
public:
- static std::shared_ptr<InputChannel> create(const std::string& name,
+ static std::unique_ptr<InputChannel> create(const std::string& name,
android::base::unique_fd fd, sp<IBinder> token);
InputChannel() = default;
InputChannel(const InputChannel& other)
@@ -208,8 +208,8 @@
* Return OK on success.
*/
static status_t openInputChannelPair(const std::string& name,
- std::shared_ptr<InputChannel>& outServerChannel,
- std::shared_ptr<InputChannel>& outClientChannel);
+ std::unique_ptr<InputChannel>& outServerChannel,
+ std::unique_ptr<InputChannel>& outClientChannel);
inline std::string getName() const { return mName; }
inline const android::base::unique_fd& getFd() const { return mFd; }
@@ -241,7 +241,7 @@
status_t receiveMessage(InputMessage* msg);
/* Return a new object that has a duplicate of this channel's fd. */
- std::shared_ptr<InputChannel> dup() const;
+ std::unique_ptr<InputChannel> dup() const;
status_t readFromParcel(const android::Parcel* parcel) override;
status_t writeToParcel(android::Parcel* parcel) const override;
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h
index 233c7ae..8a752c1 100644
--- a/include/input/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -158,10 +158,6 @@
// in scaling of the TOUCH_MAJOR/TOUCH_MINOR axis.
float globalScaleFactor = 1.0f;
- // Scaling factors applied to individual windows.
- float windowXScale = 1.0f;
- float windowYScale = 1.0f;
-
// Transform applied to individual windows.
ui::Transform transform;
@@ -205,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/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 25c0b19..9aa82d9 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -18,6 +18,9 @@
#include <binder/IServiceManager.h>
+#include <inttypes.h>
+#include <unistd.h>
+
#include <android/os/BnServiceCallback.h>
#include <android/os/IServiceManager.h>
#include <binder/IPCThreadState.h>
@@ -36,8 +39,6 @@
#include "Static.h"
-#include <unistd.h>
-
namespace android {
using AidlServiceManager = android::os::IServiceManager;
@@ -219,7 +220,8 @@
const bool isVendorService =
strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
- const long timeout = uptimeMillis() + 5000;
+ const long timeout = 5000;
+ int64_t startTime = uptimeMillis();
// Vendor code can't access system properties
if (!gSystemBootCompleted && !isVendorService) {
#ifdef __ANDROID__
@@ -233,15 +235,21 @@
// retry interval in millisecond; note that vendor services stay at 100ms
const long sleepTime = gSystemBootCompleted ? 1000 : 100;
+ ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
+ ProcessState::self()->getDriverName().c_str());
+
int n = 0;
- while (uptimeMillis() < timeout) {
+ while (uptimeMillis() - startTime < timeout) {
n++;
- ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
- ProcessState::self()->getDriverName().c_str());
usleep(1000*sleepTime);
sp<IBinder> svc = checkService(name);
- if (svc != nullptr) return svc;
+ if (svc != nullptr) {
+ ALOGI("Waiting for service '%s' on '%s' successful after waiting %" PRIi64 "ms",
+ String8(name).string(), ProcessState::self()->getDriverName().c_str(),
+ uptimeMillis() - startTime);
+ return svc;
+ }
}
ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
return nullptr;
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/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp
index 5f5265c..7c271f6 100644
--- a/libs/binder/ndk/tests/Android.bp
+++ b/libs/binder/ndk/tests/Android.bp
@@ -40,6 +40,7 @@
cc_defaults {
name: "test_libbinder_ndk_test_defaults",
defaults: ["test_libbinder_ndk_defaults"],
+ // critical that libbinder/libbinder_ndk are shared for VTS
shared_libs: [
"libandroid_runtime_lazy",
"libbase",
@@ -63,7 +64,7 @@
"IBinderNdkUnitTest-cpp",
"IBinderNdkUnitTest-ndk_platform",
],
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "vts"],
require_root: true,
// force since binderVendorDoubleLoadTest has its own
@@ -81,13 +82,14 @@
"IBinderVendorDoubleLoadTest-ndk_platform",
"libbinder_aidl_test_stub-ndk_platform",
],
+ // critical that libbinder/libbinder_ndk are shared for VTS
shared_libs: [
"libbase",
"libbinder",
"libbinder_ndk",
"libutils",
],
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "vts"],
}
aidl_interface {
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 2680e84..a03835b 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -155,6 +155,7 @@
"binderStabilityTest.cpp",
],
+ // critical that libbinder/libbinder_ndk are shared for VTS
shared_libs: [
"libbinder_ndk",
"libbinder",
@@ -166,7 +167,7 @@
"binderStabilityTestIface-ndk_platform",
],
- test_suites: ["device-tests"],
+ test_suites: ["device-tests", "vts"],
require_root: true,
}
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 7ec2c1a..cca8ddd 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -68,8 +68,9 @@
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);
@@ -211,7 +212,7 @@
}
public:
sp<SurfaceControl> mSurfaceControl;
- std::shared_ptr<InputChannel> mServerChannel;
+ std::unique_ptr<InputChannel> mServerChannel;
std::shared_ptr<InputChannel> mClientChannel;
sp<IInputFlinger> mInputFlinger;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 1bbddea..8dcc415 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -243,7 +243,7 @@
// --- InputChannel ---
-std::shared_ptr<InputChannel> InputChannel::create(const std::string& name,
+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) {
@@ -252,7 +252,7 @@
return nullptr;
}
// using 'new' to access a non-public constructor
- return std::shared_ptr<InputChannel>(new InputChannel(name, std::move(fd), token));
+ 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)
@@ -269,8 +269,8 @@
}
status_t InputChannel::openInputChannelPair(const std::string& name,
- std::shared_ptr<InputChannel>& outServerChannel,
- std::shared_ptr<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;
@@ -376,7 +376,7 @@
return OK;
}
-std::shared_ptr<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().get(), getName().c_str(),
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index 36c1f80..116b963 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -57,7 +57,7 @@
info.frameLeft == frameLeft && info.frameTop == frameTop &&
info.frameRight == frameRight && info.frameBottom == frameBottom &&
info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor &&
- info.windowXScale == windowXScale && info.windowYScale == windowYScale &&
+ info.transform == transform &&
info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible &&
info.canReceiveKeys == canReceiveKeys && info.trustedOverlay == trustedOverlay &&
info.hasFocus == hasFocus && info.hasWallpaper == hasWallpaper &&
@@ -93,8 +93,12 @@
parcel->writeInt32(frameBottom) ?:
parcel->writeInt32(surfaceInset) ?:
parcel->writeFloat(globalScaleFactor) ?:
- parcel->writeFloat(windowXScale) ?:
- parcel->writeFloat(windowYScale) ?:
+ parcel->writeFloat(transform.dsdx()) ?:
+ parcel->writeFloat(transform.dtdx()) ?:
+ parcel->writeFloat(transform.tx()) ?:
+ parcel->writeFloat(transform.dtdy()) ?:
+ parcel->writeFloat(transform.dsdy()) ?:
+ parcel->writeFloat(transform.ty()) ?:
parcel->writeBool(visible) ?:
parcel->writeBool(canReceiveKeys) ?:
parcel->writeBool(hasFocus) ?:
@@ -132,14 +136,19 @@
flags = Flags<Flag>(parcel->readInt32());
type = static_cast<Type>(parcel->readInt32());
+ float dsdx, dtdx, tx, dtdy, dsdy, ty;
status = parcel->readInt32(&frameLeft) ?:
parcel->readInt32(&frameTop) ?:
parcel->readInt32(&frameRight) ?:
parcel->readInt32(&frameBottom) ?:
parcel->readInt32(&surfaceInset) ?:
parcel->readFloat(&globalScaleFactor) ?:
- parcel->readFloat(&windowXScale) ?:
- parcel->readFloat(&windowYScale) ?:
+ parcel->readFloat(&dsdx) ?:
+ parcel->readFloat(&dtdx) ?:
+ parcel->readFloat(&tx) ?:
+ parcel->readFloat(&dtdy) ?:
+ parcel->readFloat(&dsdy) ?:
+ parcel->readFloat(&ty) ?:
parcel->readBool(&visible) ?:
parcel->readBool(&canReceiveKeys) ?:
parcel->readBool(&hasFocus) ?:
@@ -165,6 +174,7 @@
}
touchableRegionCropHandle = parcel->readStrongBinder();
+ transform.set(std::array<float, 9>{dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
return OK;
}
@@ -198,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/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 cc1382b..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);
- std::shared_ptr<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();
- std::shared_ptr<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) {
- std::shared_ptr<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) {
- std::shared_ptr<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) {
- std::shared_ptr<InputChannel> serverChannel, clientChannel;
+ std::unique_ptr<InputChannel> serverChannel, clientChannel;
status_t result = InputChannel::openInputChannelPair("channel name",
serverChannel, clientChannel);
@@ -150,7 +147,7 @@
}
TEST_F(InputChannelTest, SendSignal_WhenPeerClosed_ReturnsAnError) {
- std::shared_ptr<InputChannel> serverChannel, clientChannel;
+ std::unique_ptr<InputChannel> serverChannel, clientChannel;
status_t result = InputChannel::openInputChannelPair("channel name",
serverChannel, clientChannel);
@@ -167,7 +164,7 @@
}
TEST_F(InputChannelTest, SendAndReceive_MotionClassification) {
- std::shared_ptr<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) {
- std::shared_ptr<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) {
- std::shared_ptr<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";
- std::shared_ptr<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 3a7d20b..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:
- std::shared_ptr<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.reset();
- clientChannel.reset();
+ 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/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp
index e7a4587..3da869b 100644
--- a/libs/input/tests/InputWindow_test.cpp
+++ b/libs/input/tests/InputWindow_test.cpp
@@ -53,8 +53,7 @@
i.frameBottom = 19;
i.surfaceInset = 17;
i.globalScaleFactor = 0.3;
- i.windowXScale = 0.4;
- i.windowYScale = 0.5;
+ i.transform.set(std::array<float, 9>{0.4, -1, 100, 0.5, 0, 40, 0, 0, 1});
i.visible = false;
i.canReceiveKeys = false;
i.hasFocus = false;
@@ -85,8 +84,7 @@
ASSERT_EQ(i.frameBottom, i2.frameBottom);
ASSERT_EQ(i.surfaceInset, i2.surfaceInset);
ASSERT_EQ(i.globalScaleFactor, i2.globalScaleFactor);
- ASSERT_EQ(i.windowXScale, i2.windowXScale);
- ASSERT_EQ(i.windowYScale, i2.windowYScale);
+ ASSERT_EQ(i.transform, i2.transform);
ASSERT_EQ(i.visible, i2.visible);
ASSERT_EQ(i.canReceiveKeys, i2.canReceiveKeys);
ASSERT_EQ(i.hasFocus, i2.hasFocus);
diff --git a/libs/ui/Transform.cpp b/libs/ui/Transform.cpp
index 3bf3903..5424a3c 100644
--- a/libs/ui/Transform.cpp
+++ b/libs/ui/Transform.cpp
@@ -133,6 +133,14 @@
return mMatrix[1][1];
}
+float Transform::getScaleX() const {
+ return sqrt(dsdx() * dsdx()) + (dtdx() * dtdx());
+}
+
+float Transform::getScaleY() const {
+ return sqrt((dtdy() * dtdy()) + (dsdy() * dsdy()));
+}
+
void Transform::reset() {
mType = IDENTITY;
for(size_t i = 0; i < 3; i++) {
diff --git a/libs/ui/include/ui/Transform.h b/libs/ui/include/ui/Transform.h
index cf59467..2612e82 100644
--- a/libs/ui/include/ui/Transform.h
+++ b/libs/ui/include/ui/Transform.h
@@ -74,6 +74,9 @@
float dtdy() const;
float dsdy() const;
+ float getScaleX() const;
+ float getScaleY() const;
+
// modify the transform
void reset();
void set(float tx, float ty);
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 3d66d30..1914a38 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -128,7 +128,10 @@
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);
}
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index fdbb1d1..26a1644 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -240,17 +240,13 @@
volatile int32_t DispatchEntry::sNextSeqAtomic;
-DispatchEntry::DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset,
- float yOffset, float globalScaleFactor, float windowXScale,
- float windowYScale)
+DispatchEntry::DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, ui::Transform transform,
+ float globalScaleFactor)
: seq(nextSeq()),
eventEntry(eventEntry),
targetFlags(targetFlags),
- xOffset(xOffset),
- yOffset(yOffset),
+ transform(transform),
globalScaleFactor(globalScaleFactor),
- windowXScale(windowXScale),
- windowYScale(windowYScale),
deliveryTime(0),
resolvedAction(0),
resolvedFlags(0) {
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index 4147e41..e5b36f4 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -193,11 +193,8 @@
EventEntry* eventEntry; // the event to dispatch
int32_t targetFlags;
- float xOffset;
- float yOffset;
+ ui::Transform transform;
float globalScaleFactor;
- float windowXScale = 1.0f;
- float windowYScale = 1.0f;
// Both deliveryTime and timeoutTime are only populated when the entry is sent to the app,
// and will be undefined before that.
nsecs_t deliveryTime; // time when the event was actually delivered
@@ -209,8 +206,8 @@
int32_t resolvedAction;
int32_t resolvedFlags;
- DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset, float yOffset,
- float globalScaleFactor, float windowXScale, float windowYScale);
+ DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, ui::Transform transform,
+ float globalScaleFactor);
~DispatchEntry();
inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; }
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 0493130..82e0a4e 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -271,12 +271,11 @@
static std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget,
EventEntry* eventEntry,
int32_t inputTargetFlags) {
- if (inputTarget.useDefaultPointerInfo()) {
- const PointerInfo& pointerInfo = inputTarget.getDefaultPointerInfo();
+ if (inputTarget.useDefaultPointerTransform()) {
+ const ui::Transform& transform = inputTarget.getDefaultPointerTransform();
return std::make_unique<DispatchEntry>(eventEntry, // increments ref
- inputTargetFlags, pointerInfo.xOffset,
- pointerInfo.yOffset, inputTarget.globalScaleFactor,
- pointerInfo.windowXScale, pointerInfo.windowYScale);
+ inputTargetFlags, transform,
+ inputTarget.globalScaleFactor);
}
ALOG_ASSERT(eventEntry->type == EventEntry::Type::MOTION);
@@ -286,28 +285,24 @@
// Use the first pointer information to normalize all other pointers. This could be any pointer
// as long as all other pointers are normalized to the same value and the final DispatchEntry
- // uses the offset and scale for the normalized pointer.
- const PointerInfo& firstPointerInfo =
- inputTarget.pointerInfos[inputTarget.pointerIds.firstMarkedBit()];
+ // uses the transform for the normalized pointer.
+ const ui::Transform& firstPointerTransform =
+ inputTarget.pointerTransforms[inputTarget.pointerIds.firstMarkedBit()];
+ ui::Transform inverseFirstTransform = firstPointerTransform.inverse();
// Iterate through all pointers in the event to normalize against the first.
for (uint32_t pointerIndex = 0; pointerIndex < motionEntry.pointerCount; pointerIndex++) {
const PointerProperties& pointerProperties = motionEntry.pointerProperties[pointerIndex];
uint32_t pointerId = uint32_t(pointerProperties.id);
- const PointerInfo& currPointerInfo = inputTarget.pointerInfos[pointerId];
-
- // The scale factor is the ratio of the current pointers scale to the normalized scale.
- float scaleXDiff = currPointerInfo.windowXScale / firstPointerInfo.windowXScale;
- float scaleYDiff = currPointerInfo.windowYScale / firstPointerInfo.windowYScale;
+ const ui::Transform& currTransform = inputTarget.pointerTransforms[pointerId];
pointerCoords[pointerIndex].copyFrom(motionEntry.pointerCoords[pointerIndex]);
- // First apply the current pointers offset to set the window at 0,0
- pointerCoords[pointerIndex].applyOffset(currPointerInfo.xOffset, currPointerInfo.yOffset);
- // Next scale the coordinates.
- pointerCoords[pointerIndex].scale(1, scaleXDiff, scaleYDiff);
- // Lastly, offset the coordinates so they're in the normalized pointer's frame.
- pointerCoords[pointerIndex].applyOffset(-firstPointerInfo.xOffset,
- -firstPointerInfo.yOffset);
+ // First, apply the current pointer's transform to update the coordinates into
+ // window space.
+ pointerCoords[pointerIndex].transform(currTransform);
+ // Next, apply the inverse transform of the normalized coordinates so the
+ // current coordinates are transformed into the normalized coordinate space.
+ pointerCoords[pointerIndex].transform(inverseFirstTransform);
}
MotionEntry* combinedMotionEntry =
@@ -329,10 +324,8 @@
std::unique_ptr<DispatchEntry> dispatchEntry =
std::make_unique<DispatchEntry>(combinedMotionEntry, // increments ref
- inputTargetFlags, firstPointerInfo.xOffset,
- firstPointerInfo.yOffset, inputTarget.globalScaleFactor,
- firstPointerInfo.windowXScale,
- firstPointerInfo.windowYScale);
+ inputTargetFlags, firstPointerTransform,
+ inputTarget.globalScaleFactor);
combinedMotionEntry->release();
return dispatchEntry;
}
@@ -2045,8 +2038,7 @@
ALOG_ASSERT(it->flags == targetFlags);
ALOG_ASSERT(it->globalScaleFactor == windowInfo->globalScaleFactor);
- it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop,
- windowInfo->windowXScale, windowInfo->windowYScale);
+ it->addPointers(pointerIds, windowInfo->transform);
}
void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
@@ -2069,7 +2061,9 @@
InputTarget target;
target.inputChannel = monitor.inputChannel;
target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
- target.setDefaultPointerInfo(xOffset, yOffset, 1 /* windowXScale */, 1 /* windowYScale */);
+ ui::Transform t;
+ t.set(xOffset, yOffset);
+ target.setDefaultPointerTransform(t);
inputTargets.push_back(target);
}
@@ -2588,15 +2582,9 @@
const PointerCoords* usingCoords = motionEntry->pointerCoords;
// Set the X and Y offset and X and Y scale depending on the input source.
- float xOffset = 0.0f, yOffset = 0.0f;
- float xScale = 1.0f, yScale = 1.0f;
if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) &&
!(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
float globalScaleFactor = dispatchEntry->globalScaleFactor;
- xScale = dispatchEntry->windowXScale;
- yScale = dispatchEntry->windowYScale;
- xOffset = dispatchEntry->xOffset * xScale;
- yOffset = dispatchEntry->yOffset * yScale;
if (globalScaleFactor != 1.0f) {
for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
scaledCoords[i] = motionEntry->pointerCoords[i];
@@ -2631,8 +2619,12 @@
dispatchEntry->resolvedFlags,
motionEntry->edgeFlags, motionEntry->metaState,
motionEntry->buttonState,
- motionEntry->classification, xScale, yScale,
- xOffset, yOffset, motionEntry->xPrecision,
+ motionEntry->classification,
+ dispatchEntry->transform.dsdx(),
+ dispatchEntry->transform.dsdy(),
+ dispatchEntry->transform.tx(),
+ dispatchEntry->transform.ty(),
+ motionEntry->xPrecision,
motionEntry->yPrecision,
motionEntry->xCursorPosition,
motionEntry->yCursorPosition,
@@ -2910,8 +2902,7 @@
getWindowHandleLocked(connection->inputChannel->getConnectionToken());
if (windowHandle != nullptr) {
const InputWindowInfo* windowInfo = windowHandle->getInfo();
- target.setDefaultPointerInfo(-windowInfo->frameLeft, -windowInfo->frameTop,
- windowInfo->windowXScale, windowInfo->windowYScale);
+ target.setDefaultPointerTransform(windowInfo->transform);
target.globalScaleFactor = windowInfo->globalScaleFactor;
}
target.inputChannel = connection->inputChannel;
@@ -2976,8 +2967,7 @@
getWindowHandleLocked(connection->inputChannel->getConnectionToken());
if (windowHandle != nullptr) {
const InputWindowInfo* windowInfo = windowHandle->getInfo();
- target.setDefaultPointerInfo(-windowInfo->frameLeft, -windowInfo->frameTop,
- windowInfo->windowXScale, windowInfo->windowYScale);
+ target.setDefaultPointerTransform(windowInfo->transform);
target.globalScaleFactor = windowInfo->globalScaleFactor;
}
target.inputChannel = connection->inputChannel;
@@ -4221,7 +4211,7 @@
"hasWallpaper=%s, visible=%s, canReceiveKeys=%s, "
"flags=%s, type=0x%08x, "
"frame=[%d,%d][%d,%d], globalScale=%f, "
- "windowScale=(%f,%f), touchableRegion=",
+ "touchableRegion=",
i, windowInfo->name.c_str(), windowInfo->displayId,
windowInfo->portalToDisplayId,
toString(windowInfo->paused),
@@ -4229,13 +4219,11 @@
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,
- windowInfo->globalScaleFactor, windowInfo->windowXScale,
- windowInfo->windowYScale);
+ windowInfo->globalScaleFactor);
dumpRegion(dump, windowInfo->touchableRegion);
dump += StringPrintf(", inputFeatures=%s",
windowInfo->inputFeatures.string().c_str());
@@ -4243,6 +4231,7 @@
"ms\n",
windowInfo->ownerPid, windowInfo->ownerUid,
millis(windowInfo->dispatchingTimeout));
+ windowInfo->transform.dump(dump, INDENT4 "transform=");
}
} else {
dump += INDENT2 "Windows: <none>\n";
diff --git a/services/inputflinger/dispatcher/InputTarget.cpp b/services/inputflinger/dispatcher/InputTarget.cpp
index 0588374..f6958d4 100644
--- a/services/inputflinger/dispatcher/InputTarget.cpp
+++ b/services/inputflinger/dispatcher/InputTarget.cpp
@@ -42,12 +42,11 @@
return StringPrintf("%" PRId32, dispatchMode);
}
-void InputTarget::addPointers(BitSet32 newPointerIds, float xOffset, float yOffset,
- float windowXScale, float windowYScale) {
+void InputTarget::addPointers(BitSet32 newPointerIds, const ui::Transform& transform) {
// The pointerIds can be empty, but still a valid InputTarget. This can happen for Monitors
// and non splittable windows since we will just use all the pointers from the input event.
if (newPointerIds.isEmpty()) {
- setDefaultPointerInfo(xOffset, yOffset, windowXScale, windowYScale);
+ setDefaultPointerTransform(transform);
return;
}
@@ -57,47 +56,39 @@
pointerIds |= newPointerIds;
while (!newPointerIds.isEmpty()) {
int32_t pointerId = newPointerIds.clearFirstMarkedBit();
- pointerInfos[pointerId].xOffset = xOffset;
- pointerInfos[pointerId].yOffset = yOffset;
- pointerInfos[pointerId].windowXScale = windowXScale;
- pointerInfos[pointerId].windowYScale = windowYScale;
+ pointerTransforms[pointerId] = transform;
}
}
-void InputTarget::setDefaultPointerInfo(float xOffset, float yOffset, float windowXScale,
- float windowYScale) {
+void InputTarget::setDefaultPointerTransform(const ui::Transform& transform) {
pointerIds.clear();
- pointerInfos[0].xOffset = xOffset;
- pointerInfos[0].yOffset = yOffset;
- pointerInfos[0].windowXScale = windowXScale;
- pointerInfos[0].windowYScale = windowYScale;
+ pointerTransforms[0] = transform;
}
-bool InputTarget::useDefaultPointerInfo() const {
+bool InputTarget::useDefaultPointerTransform() const {
return pointerIds.isEmpty();
}
-const PointerInfo& InputTarget::getDefaultPointerInfo() const {
- return pointerInfos[0];
+const ui::Transform& InputTarget::getDefaultPointerTransform() const {
+ return pointerTransforms[0];
}
std::string InputTarget::getPointerInfoString() const {
- if (useDefaultPointerInfo()) {
- const PointerInfo& pointerInfo = getDefaultPointerInfo();
- return StringPrintf("xOffset=%.1f, yOffset=%.1f windowScaleFactor=(%.1f, %.1f)",
- pointerInfo.xOffset, pointerInfo.yOffset, pointerInfo.windowXScale,
- pointerInfo.windowYScale);
+ std::string out;
+ if (useDefaultPointerTransform()) {
+ const ui::Transform& transform = getDefaultPointerTransform();
+ transform.dump(out, "default");
+ return out;
}
- std::string out;
for (uint32_t i = pointerIds.firstMarkedBit(); i <= pointerIds.lastMarkedBit(); i++) {
if (!pointerIds.hasBit(i)) {
continue;
}
- out += StringPrintf("\n pointerId %d: xOffset=%.1f, yOffset=%.1f "
- "windowScaleFactor=(%.1f, %.1f)",
- i, pointerInfos[i].xOffset, pointerInfos[i].yOffset,
- pointerInfos[i].windowXScale, pointerInfos[i].windowYScale);
+
+ out += "\n";
+ const std::string name = "pointerId " + std::to_string(i) + ":";
+ pointerTransforms[i].dump(out, name.c_str());
}
return out;
}
diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h
index eeb6ee8..debf805 100644
--- a/services/inputflinger/dispatcher/InputTarget.h
+++ b/services/inputflinger/dispatcher/InputTarget.h
@@ -18,28 +18,13 @@
#define _UI_INPUT_INPUTDISPATCHER_INPUTTARGET_H
#include <input/InputTransport.h>
+#include <ui/Transform.h>
#include <utils/BitSet.h>
#include <utils/RefBase.h>
namespace android::inputdispatcher {
/*
- * Information about each pointer for an InputTarget. This includes offset and scale so
- * all pointers can be normalized to a single offset and scale.
- *
- * These values are ignored for KeyEvents
- */
-struct PointerInfo {
- // The x and y offset to add to a MotionEvent as it is delivered.
- float xOffset = 0.0f;
- float yOffset = 0.0f;
-
- // Scaling factor to apply to MotionEvent as it is delivered.
- float windowXScale = 1.0f;
- float windowYScale = 1.0f;
-};
-
-/*
* An input target specifies how an input event is to be dispatched to a particular window
* including the window's input channel, control flags, a timeout, and an X / Y offset to
* be added to input event coordinates to compensate for the absolute position of the
@@ -119,13 +104,11 @@
// if FLAG_SPLIT is set.
BitSet32 pointerIds;
// The data is stored by the pointerId. Use the bit position of pointerIds to look up
- // PointerInfo per pointerId.
- PointerInfo pointerInfos[MAX_POINTERS];
+ // Transform per pointerId.
+ ui::Transform pointerTransforms[MAX_POINTERS];
- void addPointers(BitSet32 pointerIds, float xOffset, float yOffset, float windowXScale,
- float windowYScale);
- void setDefaultPointerInfo(float xOffset, float yOffset, float windowXScale,
- float windowYScale);
+ void addPointers(BitSet32 pointerIds, const ui::Transform& transform);
+ void setDefaultPointerTransform(const ui::Transform& transform);
/**
* Returns whether the default pointer information should be used. This will be true when the
@@ -133,13 +116,13 @@
* and non splittable windows since we want all pointers for the EventEntry to go to this
* target.
*/
- bool useDefaultPointerInfo() const;
+ bool useDefaultPointerTransform() const;
/**
- * Returns the default PointerInfo object. This should be used when useDefaultPointerInfo is
+ * Returns the default Transform object. This should be used when useDefaultPointerTransform is
* true.
*/
- const PointerInfo& getDefaultPointerInfo() const;
+ const ui::Transform& getDefaultPointerTransform() const;
std::string getPointerInfoString() const;
};
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 89314e1..4cf4909 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -755,11 +755,11 @@
int32_t displayId, sp<IBinder> token = nullptr)
: mName(name) {
if (token == nullptr) {
- std::shared_ptr<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();
@@ -774,6 +774,7 @@
mInfo.frameTop = 0;
mInfo.frameRight = WIDTH;
mInfo.frameBottom = HEIGHT;
+ mInfo.transform.set(0, 0);
mInfo.globalScaleFactor = 1.0;
mInfo.touchableRegion.clear();
mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
@@ -802,16 +803,14 @@
mInfo.frameTop = frame.top;
mInfo.frameRight = frame.right;
mInfo.frameBottom = frame.bottom;
+ mInfo.transform.set(frame.left, frame.top);
mInfo.touchableRegion.clear();
mInfo.addTouchableRegion(frame);
}
void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
- void setWindowScale(float xScale, float yScale) {
- mInfo.windowXScale = xScale;
- mInfo.windowYScale = yScale;
- }
+ void setWindowScale(float xScale, float yScale) { mInfo.transform.set(xScale, 0, 0, yScale); }
void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
@@ -1768,10 +1767,10 @@
public:
FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
int32_t displayId, bool isGestureMonitor = false) {
- std::shared_ptr<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(); }
@@ -2459,9 +2458,8 @@
// Helper function to convert the point from screen coordinates into the window's space
static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
- float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
- float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
- return {x, y};
+ vec2 vals = windowInfo->transform.transform(point.x, point.y);
+ return {vals.x, vals.y};
}
void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp
index 282b4fa..d6543f2 100644
--- a/services/inputflinger/tests/InputFlingerService_test.cpp
+++ b/services/inputflinger/tests/InputFlingerService_test.cpp
@@ -116,7 +116,7 @@
private:
sp<SetInputWindowsListener> mSetInputWindowsListener;
- std::shared_ptr<InputChannel> mServerChannel, mClientChannel;
+ std::unique_ptr<InputChannel> mServerChannel, mClientChannel;
InputWindowInfo mInfo;
std::mutex mLock;
std::condition_variable mSetInputWindowsFinishedCondition;
@@ -291,8 +291,8 @@
mInfo.frameBottom = TestInfoFrameBottom;
mInfo.surfaceInset = TestInfoSurfaceInset;
mInfo.globalScaleFactor = TestInfoGlobalScaleFactor;
- mInfo.windowXScale = TestInfoWindowXScale;
- mInfo.windowYScale = TestInfoWindowYScale;
+ mInfo.transform.set(std::array<float, 9>{TestInfoWindowXScale, 0, TestInfoFrameLeft, 0,
+ TestInfoWindowYScale, TestInfoFrameTop, 0, 0, 1});
mInfo.touchableRegion = TestInfoTouchableRegion;
mInfo.visible = TestInfoVisible;
mInfo.canReceiveKeys = TestInfoCanReceiveKeys;
@@ -369,7 +369,7 @@
* Test InputFlinger service interface registerInputChannel
*/
TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) {
- std::shared_ptr<InputChannel> serverChannel, clientChannel;
+ std::unique_ptr<InputChannel> serverChannel, clientChannel;
InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
mService->registerInputChannel(*serverChannel);
@@ -388,7 +388,7 @@
* Test InputFlinger service interface registerInputChannel with invalid cases
*/
TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) {
- std::shared_ptr<InputChannel> serverChannel, clientChannel;
+ std::unique_ptr<InputChannel> serverChannel, clientChannel;
InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
std::vector<::android::InputChannel> channels;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 70822bd..89c95d2 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2387,17 +2387,8 @@
}
ui::Transform t = getTransform();
- const float xScale = t.dsdx();
- const float yScale = t.dsdy();
int32_t xSurfaceInset = info.surfaceInset;
int32_t ySurfaceInset = info.surfaceInset;
- if (xScale != 1.0f || yScale != 1.0f) {
- info.windowXScale *= (xScale != 0.0f) ? 1.0f / xScale : 0.0f;
- info.windowYScale *= (yScale != 0.0f) ? 1.0f / yScale : 0.0f;
- info.touchableRegion.scaleSelf(xScale, yScale);
- xSurfaceInset = std::round(xSurfaceInset * xScale);
- ySurfaceInset = std::round(ySurfaceInset * yScale);
- }
// Transform layer size to screen space and inset it by surface insets.
// If this is a portal window, set the touchableRegion to the layerBounds.
@@ -2407,6 +2398,15 @@
if (!layerBounds.isValid()) {
layerBounds = getCroppedBufferSize(getDrawingState());
}
+
+ const float xScale = t.getScaleX();
+ const float yScale = t.getScaleY();
+ if (xScale != 1.0f || yScale != 1.0f) {
+ info.touchableRegion.scaleSelf(xScale, yScale);
+ xSurfaceInset = std::round(xSurfaceInset * xScale);
+ ySurfaceInset = std::round(ySurfaceInset * yScale);
+ }
+
layerBounds = t.transform(layerBounds);
// clamp inset to layer bounds
@@ -2421,6 +2421,10 @@
info.frameRight = layerBounds.right;
info.frameBottom = layerBounds.bottom;
+ ui::Transform inputTransform(t);
+ inputTransform.set(layerBounds.left, layerBounds.top);
+ info.transform = inputTransform.inverse();
+
// Position the touchable region relative to frame screen location and restrict it to frame
// bounds.
info.touchableRegion = info.touchableRegion.translate(info.frameLeft, info.frameTop);
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index dd65cf4..5d99908 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -151,8 +151,7 @@
proto->set_has_wallpaper(inputInfo.hasWallpaper);
proto->set_global_scale_factor(inputInfo.globalScaleFactor);
- proto->set_window_x_scale(inputInfo.windowXScale);
- proto->set_window_y_scale(inputInfo.windowYScale);
+ LayerProtoHelper::writeToProto(inputInfo.transform, proto->mutable_transform());
proto->set_replace_touchable_region_with_crop(inputInfo.replaceTouchableRegionWithCrop);
auto cropLayer = touchableRegionBounds.promote();
if (cropLayer != nullptr) {
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index 7f1f542..8458d54 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -196,12 +196,13 @@
bool has_wallpaper = 9;
float global_scale_factor = 10;
- float window_x_scale = 11;
- float window_y_scale = 12;
+ float window_x_scale = 11 [deprecated=true];
+ float window_y_scale = 12 [deprecated=true];
uint32 crop_layer_id = 13;
bool replace_touchable_region_with_crop = 14;
RectProto touchable_region_crop = 15;
+ TransformProto transform = 16;
}
message ColorTransformProto {