Merge "Add function for scaling haptic data."
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 28fdaa4..fc3572c 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -239,6 +239,10 @@
{ OPT, "events/kmem/ion_heap_shrink/enable" },
{ OPT, "events/ion/ion_stat/enable" },
} },
+ { "thermal", "Thermal event", 0, {
+ { REQ, "events/thermal/thermal_temperature/enable" },
+ { OPT, "events/thermal/cdev_update/enable" },
+ } },
};
struct TracingVendorCategory {
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index f442dae..d2ccef1 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -166,6 +166,12 @@
chmod 0666 /sys/kernel/tracing/events/filemap/mm_filemap_delete_from_page_cache/enable
chmod 0666 /sys/kernel/debug/tracing/events/filemap/mm_filemap_delete_from_page_cache/enable
+ # thermal
+ chmod 0666 /sys/kernel/debug/tracing/events/thermal/thermal_temperature/enable
+ chmod 0666 /sys/kernel/tracing/events/thermal/thermal_temperature/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/thermal/cdev_update/enable
+ chmod 0666 /sys/kernel/tracing/events/thermal/cdev_update/enable
+
# Tracing disabled by default
write /sys/kernel/debug/tracing/tracing_on 0
write /sys/kernel/tracing/tracing_on 0
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 5afae4b..987adaf 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -75,7 +75,7 @@
defaults: ["lshal_defaults"],
gtest: true,
static_libs: [
- "android.hardware.tests.baz@1.0",
+ "android.hardware.tests.inheritance@1.0",
"libgmock",
],
shared_libs: [
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index af22ac9..72958bd 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -39,7 +39,7 @@
// Optargs cannnot be used because the flag should not be considered set
// if it should really be contained in mOptions.
if (std::string(arg.argv[optind]) == "-E") {
- mExcludesParentInstances = true;
+ mParentDebugInfoLevel = ParentDebugInfoLevel::NOTHING;
optind++;
}
@@ -67,7 +67,7 @@
return mLshal.emitDebugInfo(
pair.first, pair.second.empty() ? "default" : pair.second, mOptions,
- mExcludesParentInstances,
+ mParentDebugInfoLevel,
mLshal.out().buf(),
mLshal.err());
}
diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h
index cd57e31..317cc28 100644
--- a/cmds/lshal/DebugCommand.h
+++ b/cmds/lshal/DebugCommand.h
@@ -21,6 +21,7 @@
#include <android-base/macros.h>
#include "Command.h"
+#include "ParentDebugInfoLevel.h"
#include "utils.h"
namespace android {
@@ -42,9 +43,8 @@
std::string mInterfaceName;
std::vector<std::string> mOptions;
- // Outputs the actual descriptor of a hal instead of the debug output
- // if the arguments provided are a superclass of the actual hal impl.
- bool mExcludesParentInstances;
+ // See comment on ParentDebugInfoLevel.
+ ParentDebugInfoLevel mParentDebugInfoLevel = ParentDebugInfoLevel::FULL;
DISALLOW_COPY_AND_ASSIGN(DebugCommand);
};
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index fb11cee..a805a48 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -555,7 +555,7 @@
std::stringstream ss;
auto pair = splitFirst(iName, '/');
mLshal.emitDebugInfo(pair.first, pair.second, {},
- false /* excludesParentInstances */, ss,
+ ParentDebugInfoLevel::FQNAME_ONLY, ss,
NullableOStream<std::ostream>(nullptr));
return ss.str();
};
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 132b31e..2c3efe5 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -101,7 +101,7 @@
const std::string &interfaceName,
const std::string &instanceName,
const std::vector<std::string> &options,
- bool excludesParentInstances,
+ ParentDebugInfoLevel parentDebugInfoLevel,
std::ostream &out,
NullableOStream<std::ostream> err) const {
using android::hidl::base::V1_0::IBase;
@@ -126,7 +126,7 @@
return NO_INTERFACE;
}
- if (excludesParentInstances) {
+ if (parentDebugInfoLevel != ParentDebugInfoLevel::FULL) {
const std::string descriptor = getDescriptor(base.get());
if (descriptor.empty()) {
std::string msg = interfaceName + "/" + instanceName + " getDescriptor failed";
@@ -134,6 +134,9 @@
LOG(ERROR) << msg;
}
if (descriptor != interfaceName) {
+ if (parentDebugInfoLevel == ParentDebugInfoLevel::FQNAME_ONLY) {
+ out << "[See " << descriptor << "/" << instanceName << "]";
+ }
return OK;
}
}
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
index 830bd87..50279d4 100644
--- a/cmds/lshal/Lshal.h
+++ b/cmds/lshal/Lshal.h
@@ -25,6 +25,7 @@
#include "Command.h"
#include "NullableOStream.h"
+#include "ParentDebugInfoLevel.h"
#include "utils.h"
namespace android {
@@ -49,7 +50,7 @@
const std::string &interfaceName,
const std::string &instanceName,
const std::vector<std::string> &options,
- bool excludesParentInstances,
+ ParentDebugInfoLevel parentDebugInfoLevel,
std::ostream &out,
NullableOStream<std::ostream> err) const;
diff --git a/cmds/lshal/ParentDebugInfoLevel.h b/cmds/lshal/ParentDebugInfoLevel.h
new file mode 100644
index 0000000..12ac9c8
--- /dev/null
+++ b/cmds/lshal/ParentDebugInfoLevel.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+#pragma once
+
+namespace android {
+namespace lshal {
+
+// Describe verbosity when dumping debug information on a HAL service by
+// referring to a parent HAL interface FQName (for example, when dumping debug information
+// on foo@1.0::IFoo but the HAL implementation is foo@1.1::IFoo).
+enum class ParentDebugInfoLevel {
+ // Write nothing.
+ NOTHING,
+ // Write a short description that includes the FQName of the real implementation.
+ FQNAME_ONLY,
+ // Write full debug info.
+ FULL,
+};
+
+} // namespace lshal
+} // namespace android
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 3d550ba..afe5d63 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -24,7 +24,7 @@
#include <gtest/gtest.h>
#include <gmock/gmock.h>
-#include <android/hardware/tests/baz/1.0/IQuux.h>
+#include <android/hardware/tests/inheritance/1.0/IChild.h>
#include <hidl/HidlTransportSupport.h>
#include <vintf/parse_xml.h>
@@ -44,6 +44,7 @@
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
+using ::android::hardware::Void;
using android::vintf::Arch;
using android::vintf::CompatibilityMatrix;
using android::vintf::gCompatibilityMatrixConverter;
@@ -59,10 +60,14 @@
namespace android {
namespace hardware {
namespace tests {
-namespace baz {
+namespace inheritance {
namespace V1_0 {
namespace implementation {
-struct Quux : android::hardware::tests::baz::V1_0::IQuux {
+struct Child : android::hardware::tests::inheritance::V1_0::IChild {
+ ::android::hardware::Return<void> doChild() override { return Void(); }
+ ::android::hardware::Return<void> doParent() override { return Void(); }
+ ::android::hardware::Return<void> doGrandparent() override { return Void(); }
+
::android::hardware::Return<void> debug(const hidl_handle& hh, const hidl_vec<hidl_string>& options) override {
const native_handle_t *handle = hh.getNativeHandle();
if (handle->numFds < 1) {
@@ -76,7 +81,7 @@
}
ssize_t written = write(fd, content.c_str(), content.size());
if (written != (ssize_t)content.size()) {
- LOG(WARNING) << "SERVER(Quux) debug writes " << written << " bytes < "
+ LOG(WARNING) << "SERVER(Child) debug writes " << written << " bytes < "
<< content.size() << " bytes, errno = " << errno;
}
return Void();
@@ -85,7 +90,7 @@
} // namespace implementation
} // namespace V1_0
-} // namespace baz
+} // namespace inheritance
} // namespace tests
} // namespace hardware
@@ -124,18 +129,24 @@
class DebugTest : public ::testing::Test {
public:
void SetUp() override {
- using ::android::hardware::tests::baz::V1_0::IQuux;
- using ::android::hardware::tests::baz::V1_0::implementation::Quux;
+ using ::android::hardware::tests::inheritance::V1_0::IChild;
+ using ::android::hardware::tests::inheritance::V1_0::IParent;
+ using ::android::hardware::tests::inheritance::V1_0::IGrandparent;
+ using ::android::hardware::tests::inheritance::V1_0::implementation::Child;
err.str("");
out.str("");
serviceManager = new testing::NiceMock<MockServiceManager>();
- ON_CALL(*serviceManager, get(_, _)).WillByDefault(Invoke(
- [](const auto &iface, const auto &inst) -> ::android::hardware::Return<sp<IBase>> {
- if (iface == IQuux::descriptor && inst == "default")
- return new Quux();
- return nullptr;
- }));
+ ON_CALL(*serviceManager, get(_, _))
+ .WillByDefault(
+ Invoke([](const auto& iface,
+ const auto& inst) -> ::android::hardware::Return<sp<IBase>> {
+ if (inst != "default") return nullptr;
+ if (iface == IChild::descriptor || iface == IParent::descriptor ||
+ iface == IGrandparent::descriptor)
+ return new Child();
+ return nullptr;
+ }));
lshal = std::make_unique<Lshal>(out, err, serviceManager, serviceManager);
}
@@ -159,17 +170,17 @@
TEST_F(DebugTest, Debug) {
EXPECT_EQ(0u, callMain(lshal, {
- "lshal", "debug", "android.hardware.tests.baz@1.0::IQuux/default", "foo", "bar"
+ "lshal", "debug", "android.hardware.tests.inheritance@1.0::IChild/default", "foo", "bar"
}));
- EXPECT_THAT(out.str(), StrEq("android.hardware.tests.baz@1.0::IQuux\nfoo\nbar"));
+ EXPECT_THAT(out.str(), StrEq("android.hardware.tests.inheritance@1.0::IChild\nfoo\nbar"));
EXPECT_THAT(err.str(), IsEmpty());
}
TEST_F(DebugTest, Debug2) {
EXPECT_EQ(0u, callMain(lshal, {
- "lshal", "debug", "android.hardware.tests.baz@1.0::IQuux", "baz", "quux"
+ "lshal", "debug", "android.hardware.tests.inheritance@1.0::IChild", "baz", "quux"
}));
- EXPECT_THAT(out.str(), StrEq("android.hardware.tests.baz@1.0::IQuux\nbaz\nquux"));
+ EXPECT_THAT(out.str(), StrEq("android.hardware.tests.inheritance@1.0::IChild\nbaz\nquux"));
EXPECT_THAT(err.str(), IsEmpty());
}
@@ -180,6 +191,22 @@
EXPECT_THAT(err.str(), HasSubstr("does not exist"));
}
+TEST_F(DebugTest, DebugParent) {
+ EXPECT_EQ(0u, callMain(lshal, {
+ "lshal", "debug", "android.hardware.tests.inheritance@1.0::IParent", "calling parent"
+ }));
+ EXPECT_THAT(out.str(), StrEq("android.hardware.tests.inheritance@1.0::IChild\ncalling parent"));
+ EXPECT_THAT(err.str(), IsEmpty());
+}
+
+TEST_F(DebugTest, DebugParentExclude) {
+ EXPECT_EQ(0u, callMain(lshal, {
+ "lshal", "debug", "-E", "android.hardware.tests.inheritance@1.0::IParent", "excluding"
+ }));
+ EXPECT_THAT(out.str(), IsEmpty());
+ EXPECT_THAT(err.str(), IsEmpty());
+}
+
class MockLshal : public Lshal {
public:
MockLshal() {}
@@ -766,6 +793,91 @@
EXPECT_EQ("", err.str());
}
+// Fake service returned by mocked IServiceManager::get for DumpDebug.
+// The interfaceChain and getHashChain functions returns
+// foo(id - 1) -> foo(id - 2) -> ... foo1 -> IBase.
+class InheritingService : public IBase {
+public:
+ explicit InheritingService(pid_t id) : mId(id) {}
+ android::hardware::Return<void> interfaceDescriptor(interfaceDescriptor_cb cb) override {
+ cb(getInterfaceName(mId));
+ return hardware::Void();
+ }
+ android::hardware::Return<void> interfaceChain(interfaceChain_cb cb) override {
+ std::vector<hidl_string> ret;
+ for (auto i = mId; i > 0; --i) {
+ ret.push_back(getInterfaceName(i));
+ }
+ ret.push_back(IBase::descriptor);
+ cb(ret);
+ return hardware::Void();
+ }
+ android::hardware::Return<void> getHashChain(getHashChain_cb cb) override {
+ std::vector<hidl_hash> ret;
+ for (auto i = mId; i > 0; --i) {
+ ret.push_back(getHashFromId(i));
+ }
+ ret.push_back(getHashFromId(0xff));
+ cb(ret);
+ return hardware::Void();
+ }
+ android::hardware::Return<void> debug(const hidl_handle& hh,
+ const hidl_vec<hidl_string>&) override {
+ const native_handle_t* handle = hh.getNativeHandle();
+ if (handle->numFds < 1) {
+ return Void();
+ }
+ int fd = handle->data[0];
+ std::string content = "debug info for ";
+ content += getInterfaceName(mId);
+ ssize_t written = write(fd, content.c_str(), content.size());
+ if (written != (ssize_t)content.size()) {
+ LOG(WARNING) << "SERVER(" << descriptor << ") debug writes " << written << " bytes < "
+ << content.size() << " bytes, errno = " << errno;
+ }
+ return Void();
+ }
+
+private:
+ pid_t mId;
+};
+
+TEST_F(ListTest, DumpDebug) {
+ size_t inheritanceLevel = 3;
+ sp<IBase> service = new InheritingService(inheritanceLevel);
+
+ EXPECT_CALL(*serviceManager, list(_)).WillRepeatedly(Invoke([&](IServiceManager::list_cb cb) {
+ std::vector<hidl_string> ret;
+ for (auto i = 1; i <= inheritanceLevel; ++i) {
+ ret.push_back(getInterfaceName(i) + "/default");
+ }
+ cb(ret);
+ return hardware::Void();
+ }));
+ EXPECT_CALL(*serviceManager, get(_, _))
+ .WillRepeatedly(
+ Invoke([&](const hidl_string&, const hidl_string& instance) -> sp<IBase> {
+ int id = getIdFromInstanceName(instance);
+ if (id > inheritanceLevel) return nullptr;
+ return sp<IBase>(service);
+ }));
+
+ const std::string expected = "[fake description 0]\n"
+ "Interface\n"
+ "a.h.foo1@1.0::IFoo/default\n"
+ "[See a.h.foo3@3.0::IFoo/default]\n"
+ "a.h.foo2@2.0::IFoo/default\n"
+ "[See a.h.foo3@3.0::IFoo/default]\n"
+ "a.h.foo3@3.0::IFoo/default\n"
+ "debug info for a.h.foo3@3.0::IFoo\n"
+ "\n";
+
+ optind = 1; // mimic Lshal::parseArg()
+ EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--types=b", "-id"})));
+ EXPECT_EQ(expected, out.str());
+ EXPECT_EQ("", err.str());
+}
+
class ListVintfTest : public ListTest {
public:
virtual void SetUp() override {
diff --git a/include/android/hardware_buffer_jni.h b/include/android/hardware_buffer_jni.h
index 293e5ac..ae208a6 100644
--- a/include/android/hardware_buffer_jni.h
+++ b/include/android/hardware_buffer_jni.h
@@ -39,9 +39,9 @@
* Return the AHardwareBuffer wrapped by a Java HardwareBuffer object.
*
* This method does not acquire any additional reference to the AHardwareBuffer
- * that is returned. To keep the AHardwareBuffer live after the Java
- * HardwareBuffer object got garbage collected, be sure to use AHardwareBuffer_acquire()
- * to acquire an additional reference.
+ * that is returned. To keep the AHardwareBuffer alive after the Java
+ * HardwareBuffer object is closed, explicitly or by the garbage collector, be
+ * sure to use AHardwareBuffer_acquire() to acquire an additional reference.
*
* Available since API level 26.
*/
@@ -50,7 +50,18 @@
/**
* Return a new Java HardwareBuffer object that wraps the passed native
- * AHardwareBuffer object.
+ * AHardwareBuffer object. The Java HardwareBuffer will acquire a reference to
+ * the internal buffer and manage its lifetime. For example:
+ *
+ * <pre><code>
+ * AHardwareBuffer* buffer;
+ * AHardwareBuffer_allocate(..., &buffer); // `buffer` has reference count 1
+ * jobject java_result = AHardwareBuffer_toHardwareBuffer(buffer); // `buffer` has reference count 2.
+ * AHardwareBuffer_release(buffer); // `buffer` has reference count 1
+ * return result; // The underlying buffer is kept alive by `java_result` and
+ * // will be set to 0 when it is closed on the Java side with
+ * // HardwareBuffer::close().
+ * </code></pre>
*
* Available since API level 26.
*/
diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h
index 2427a07..334fe34 100644
--- a/include/input/DisplayViewport.h
+++ b/include/input/DisplayViewport.h
@@ -17,12 +17,12 @@
#ifndef _LIBINPUT_DISPLAY_VIEWPORT_H
#define _LIBINPUT_DISPLAY_VIEWPORT_H
-#include <cinttypes>
-#include <optional>
-
#include <android-base/stringprintf.h>
#include <input/Input.h>
+#include <cinttypes>
+#include <optional>
+
using android::base::StringPrintf;
namespace android {
@@ -39,22 +39,21 @@
* Keep in sync with values in InputManagerService.java.
*/
enum class ViewportType : int32_t {
- VIEWPORT_INTERNAL = 1,
- VIEWPORT_EXTERNAL = 2,
- VIEWPORT_VIRTUAL = 3,
+ INTERNAL = 1,
+ EXTERNAL = 2,
+ VIRTUAL = 3,
};
static const char* viewportTypeToString(ViewportType type) {
- switch(type) {
- case ViewportType::VIEWPORT_INTERNAL:
+ switch (type) {
+ case ViewportType::INTERNAL:
return "INTERNAL";
- case ViewportType::VIEWPORT_EXTERNAL:
+ case ViewportType::EXTERNAL:
return "EXTERNAL";
- case ViewportType::VIEWPORT_VIRTUAL:
+ case ViewportType::VIRTUAL:
return "VIRTUAL";
- default:
- return "UNKNOWN";
}
+ return "UNKNOWN";
}
/*
@@ -97,7 +96,7 @@
isActive(false),
uniqueId(),
physicalPort(std::nullopt),
- type(ViewportType::VIEWPORT_INTERNAL) {}
+ type(ViewportType::INTERNAL) {}
bool operator==(const DisplayViewport& other) const {
return displayId == other.displayId && orientation == other.orientation &&
@@ -134,7 +133,7 @@
isActive = false;
uniqueId.clear();
physicalPort = std::nullopt;
- type = ViewportType::VIEWPORT_INTERNAL;
+ type = ViewportType::INTERNAL;
}
std::string toString() const {
diff --git a/include/input/Flags.h b/include/input/Flags.h
new file mode 100644
index 0000000..f3198c9
--- /dev/null
+++ b/include/input/Flags.h
@@ -0,0 +1,179 @@
+/*
+ * 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 <android-base/stringprintf.h>
+
+#include <cstdint>
+#include <optional>
+#include <string>
+#include <type_traits>
+
+#include "utils/BitSet.h"
+
+#ifndef __UI_INPUT_FLAGS_H
+#define __UI_INPUT_FLAGS_H
+
+namespace android {
+
+// 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 {};
+
+// By definition, an enum class is an enum that is not implicitly convertible to its underlying
+// type.
+template <typename T>
+struct is_enum_class<T, true>
+ : std::bool_constant<!std::is_convertible_v<T, std::underlying_type_t<T>>> {};
+
+template <typename T>
+inline constexpr bool is_enum_class_v = is_enum_class<T>::value;
+
+/* 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>>>
+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.
+ 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) {}
+
+ // 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) {}
+ template <typename T = U>
+ explicit constexpr Flags(T t, typename std::enable_if_t<is_enum_class_v<F>, T>* = nullptr)
+ : flags(t) {}
+ /*
+ * Tests whether the given flag is set.
+ */
+ bool test(F flag) const {
+ U f = static_cast<U>(flag);
+ return (f & flags) == f;
+ }
+
+ /* Tests whether any of the given flags are set */
+ bool any(Flags<F> f) { return (flags & f.flags) != 0; }
+
+ /* Tests whether all of the given flags are set */
+ bool all(Flags<F> f) { return (flags & f.flags) == f.flags; }
+
+ Flags<F> operator|(Flags<F> rhs) const { return static_cast<F>(flags | rhs.flags); }
+ Flags<F>& operator|=(Flags<F> rhs) {
+ flags = flags | rhs.flags;
+ return *this;
+ }
+
+ Flags<F> operator&(Flags<F> rhs) const { return static_cast<F>(flags & rhs.flags); }
+ Flags<F>& operator&=(Flags<F> rhs) {
+ flags = flags & rhs.flags;
+ return *this;
+ }
+
+ Flags<F> operator^(Flags<F> rhs) const { return static_cast<F>(flags ^ rhs.flags); }
+ Flags<F>& operator^=(Flags<F> rhs) {
+ flags = flags ^ rhs.flags;
+ return *this;
+ }
+
+ Flags<F> operator~() { return static_cast<F>(~flags); }
+
+ bool operator==(Flags<F> rhs) const { return flags == rhs.flags; }
+ bool operator!=(Flags<F> rhs) const { return !operator==(rhs); }
+
+ Flags<F>& operator=(const Flags<F>& rhs) {
+ flags = rhs.flags;
+ return *this;
+ }
+
+ /*
+ * Returns the stored set of flags.
+ *
+ * Note that this returns the underlying type rather than the base enum class. This is because
+ * 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; }
+
+ 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 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));
+ if (flagString) {
+ appendFlag(result, flagString.value(), first);
+ } else {
+ unstringified |= flag;
+ }
+ }
+
+ if (unstringified != 0) {
+ appendFlag(result, base::StringPrintf("0x%08x", unstringified), first);
+ }
+
+ if (first) {
+ result += "0x0";
+ }
+
+ return result;
+ }
+
+private:
+ U flags;
+
+ static std::optional<std::string> defaultStringify(F) { return std::nullopt; }
+ static void appendFlag(std::string& str, const std::string& flag, bool& first) {
+ if (first) {
+ first = false;
+ } else {
+ str += " | ";
+ }
+ str += flag;
+ }
+};
+
+// This namespace provides operator overloads for enum classes to make it easier to work with them
+// 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>>>
+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>>>
+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));
+}
+
+} // namespace flag_operators
+} // namespace android
+
+#endif // __UI_INPUT_FLAGS_H
\ No newline at end of file
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
deleted file mode 100644
index d23e3b7..0000000
--- a/include/input/IInputFlinger.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2013 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 _LIBINPUT_IINPUT_FLINGER_H
-#define _LIBINPUT_IINPUT_FLINGER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/IInterface.h>
-
-#include <input/InputWindow.h>
-#include <input/ISetInputWindowsListener.h>
-
-namespace android {
-
-/*
- * This class defines the Binder IPC interface for accessing various
- * InputFlinger features.
- */
-class IInputFlinger : public IInterface {
-public:
- DECLARE_META_INTERFACE(InputFlinger)
-
- virtual void setInputWindows(const std::vector<InputWindowInfo>& inputHandles,
- const sp<ISetInputWindowsListener>& setInputWindowsListener) = 0;
- virtual void registerInputChannel(const sp<InputChannel>& channel) = 0;
- virtual void unregisterInputChannel(const sp<InputChannel>& channel) = 0;
-};
-
-
-/**
- * Binder implementation.
- */
-class BnInputFlinger : public BnInterface<IInputFlinger> {
-public:
- enum {
- SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
- REGISTER_INPUT_CHANNEL_TRANSACTION,
- UNREGISTER_INPUT_CHANNEL_TRANSACTION
- };
-
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags = 0);
-};
-
-} // namespace android
-
-#endif // _LIBINPUT_IINPUT_FLINGER_H
diff --git a/include/input/ISetInputWindowsListener.h b/include/input/ISetInputWindowsListener.h
deleted file mode 100644
index 15d31b2..0000000
--- a/include/input/ISetInputWindowsListener.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#pragma once
-
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class ISetInputWindowsListener : public IInterface {
-public:
- DECLARE_META_INTERFACE(SetInputWindowsListener)
- virtual void onSetInputWindowsFinished() = 0;
-};
-
-class BnSetInputWindowsListener: public BnInterface<ISetInputWindowsListener> {
-public:
- enum SetInputWindowsTag : uint32_t {
- ON_SET_INPUT_WINDOWS_FINISHED
- };
-
- virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0) override;
-};
-
-}; // namespace android
diff --git a/include/input/Input.h b/include/input/Input.h
index ac901ae..40d655f 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -26,6 +26,7 @@
#include <android/input.h>
#include <math.h>
#include <stdint.h>
+#include <ui/Transform.h>
#include <utils/BitSet.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
@@ -341,6 +342,8 @@
void scale(float globalScale, float windowXScale, float windowYScale);
void applyOffset(float xOffset, float yOffset);
+ void transform(const ui::Transform& transform);
+
inline float getX() const {
return getAxisValue(AMOTION_EVENT_AXIS_X);
}
@@ -741,6 +744,7 @@
float mYScale;
float mXOffset;
float mYOffset;
+ ui::Transform mTransform;
float mXPrecision;
float mYPrecision;
float mRawXCursorPosition;
diff --git a/include/input/InputApplication.h b/include/input/InputApplication.h
index ccffeb1..b6b9353 100644
--- a/include/input/InputApplication.h
+++ b/include/input/InputApplication.h
@@ -21,6 +21,7 @@
#include <binder/IBinder.h>
#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
#include <input/Input.h>
#include <utils/RefBase.h>
@@ -31,15 +32,17 @@
/*
* Describes the properties of an application that can receive input.
*/
-struct InputApplicationInfo {
+struct InputApplicationInfo : public Parcelable {
sp<IBinder> token;
std::string name;
std::chrono::nanoseconds dispatchingTimeout;
- status_t write(Parcel& output) const;
- static InputApplicationInfo read(const Parcel& from);
-};
+ InputApplicationInfo() = default;
+ status_t readFromParcel(const android::Parcel* parcel) override;
+
+ status_t writeToParcel(android::Parcel* parcel) const override;
+};
/*
* Handle for an application that can receive input.
@@ -76,6 +79,7 @@
* Returns true on success, or false if the handle is no longer valid.
*/
virtual bool updateInfo() = 0;
+
protected:
InputApplicationHandle();
virtual ~InputApplicationHandle();
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 20a17e3..c7685b7 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -144,10 +144,10 @@
};
/* Types of input device configuration files. */
-enum InputDeviceConfigurationFileType {
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION = 0, /* .idc file */
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT = 1, /* .kl file */
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP = 2, /* .kcm file */
+enum class InputDeviceConfigurationFileType : int32_t {
+ CONFIGURATION = 0, /* .idc file */
+ KEY_LAYOUT = 1, /* .kl file */
+ KEY_CHARACTER_MAP = 2, /* .kcm file */
};
/*
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 7ca9031..09cebef 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -34,12 +34,13 @@
#include <android-base/chrono_utils.h>
#include <binder/IBinder.h>
+#include <binder/Parcelable.h>
#include <input/Input.h>
+#include <sys/stat.h>
#include <utils/BitSet.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
-#include <utils/Vector.h>
#include <android-base/unique_fd.h>
@@ -69,10 +70,7 @@
struct Header {
Type type; // 4 bytes
- // We don't need this field in order to align the body below but we
- // leave it here because InputMessage::size() and other functions
- // compute the size of this structure as sizeof(Header) + sizeof(Body).
- uint32_t padding;
+ uint32_t seq;
} header;
// Body *must* be 8 byte aligned.
@@ -81,8 +79,8 @@
static_assert(sizeof(std::array<uint8_t, 32>) == 32);
union Body {
struct Key {
- uint32_t seq;
int32_t eventId;
+ uint32_t empty1;
nsecs_t eventTime __attribute__((aligned(8)));
int32_t deviceId;
int32_t source;
@@ -101,8 +99,8 @@
} key;
struct Motion {
- uint32_t seq;
int32_t eventId;
+ uint32_t empty1;
nsecs_t eventTime __attribute__((aligned(8)));
int32_t deviceId;
int32_t source;
@@ -151,16 +149,14 @@
} motion;
struct Finished {
- uint32_t seq;
+ uint32_t empty1;
uint32_t handled; // actually a bool, but we must maintain 8-byte alignment
inline size_t size() const { return sizeof(Finished); }
} finished;
struct Focus {
- uint32_t seq;
int32_t eventId;
- uint32_t empty1;
// The following two fields take up 4 bytes total
uint16_t hasFocus; // actually a bool
uint16_t inTouchMode; // actually a bool, but we must maintain 8-byte alignment
@@ -172,6 +168,31 @@
bool isValid(size_t actualSize) const;
size_t size() const;
void getSanitizedCopy(InputMessage* msg) const;
+
+ static const char* typeToString(Type type) {
+ switch (type) {
+ case Type::KEY:
+ return "KEY";
+ case Type::MOTION:
+ return "MOTION";
+ case Type::FINISHED:
+ return "FINISHED";
+ case Type::FOCUS:
+ return "FOCUS";
+ }
+ }
+};
+
+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;
};
/*
@@ -183,10 +204,10 @@
* The input channel is closed when all references to it are released.
*/
class InputChannel : public RefBase {
-protected:
+public:
+ InputChannel();
virtual ~InputChannel();
-public:
static sp<InputChannel> create(const std::string& name, android::base::unique_fd fd,
sp<IBinder> token);
@@ -200,8 +221,10 @@
static status_t openInputChannelPair(const std::string& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel);
- inline std::string getName() const { return mName; }
- inline int getFd() const { return mFd.get(); }
+ 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; }
/* Send a message to the other endpoint.
*
@@ -231,8 +254,9 @@
/* Return a new object that has a duplicate of this channel's fd. */
sp<InputChannel> dup() const;
- status_t write(Parcel& out) const;
- static sp<InputChannel> read(const Parcel& from);
+ status_t readFromParcel(const android::Parcel* parcel);
+
+ status_t writeToParcel(android::Parcel* parcel) const;
/**
* The connection token is used to identify the input connection, i.e.
@@ -248,12 +272,23 @@
*/
sp<IBinder> getConnectionToken() const;
+ bool operator==(const InputChannel& inputChannel) const {
+ struct stat lhsInfo, rhsInfo;
+ if (fstat(mInfo.mFd.get(), &lhsInfo) != 0) {
+ return false;
+ }
+ if (fstat(inputChannel.getFd(), &rhsInfo) != 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;
+ }
+
private:
InputChannel(const std::string& name, android::base::unique_fd fd, sp<IBinder> token);
- std::string mName;
- android::base::unique_fd mFd;
-
- sp<IBinder> mToken;
+ InputChannelInfo mInfo;
};
/*
@@ -325,7 +360,6 @@
status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled);
private:
-
sp<InputChannel> mChannel;
};
@@ -411,6 +445,8 @@
*/
int32_t getPendingBatchSource() const;
+ std::string dump() const;
+
private:
// True if touch resampling is enabled.
const bool mResampleTouch;
@@ -427,9 +463,9 @@
// Batched motion events per device and source.
struct Batch {
- Vector<InputMessage> samples;
+ std::vector<InputMessage> samples;
};
- Vector<Batch> mBatches;
+ std::vector<Batch> mBatches;
// Touch state per device and source, only for sources of class pointer.
struct History {
@@ -516,7 +552,7 @@
return false;
}
};
- Vector<TouchState> mTouchStates;
+ std::vector<TouchState> mTouchStates;
// Chain of batched sequence numbers. When multiple input messages are combined into
// a batch, we append a record here that associates the last sequence number in the
@@ -526,7 +562,7 @@
uint32_t seq; // sequence number of batched input message
uint32_t chain; // sequence number of previous batched input message
};
- Vector<SeqChain> mSeqChains;
+ std::vector<SeqChain> mSeqChains;
status_t consumeBatch(InputEventFactoryInterface* factory,
nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h
index f8c759c..233c7ae 100644
--- a/include/input/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -17,112 +17,114 @@
#ifndef _UI_INPUT_WINDOW_H
#define _UI_INPUT_WINDOW_H
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <input/Flags.h>
#include <input/Input.h>
#include <input/InputTransport.h>
#include <ui/Rect.h>
#include <ui/Region.h>
+#include <ui/Transform.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
#include "InputApplication.h"
namespace android {
-class Parcel;
/*
* Describes the properties of a window that can receive input.
*/
-struct InputWindowInfo {
+struct InputWindowInfo : public Parcelable {
InputWindowInfo() = default;
- InputWindowInfo(const Parcel& from);
// Window flags from WindowManager.LayoutParams
- enum : uint32_t {
- FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
- FLAG_DIM_BEHIND = 0x00000002,
- FLAG_BLUR_BEHIND = 0x00000004,
- FLAG_NOT_FOCUSABLE = 0x00000008,
- FLAG_NOT_TOUCHABLE = 0x00000010,
- FLAG_NOT_TOUCH_MODAL = 0x00000020,
- FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
- FLAG_KEEP_SCREEN_ON = 0x00000080,
- FLAG_LAYOUT_IN_SCREEN = 0x00000100,
- FLAG_LAYOUT_NO_LIMITS = 0x00000200,
- FLAG_FULLSCREEN = 0x00000400,
- FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
- FLAG_DITHER = 0x00001000,
- FLAG_SECURE = 0x00002000,
- FLAG_SCALED = 0x00004000,
- FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
- FLAG_LAYOUT_INSET_DECOR = 0x00010000,
- FLAG_ALT_FOCUSABLE_IM = 0x00020000,
- FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
- FLAG_SHOW_WHEN_LOCKED = 0x00080000,
- FLAG_SHOW_WALLPAPER = 0x00100000,
- FLAG_TURN_SCREEN_ON = 0x00200000,
- FLAG_DISMISS_KEYGUARD = 0x00400000,
- FLAG_SPLIT_TOUCH = 0x00800000,
- FLAG_HARDWARE_ACCELERATED = 0x01000000,
- FLAG_LAYOUT_IN_OVERSCAN = 0x02000000,
- FLAG_TRANSLUCENT_STATUS = 0x04000000,
- FLAG_TRANSLUCENT_NAVIGATION = 0x08000000,
- FLAG_LOCAL_FOCUS_MODE = 0x10000000,
- FLAG_SLIPPERY = 0x20000000,
- FLAG_LAYOUT_ATTACHED_IN_DECOR = 0x40000000,
- FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = 0x80000000,
- };
+ enum class Flag : uint32_t {
+ ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
+ DIM_BEHIND = 0x00000002,
+ BLUR_BEHIND = 0x00000004,
+ NOT_FOCUSABLE = 0x00000008,
+ NOT_TOUCHABLE = 0x00000010,
+ NOT_TOUCH_MODAL = 0x00000020,
+ TOUCHABLE_WHEN_WAKING = 0x00000040,
+ KEEP_SCREEN_ON = 0x00000080,
+ LAYOUT_IN_SCREEN = 0x00000100,
+ LAYOUT_NO_LIMITS = 0x00000200,
+ FULLSCREEN = 0x00000400,
+ FORCE_NOT_FULLSCREEN = 0x00000800,
+ DITHER = 0x00001000,
+ SECURE = 0x00002000,
+ SCALED = 0x00004000,
+ IGNORE_CHEEK_PRESSES = 0x00008000,
+ LAYOUT_INSET_DECOR = 0x00010000,
+ ALT_FOCUSABLE_IM = 0x00020000,
+ WATCH_OUTSIDE_TOUCH = 0x00040000,
+ SHOW_WHEN_LOCKED = 0x00080000,
+ SHOW_WALLPAPER = 0x00100000,
+ TURN_SCREEN_ON = 0x00200000,
+ DISMISS_KEYGUARD = 0x00400000,
+ SPLIT_TOUCH = 0x00800000,
+ HARDWARE_ACCELERATED = 0x01000000,
+ LAYOUT_IN_OVERSCAN = 0x02000000,
+ TRANSLUCENT_STATUS = 0x04000000,
+ TRANSLUCENT_NAVIGATION = 0x08000000,
+ LOCAL_FOCUS_MODE = 0x10000000,
+ SLIPPERY = 0x20000000,
+ LAYOUT_ATTACHED_IN_DECOR = 0x40000000,
+ DRAWS_SYSTEM_BAR_BACKGROUNDS = 0x80000000,
+ }; // Window types from WindowManager.LayoutParams
- // Window types from WindowManager.LayoutParams
- enum {
+ enum class Type : int32_t {
+ UNKNOWN = 0,
FIRST_APPLICATION_WINDOW = 1,
- TYPE_BASE_APPLICATION = 1,
- TYPE_APPLICATION = 2,
- TYPE_APPLICATION_STARTING = 3,
+ BASE_APPLICATION = 1,
+ APPLICATION = 2,
+ APPLICATION_STARTING = 3,
LAST_APPLICATION_WINDOW = 99,
FIRST_SUB_WINDOW = 1000,
- TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
- TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1,
- TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2,
- TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3,
- TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4,
+ APPLICATION_PANEL = FIRST_SUB_WINDOW,
+ APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1,
+ APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2,
+ APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3,
+ APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4,
LAST_SUB_WINDOW = 1999,
FIRST_SYSTEM_WINDOW = 2000,
- TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
- TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW + 1,
- TYPE_PHONE = FIRST_SYSTEM_WINDOW + 2,
- TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW + 3,
- TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW + 4,
- TYPE_TOAST = FIRST_SYSTEM_WINDOW + 5,
- TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 6,
- TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW + 7,
- TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW + 8,
- TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW + 9,
- TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW + 10,
- TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW + 11,
- TYPE_INPUT_METHOD_DIALOG = FIRST_SYSTEM_WINDOW + 12,
- TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW + 13,
- TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW + 14,
- TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 15,
- TYPE_DRAG = FIRST_SYSTEM_WINDOW + 16,
- TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW + 17,
- TYPE_POINTER = FIRST_SYSTEM_WINDOW + 18,
- TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 19,
- TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW + 20,
- TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW + 21,
- TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW + 22,
- TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW + 24,
- TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 27,
- TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32,
- TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34,
- TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39,
- TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40,
+ STATUS_BAR = FIRST_SYSTEM_WINDOW,
+ SEARCH_BAR = FIRST_SYSTEM_WINDOW + 1,
+ PHONE = FIRST_SYSTEM_WINDOW + 2,
+ SYSTEM_ALERT = FIRST_SYSTEM_WINDOW + 3,
+ KEYGUARD = FIRST_SYSTEM_WINDOW + 4,
+ TOAST = FIRST_SYSTEM_WINDOW + 5,
+ SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 6,
+ PRIORITY_PHONE = FIRST_SYSTEM_WINDOW + 7,
+ SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW + 8,
+ KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW + 9,
+ SYSTEM_ERROR = FIRST_SYSTEM_WINDOW + 10,
+ INPUT_METHOD = FIRST_SYSTEM_WINDOW + 11,
+ INPUT_METHOD_DIALOG = FIRST_SYSTEM_WINDOW + 12,
+ WALLPAPER = FIRST_SYSTEM_WINDOW + 13,
+ STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW + 14,
+ SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 15,
+ DRAG = FIRST_SYSTEM_WINDOW + 16,
+ STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW + 17,
+ POINTER = FIRST_SYSTEM_WINDOW + 18,
+ NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 19,
+ VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW + 20,
+ BOOT_PROGRESS = FIRST_SYSTEM_WINDOW + 21,
+ INPUT_CONSUMER = FIRST_SYSTEM_WINDOW + 22,
+ NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW + 24,
+ MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 27,
+ ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32,
+ DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34,
+ ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39,
+ NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40,
LAST_SYSTEM_WINDOW = 2999,
};
- enum {
- INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001,
- INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002,
- INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004,
+ enum class Feature {
+ DISABLE_TOUCH_PAD_GESTURES = 0x00000001,
+ NO_INPUT_CHANNEL = 0x00000002,
+ DISABLE_USER_ACTIVITY = 0x00000004,
};
/* These values are filled in by the WM and passed through SurfaceFlinger
@@ -134,8 +136,8 @@
// This uniquely identifies the input window.
int32_t id = -1;
std::string name;
- int32_t layoutParamsFlags = 0;
- int32_t layoutParamsType = 0;
+ Flags<Flag> flags;
+ Type type = Type::UNKNOWN;
std::chrono::nanoseconds dispatchingTimeout = std::chrono::seconds(5);
/* These values are filled in by SurfaceFlinger. */
@@ -160,6 +162,9 @@
float windowXScale = 1.0f;
float windowYScale = 1.0f;
+ // Transform applied to individual windows.
+ ui::Transform transform;
+
/*
* This is filled in by the WM relative to the frame and then translated
* to absolute coordinates by SurfaceFlinger once the frame is computed.
@@ -178,7 +183,7 @@
bool trustedOverlay = false;
int32_t ownerPid = -1;
int32_t ownerUid = -1;
- int32_t inputFeatures = 0;
+ Flags<Feature> inputFeatures;
int32_t displayId = ADISPLAY_ID_NONE;
int32_t portalToDisplayId = ADISPLAY_ID_NONE;
InputApplicationInfo applicationInfo;
@@ -195,13 +200,15 @@
bool overlaps(const InputWindowInfo* other) const;
- status_t write(Parcel& output) const;
+ bool operator==(const InputWindowInfo& inputChannel) const;
- static InputWindowInfo read(const Parcel& from);
+ status_t writeToParcel(android::Parcel* parcel) const override;
+
+ status_t readFromParcel(const android::Parcel* parcel) override;
+
+ static std::optional<std::string> flagToString(Flag f);
};
-std::string inputWindowFlagsToString(uint32_t flags);
-
/*
* Handle for a window that can receive input.
*
@@ -210,22 +217,19 @@
*/
class InputWindowHandle : public RefBase {
public:
+ explicit InputWindowHandle();
+ InputWindowHandle(const InputWindowHandle& other);
+ InputWindowHandle(const InputWindowInfo& other);
- inline const InputWindowInfo* getInfo() const {
- return &mInfo;
- }
+ inline const InputWindowInfo* getInfo() const { return &mInfo; }
sp<IBinder> getToken() const;
int32_t getId() const { return mInfo.id; }
- sp<IBinder> getApplicationToken() {
- return mInfo.applicationInfo.token;
- }
+ sp<IBinder> getApplicationToken() { return mInfo.applicationInfo.token; }
- inline std::string getName() const {
- return !mInfo.name.empty() ? mInfo.name : "<invalid>";
- }
+ inline std::string getName() const { return !mInfo.name.empty() ? mInfo.name : "<invalid>"; }
inline std::chrono::nanoseconds getDispatchingTimeout(
std::chrono::nanoseconds defaultValue) const {
@@ -235,13 +239,14 @@
/**
* Requests that the state of this object be updated to reflect
* the most current available information about the application.
+ * As this class is created as RefBase object, no pure virtual function is allowed.
*
* This method should only be called from within the input dispatcher's
* critical section.
*
* Returns true on success, or false if the handle is no longer valid.
*/
- virtual bool updateInfo() = 0;
+ virtual bool updateInfo() { return false; }
/**
* Updates from another input window handle.
@@ -254,13 +259,15 @@
*/
void releaseChannel();
+ // Not override since this class is not derrived from Parcelable.
+ status_t readFromParcel(const android::Parcel* parcel);
+ status_t writeToParcel(android::Parcel* parcel) const;
+
protected:
- explicit InputWindowHandle();
virtual ~InputWindowHandle();
InputWindowInfo mInfo;
};
-
} // namespace android
#endif // _UI_INPUT_WINDOW_H
diff --git a/include/ui/Rotation.h b/include/ui/Rotation.h
new file mode 120000
index 0000000..095d2ce
--- /dev/null
+++ b/include/ui/Rotation.h
@@ -0,0 +1 @@
+../../libs/ui/include/ui/Rotation.h
\ No newline at end of file
diff --git a/include/ui/Transform.h b/include/ui/Transform.h
new file mode 120000
index 0000000..323f1fd
--- /dev/null
+++ b/include/ui/Transform.h
@@ -0,0 +1 @@
+../../libs/ui/include/ui/Transform.h
\ No newline at end of file
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 05f43e3..25c0b19 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -326,6 +326,11 @@
while(true) {
{
+ // It would be really nice if we could read binder commands on this
+ // thread instead of needing a threadpool to be started, but for
+ // instance, if we call getAndExecuteCommand, it might be the case
+ // that another thread serves the callback, and we never get a
+ // command, so we hang indefinitely.
std::unique_lock<std::mutex> lock(waiter->mMutex);
using std::literals::chrono_literals::operator""s;
waiter->mCv.wait_for(lock, 1s, [&] {
@@ -334,6 +339,8 @@
if (waiter->mBinder != nullptr) return waiter->mBinder;
}
+ ALOGW("Waited one second for %s (is service started? are binder threads started and available?)", name.c_str());
+
// Handle race condition for lazy services. Here is what can happen:
// - the service dies (not processed by init yet).
// - sm processes death notification.
@@ -347,8 +354,6 @@
return nullptr;
}
if (out != nullptr) return out;
-
- ALOGW("Waited one second for %s", name.c_str());
}
}
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 7116154..33ee680 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -247,8 +247,6 @@
"android.hardware.ISoundTriggerHwService",
"android.hardware.IStreamListener",
"android.hardware.IStreamSource",
- "android.input.IInputFlinger",
- "android.input.ISetInputWindowsListener",
"android.media.IAudioFlinger",
"android.media.IAudioFlingerClient",
"android.media.IAudioPolicyService",
@@ -282,7 +280,6 @@
"android.os.IComplexTypeInterface",
"android.os.IPermissionController",
"android.os.IPingResponder",
- "android.os.IPowerManager",
"android.os.IProcessInfoService",
"android.os.ISchedulingPolicyService",
"android.os.IStringConstants",
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index b4e4a42..8d51cdc 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -50,7 +50,7 @@
* Returns the SELinux security identifier of the process which has
* made the current binder call. If not in a binder call this will
* return nullptr. If this isn't requested with
- * IBinder::setRequestingSid, it will also return nullptr.
+ * Binder::setRequestingSid, it will also return nullptr.
*
* This can't be restored once it's cleared, and it does not return the
* context of the current process when not in a binder call.
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index f66406f..c7e1e14 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -50,12 +50,18 @@
// ---------------------------------------------------------------------------
+// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
+// be allocated.
// Text output stream for printing to the log (via utils/Log.h).
extern TextOutput& alog;
+// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
+// be allocated.
// Text output stream for printing to stdout.
extern TextOutput& aout;
+// DO NOT USE: prefer libutils/libbase logs, which don't require static data to
+// be allocated.
// Text output stream for printing to stderr.
extern TextOutput& aerr;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 743ef89..d287290 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -15,6 +15,7 @@
*/
#include <android/binder_ibinder.h>
+#include <android/binder_ibinder_platform.h>
#include "ibinder_internal.h"
#include <android/binder_stability.h>
@@ -682,3 +683,29 @@
rawBinder->setExtension(ext->getBinder());
return STATUS_OK;
}
+
+// platform methods follow
+
+void AIBinder_setRequestingSid(AIBinder* binder, bool requestingSid) {
+ ABBinder* localBinder = binder->asABBinder();
+ if (localBinder == nullptr) {
+ LOG(FATAL) << "AIBinder_setRequestingSid must be called on a local binder";
+ }
+
+ localBinder->setRequestingSid(requestingSid);
+}
+
+const char* AIBinder_getCallingSid() {
+ return ::android::IPCThreadState::self()->getCallingSid();
+}
+
+android::sp<android::IBinder> AIBinder_toPlatformBinder(AIBinder* binder) {
+ if (binder == nullptr) return nullptr;
+ return binder->getBinder();
+}
+
+AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder) {
+ sp<AIBinder> ndkBinder = ABpBinder::lookupOrCreateFromBinder(binder);
+ AIBinder_incStrong(ndkBinder.get());
+ return ndkBinder.get();
+}
diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
new file mode 100644
index 0000000..d4feaba
--- /dev/null
+++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+
+#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
+#include <binder/IBinder.h>
+#endif
+
+__BEGIN_DECLS
+
+/**
+ * Makes calls to AIBinder_getCallingSid work if the kernel supports it. This
+ * must be called on a local binder server before it is sent out to any othe
+ * process. If this is a remote binder, it will abort. If the kernel doesn't
+ * support this feature, you'll always get null from AIBinder_getCallingSid.
+ *
+ * \param binder local server binder to request security contexts on
+ */
+void AIBinder_setRequestingSid(AIBinder* binder, bool requestingSid) __INTRODUCED_IN(31);
+
+/**
+ * Returns the selinux context of the callee.
+ *
+ * In order for this to work, the following conditions must be met:
+ * - The kernel must be new enough to support this feature.
+ * - The server must have called AIBinder_setRequestingSid.
+ * - The callee must be a remote process.
+ *
+ * \return security context or null if unavailable. The lifetime of this context
+ * is the lifetime of the transaction.
+ */
+__attribute__((warn_unused_result)) const char* AIBinder_getCallingSid() __INTRODUCED_IN(31);
+
+__END_DECLS
+
+#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
+
+/**
+ * Get libbinder version of binder from AIBinder.
+ *
+ * WARNING: function calls to a local object on the other side of this function
+ * will parcel. When converting between binders, keep in mind it is not as
+ * efficient as a direct function call.
+ *
+ * \param binder binder with ownership retained by the client
+ * \return platform binder object
+ */
+android::sp<android::IBinder> AIBinder_toPlatformBinder(AIBinder* binder);
+
+/**
+ * Get libbinder_ndk version of binder from platform binder.
+ *
+ * WARNING: function calls to a local object on the other side of this function
+ * will parcel. When converting between binders, keep in mind it is not as
+ * efficient as a direct function call.
+ *
+ * \param binder platform binder which may be from anywhere (doesn't have to be
+ * created with libbinder_ndK)
+ * \return binder with one reference count of ownership given to the client. See
+ * AIBinder_decStrong
+ */
+AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder);
+
+#endif
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index a9eba47..9b5fa26 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -95,8 +95,6 @@
AServiceManager_addService; # apex llndk
AServiceManager_checkService; # apex llndk
AServiceManager_getService; # apex llndk
- local:
- *;
};
LIBBINDER_NDK30 { # introduced=30
@@ -111,11 +109,21 @@
AIBinder_markVendorStability; # llndk
AIBinder_markVintfStability; # apex llndk
AIBinder_Class_setHandleShellCommand; # apex llndk
- local:
- *;
+};
+
+LIBBINDER_NDK31 { # introduced=31
+ global:
+ AIBinder_getCallingSid; # apex
+ AIBinder_setRequestingSid; # apex
};
LIBBINDER_NDK_PLATFORM {
global:
AParcel_getAllowFds;
+ extern "C++" {
+ AIBinder_fromPlatformBinder*;
+ AIBinder_toPlatformBinder*;
+ };
+ local:
+ *;
};
diff --git a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
index 6e8e463..dc77467d 100644
--- a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
+++ b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
@@ -22,6 +22,10 @@
import IEmpty;
interface IBinderNdkUnitTest {
+ int repeatInt(int a);
+
void takeInterface(IEmpty test);
void forceFlushCommands();
+
+ boolean getsRequestedSid();
}
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index fd30d87..e3fdb4b 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -19,6 +19,7 @@
#include <aidl/BnEmpty.h>
#include <android-base/logging.h>
#include <android/binder_ibinder_jni.h>
+#include <android/binder_ibinder_platform.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <gtest/gtest.h>
@@ -34,6 +35,7 @@
#include <sys/prctl.h>
#include <chrono>
#include <condition_variable>
+#include <iostream>
#include <mutex>
using namespace android;
@@ -42,6 +44,10 @@
constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
+ ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
+ *out = in;
+ return ndk::ScopedAStatus::ok();
+ }
ndk::ScopedAStatus takeInterface(const std::shared_ptr<aidl::IEmpty>& empty) {
(void)empty;
return ndk::ScopedAStatus::ok();
@@ -52,6 +58,12 @@
android::IPCThreadState::self()->flushCommands();
return ndk::ScopedAStatus::ok();
}
+ ndk::ScopedAStatus getsRequestedSid(bool* out) {
+ const char* sid = AIBinder_getCallingSid();
+ std::cout << "Got security context: " << (sid ?: "null") << std::endl;
+ *out = sid != nullptr;
+ return ndk::ScopedAStatus::ok();
+ }
binder_status_t handleShellCommand(int /*in*/, int out, int /*err*/, const char** args,
uint32_t numArgs) override {
for (uint32_t i = 0; i < numArgs; i++) {
@@ -66,8 +78,11 @@
ABinderProcess_setThreadPoolMaxThreadCount(0);
auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
- binder_status_t status =
- AServiceManager_addService(service->asBinder().get(), kBinderNdkUnitTestService);
+ auto binder = service->asBinder();
+
+ AIBinder_setRequestingSid(binder.get(), true);
+
+ binder_status_t status = AServiceManager_addService(binder.get(), kBinderNdkUnitTestService);
if (status != STATUS_OK) {
LOG(FATAL) << "Could not register: " << status << " " << kBinderNdkUnitTestService;
@@ -274,6 +289,16 @@
EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
}
+TEST(NdkBinder, RequestedSidWorks) {
+ ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService));
+ std::shared_ptr<aidl::IBinderNdkUnitTest> service =
+ aidl::IBinderNdkUnitTest::fromBinder(binder);
+
+ bool gotSid = false;
+ EXPECT_TRUE(service->getsRequestedSid(&gotSid).isOk());
+ EXPECT_TRUE(gotSid);
+}
+
TEST(NdkBinder, SentAidlBinderCanBeDestroyed) {
static volatile bool destroyed = false;
static std::mutex dMutex;
@@ -308,6 +333,30 @@
EXPECT_TRUE(destroyed);
}
+TEST(NdkBinder, ConvertToPlatformBinder) {
+ for (const ndk::SpAIBinder& binder :
+ {// remote
+ ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)),
+ // local
+ ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) {
+ // convert to platform binder
+ EXPECT_NE(binder.get(), nullptr);
+ sp<IBinder> platformBinder = AIBinder_toPlatformBinder(binder.get());
+ EXPECT_NE(platformBinder.get(), nullptr);
+ auto proxy = interface_cast<IBinderNdkUnitTest>(platformBinder);
+ EXPECT_NE(proxy, nullptr);
+
+ // use platform binder
+ int out;
+ EXPECT_TRUE(proxy->repeatInt(4, &out).isOk());
+ EXPECT_EQ(out, 4);
+
+ // convert back
+ ndk::SpAIBinder backBinder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(platformBinder));
+ EXPECT_EQ(backBinder.get(), binder.get());
+ }
+}
+
class MyResultReceiver : public BnResultReceiver {
public:
Mutex mMutex;
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
index 68cc225..44e2fd1 100644
--- a/libs/binderthreadstate/test.cpp
+++ b/libs/binderthreadstate/test.cpp
@@ -165,7 +165,6 @@
android::ProcessState::self()->startThreadPool();
// HIDL
- setenv("TREBLE_TESTING_OVERRIDE", "true", true);
android::hardware::configureRpcThreadpool(1, true /*callerWillJoin*/);
sp<IHidlStuff> hidlServer = new HidlServer(thisId, otherId);
CHECK(OK == hidlServer->registerAsService(id2name(thisId).c_str()));
@@ -176,7 +175,7 @@
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
- setenv("TREBLE_TESTING_OVERRIDE", "true", true);
+ android::hardware::details::setTrebleTestingOverride(true);
if (fork() == 0) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
return server(kP1Id, kP2Id);
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index e43446a..1030b82 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -55,7 +55,7 @@
output.writeFloat(color.g);
output.writeFloat(color.b);
#ifndef NO_INPUT
- inputInfo.write(output);
+ inputHandle->writeToParcel(&output);
#endif
output.write(transparentRegion);
output.writeUint32(transform);
@@ -152,7 +152,7 @@
color.b = input.readFloat();
#ifndef NO_INPUT
- inputInfo = InputWindowInfo::read(input);
+ inputHandle->readFromParcel(&input);
#endif
input.read(transparentRegion);
@@ -404,7 +404,7 @@
#ifndef NO_INPUT
if (other.what & eInputInfoChanged) {
what |= eInputInfoChanged;
- inputInfo = other.inputInfo;
+ inputHandle = new InputWindowHandle(*other.inputHandle);
}
#endif
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 16b46df..d797a35 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1359,7 +1359,7 @@
mStatus = BAD_INDEX;
return *this;
}
- s->inputInfo = info;
+ s->inputHandle = new InputWindowHandle(info);
s->what |= layer_state_t::eInputInfoChanged;
return *this;
}
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index e60f677..00ae220 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -201,7 +201,7 @@
mat4 colorTransform;
#ifndef NO_INPUT
- InputWindowInfo inputInfo;
+ sp<InputWindowHandle> inputHandle = new InputWindowHandle();
#endif
client_cache_t cachedBuffer;
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 32c7fc2..383d591 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -36,15 +36,16 @@
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
-#include <input/InputWindow.h>
-#include <input/IInputFlinger.h>
-#include <input/InputTransport.h>
+#include <android/os/IInputFlinger.h>
#include <input/Input.h>
+#include <input/InputTransport.h>
+#include <input/InputWindow.h>
#include <ui/DisplayConfig.h>
#include <ui/Rect.h>
#include <ui/Region.h>
+using android::os::IInputFlinger;
namespace android {
namespace test {
@@ -71,7 +72,7 @@
InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
mInputFlinger = getInputFlinger();
- mInputFlinger->registerInputChannel(mServerChannel);
+ mInputFlinger->registerInputChannel(mServerChannel->getInfo());
populateInputInfo(width, height);
@@ -153,9 +154,7 @@
EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS);
}
- ~InputSurface() {
- mInputFlinger->unregisterInputChannel(mServerChannel);
- }
+ ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel->getInfo()); }
void doTransaction(std::function<void(SurfaceComposerClient::Transaction&,
const sp<SurfaceControl>&)> transactionBody) {
@@ -187,8 +186,8 @@
void populateInputInfo(int width, int height) {
mInputInfo.token = mServerChannel->getConnectionToken();
mInputInfo.name = "Test info";
- mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
- mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION;
+ mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL;
+ mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION;
mInputInfo.dispatchingTimeout = 5s;
mInputInfo.globalScaleFactor = 1.0;
mInputInfo.canReceiveKeys = true;
@@ -201,7 +200,6 @@
// TODO: Fill in from SF?
mInputInfo.ownerPid = 11111;
mInputInfo.ownerUid = 11111;
- mInputInfo.inputFeatures = 0;
mInputInfo.displayId = 0;
InputApplicationInfo aInfo;
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 7037680..8a9f261 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -43,17 +43,25 @@
"libcutils",
],
+ static_libs: [
+ "libui-types",
+ ],
+
+ export_static_lib_headers: [
+ "libui-types",
+ ],
+
target: {
android: {
srcs: [
- "IInputFlinger.cpp",
"InputApplication.cpp",
"InputTransport.cpp",
"InputWindow.cpp",
- "ISetInputWindowsListener.cpp",
"LatencyStatistics.cpp",
"VelocityControl.cpp",
"VelocityTracker.cpp",
+ "android/os/IInputFlinger.aidl",
+ "android/os/ISetInputWindowsListener.aidl",
],
shared_libs: [
@@ -72,6 +80,11 @@
},
},
},
+
+ aidl: {
+ local_include_dirs: ["."],
+ export_aidl_headers: true
+ },
}
subdirs = ["tests"]
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
deleted file mode 100644
index 8ec5165..0000000
--- a/libs/input/IInputFlinger.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <input/IInputFlinger.h>
-
-namespace android {
-
-class BpInputFlinger : public BpInterface<IInputFlinger> {
-public:
- explicit BpInputFlinger(const sp<IBinder>& impl) :
- BpInterface<IInputFlinger>(impl) { }
-
- virtual void setInputWindows(const std::vector<InputWindowInfo>& inputInfo,
- const sp<ISetInputWindowsListener>& setInputWindowsListener) {
- Parcel data, reply;
- data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
-
- data.writeUint32(static_cast<uint32_t>(inputInfo.size()));
- for (const auto& info : inputInfo) {
- info.write(data);
- }
- data.writeStrongBinder(IInterface::asBinder(setInputWindowsListener));
-
- remote()->transact(BnInputFlinger::SET_INPUT_WINDOWS_TRANSACTION, data, &reply,
- IBinder::FLAG_ONEWAY);
- }
-
- virtual void registerInputChannel(const sp<InputChannel>& channel) {
- Parcel data, reply;
- data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
- channel->write(data);
- remote()->transact(BnInputFlinger::REGISTER_INPUT_CHANNEL_TRANSACTION, data, &reply);
- }
-
- virtual void unregisterInputChannel(const sp<InputChannel>& channel) {
- Parcel data, reply;
- data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
- channel->write(data);
- remote()->transact(BnInputFlinger::UNREGISTER_INPUT_CHANNEL_TRANSACTION, data, &reply);
- }
-};
-
-IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger");
-
-status_t BnInputFlinger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- switch(code) {
- case SET_INPUT_WINDOWS_TRANSACTION: {
- CHECK_INTERFACE(IInputFlinger, data, reply);
- size_t count = data.readUint32();
- if (count > data.dataSize()) {
- return BAD_VALUE;
- }
- std::vector<InputWindowInfo> handles;
- for (size_t i = 0; i < count; i++) {
- handles.push_back(InputWindowInfo::read(data));
- }
- const sp<ISetInputWindowsListener> setInputWindowsListener =
- ISetInputWindowsListener::asInterface(data.readStrongBinder());
- setInputWindows(handles, setInputWindowsListener);
- break;
- }
- case REGISTER_INPUT_CHANNEL_TRANSACTION: {
- CHECK_INTERFACE(IInputFlinger, data, reply);
- sp<InputChannel> channel = InputChannel::read(data);
- registerInputChannel(channel);
- break;
- }
- case UNREGISTER_INPUT_CHANNEL_TRANSACTION: {
- CHECK_INTERFACE(IInputFlinger, data, reply);
- sp<InputChannel> channel = InputChannel::read(data);
- unregisterInputChannel(channel);
- break;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
- return NO_ERROR;
-}
-
-};
diff --git a/libs/input/ISetInputWindowsListener.cpp b/libs/input/ISetInputWindowsListener.cpp
deleted file mode 100644
index a0330da..0000000
--- a/libs/input/ISetInputWindowsListener.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 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 <input/ISetInputWindowsListener.h>
-
-namespace android {
-
-class BpSetInputWindowsListener : public BpInterface<ISetInputWindowsListener> {
-public:
- explicit BpSetInputWindowsListener(const sp<IBinder>& impl)
- : BpInterface<ISetInputWindowsListener>(impl) {
- }
-
- virtual ~BpSetInputWindowsListener() = default;
-
- virtual void onSetInputWindowsFinished() {
- Parcel data, reply;
- data.writeInterfaceToken(ISetInputWindowsListener::getInterfaceDescriptor());
- remote()->transact(BnSetInputWindowsListener::ON_SET_INPUT_WINDOWS_FINISHED, data, &reply,
- IBinder::FLAG_ONEWAY);
- }
-};
-
-IMPLEMENT_META_INTERFACE(SetInputWindowsListener, "android.input.ISetInputWindowsListener");
-
-status_t BnSetInputWindowsListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags) {
- switch(code) {
- case ON_SET_INPUT_WINDOWS_FINISHED: {
- CHECK_INTERFACE(ISetInputWindowsListener, data, reply);
- onSetInputWindowsFinished();
- return NO_ERROR;
- }
- default: {
- return BBinder::onTransact(code, data, reply, flags);
- }
- }
-}
-
-} // namespace android
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 31aa685..2ac079e 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -301,6 +301,11 @@
}
}
+void PointerCoords::transform(const ui::Transform& transform) {
+ vec2 newCoords = transform.transform(getX(), getY());
+ setAxisValue(AMOTION_EVENT_AXIS_X, newCoords.x);
+ setAxisValue(AMOTION_EVENT_AXIS_Y, newCoords.y);
+}
// --- PointerProperties ---
diff --git a/libs/input/InputApplication.cpp b/libs/input/InputApplication.cpp
index c745c24..41721a7 100644
--- a/libs/input/InputApplication.cpp
+++ b/libs/input/InputApplication.cpp
@@ -22,29 +22,34 @@
namespace android {
+status_t InputApplicationInfo::readFromParcel(const android::Parcel* parcel) {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __func__);
+ return BAD_VALUE;
+ }
+ token = parcel->readStrongBinder();
+ dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64());
+ status_t status = parcel->readUtf8FromUtf16(&name);
+
+ return status;
+}
+
+status_t InputApplicationInfo::writeToParcel(android::Parcel* parcel) const {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __func__);
+ return BAD_VALUE;
+ }
+ status_t status = parcel->writeStrongBinder(token)
+ ?: parcel->writeInt64(dispatchingTimeout.count())
+ ?: parcel->writeUtf8AsUtf16(name) ;
+
+ return status;
+}
+
// --- InputApplicationHandle ---
-InputApplicationHandle::InputApplicationHandle() {
-}
+InputApplicationHandle::InputApplicationHandle() {}
-InputApplicationHandle::~InputApplicationHandle() {
-}
-
-InputApplicationInfo InputApplicationInfo::read(const Parcel& from) {
- InputApplicationInfo ret;
- ret.token = from.readStrongBinder();
- ret.name = from.readString8().c_str();
- ret.dispatchingTimeout = decltype(ret.dispatchingTimeout)(from.readInt64());
-
- return ret;
-}
-
-status_t InputApplicationInfo::write(Parcel& output) const {
- output.writeStrongBinder(token);
- output.writeString8(String8(name.c_str()));
- output.writeInt64(dispatchingTimeout.count());
-
- return OK;
-}
+InputApplicationHandle::~InputApplicationHandle() {}
} // namespace android
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 4db9e06..dbd6293 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -46,9 +46,9 @@
static void appendInputDeviceConfigurationFileRelativePath(std::string& path,
const std::string& name, InputDeviceConfigurationFileType type) {
- path += CONFIGURATION_FILE_DIR[type];
+ path += CONFIGURATION_FILE_DIR[static_cast<int32_t>(type)];
path += name;
- path += CONFIGURATION_FILE_EXTENSION[type];
+ path += CONFIGURATION_FILE_EXTENSION[static_cast<int32_t>(type)];
}
std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 11af23e..60ad578 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -133,12 +133,11 @@
// Write the header
msg->header.type = header.type;
+ msg->header.seq = header.seq;
// Write the body
switch(header.type) {
case InputMessage::Type::KEY: {
- // uint32_t seq
- msg->body.key.seq = body.key.seq;
// int32_t eventId
msg->body.key.eventId = body.key.eventId;
// nsecs_t eventTime
@@ -168,8 +167,6 @@
break;
}
case InputMessage::Type::MOTION: {
- // uint32_t seq
- msg->body.motion.seq = body.motion.seq;
// int32_t eventId
msg->body.motion.eventId = body.motion.eventId;
// nsecs_t eventTime
@@ -232,12 +229,10 @@
break;
}
case InputMessage::Type::FINISHED: {
- msg->body.finished.seq = body.finished.seq;
msg->body.finished.handled = body.finished.handled;
break;
}
case InputMessage::Type::FOCUS: {
- msg->body.focus.seq = body.focus.seq;
msg->body.focus.eventId = body.focus.eventId;
msg->body.focus.hasFocus = body.focus.hasFocus;
msg->body.focus.inTouchMode = body.focus.inTouchMode;
@@ -246,6 +241,28 @@
}
}
+// --- 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,
@@ -260,15 +277,17 @@
}
InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd, sp<IBinder> token)
- : mName(name), mFd(std::move(fd)), mToken(token) {
+ : mInfo(name, std::move(fd), token) {
if (DEBUG_CHANNEL_LIFECYCLE) {
- ALOGD("Input channel constructed: name='%s', fd=%d", mName.c_str(), mFd.get());
+ ALOGD("Input channel constructed: name='%s', fd=%d", mInfo.mName.c_str(), mInfo.mFd.get());
}
}
+InputChannel::InputChannel() {}
+
InputChannel::~InputChannel() {
if (DEBUG_CHANNEL_LIFECYCLE) {
- ALOGD("Input channel destroyed: name='%s', fd=%d", mName.c_str(), mFd.get());
+ ALOGD("Input channel destroyed: name='%s', fd=%d", getName().c_str(), getFd());
}
}
@@ -308,7 +327,7 @@
msg->getSanitizedCopy(&cleanMsg);
ssize_t nWrite;
do {
- nWrite = ::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
+ nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
if (nWrite < 0) {
@@ -343,7 +362,7 @@
status_t InputChannel::receiveMessage(InputMessage* msg) {
ssize_t nRead;
do {
- nRead = ::recv(mFd.get(), msg, sizeof(InputMessage), MSG_DONTWAIT);
+ nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT);
} while (nRead == -1 && errno == EINTR);
if (nRead < 0) {
@@ -383,7 +402,7 @@
sp<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(), mName.c_str(),
+ ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), 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
@@ -394,38 +413,19 @@
getName().c_str());
return nullptr;
}
- return InputChannel::create(mName, std::move(newFd), mToken);
+ return InputChannel::create(getName(), std::move(newFd), getConnectionToken());
}
-status_t InputChannel::write(Parcel& out) const {
- status_t s = out.writeCString(getName().c_str());
- if (s != OK) {
- return s;
- }
-
- s = out.writeStrongBinder(mToken);
- if (s != OK) {
- return s;
- }
-
- s = out.writeUniqueFileDescriptor(mFd);
- return s;
+status_t InputChannel::writeToParcel(android::Parcel* parcel) const {
+ return mInfo.writeToParcel(parcel);
}
-sp<InputChannel> InputChannel::read(const Parcel& from) {
- std::string name = from.readCString();
- sp<IBinder> token = from.readStrongBinder();
- android::base::unique_fd rawFd;
- status_t fdResult = from.readUniqueFileDescriptor(&rawFd);
- if (fdResult != OK) {
- return nullptr;
- }
-
- return InputChannel::create(name, std::move(rawFd), token);
+status_t InputChannel::readFromParcel(const android::Parcel* parcel) {
+ return mInfo.readFromParcel(parcel);
}
sp<IBinder> InputChannel::getConnectionToken() const {
- return mToken;
+ return mInfo.mToken;
}
// --- InputPublisher ---
@@ -463,7 +463,7 @@
InputMessage msg;
msg.header.type = InputMessage::Type::KEY;
- msg.body.key.seq = seq;
+ msg.header.seq = seq;
msg.body.key.eventId = eventId;
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
@@ -521,7 +521,7 @@
InputMessage msg;
msg.header.type = InputMessage::Type::MOTION;
- msg.body.motion.seq = seq;
+ msg.header.seq = seq;
msg.body.motion.eventId = eventId;
msg.body.motion.deviceId = deviceId;
msg.body.motion.source = source;
@@ -565,7 +565,7 @@
InputMessage msg;
msg.header.type = InputMessage::Type::FOCUS;
- msg.body.focus.seq = seq;
+ msg.header.seq = seq;
msg.body.focus.eventId = eventId;
msg.body.focus.hasFocus = hasFocus ? 1 : 0;
msg.body.focus.inTouchMode = inTouchMode ? 1 : 0;
@@ -589,7 +589,7 @@
mChannel->getName().c_str(), msg.header.type);
return UNKNOWN_ERROR;
}
- *outSeq = msg.body.finished.seq;
+ *outSeq = msg.header.seq;
*outHandled = msg.body.finished.handled == 1;
return OK;
}
@@ -650,7 +650,7 @@
if (!keyEvent) return NO_MEMORY;
initializeKeyEvent(keyEvent, &mMsg);
- *outSeq = mMsg.body.key.seq;
+ *outSeq = mMsg.header.seq;
*outEvent = keyEvent;
if (DEBUG_TRANSPORT_ACTIONS) {
ALOGD("channel '%s' consumer ~ consumed key event, seq=%u",
@@ -662,9 +662,9 @@
case InputMessage::Type::MOTION: {
ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source);
if (batchIndex >= 0) {
- Batch& batch = mBatches.editItemAt(batchIndex);
+ Batch& batch = mBatches[batchIndex];
if (canAddSample(batch, &mMsg)) {
- batch.samples.push(mMsg);
+ batch.samples.push_back(mMsg);
if (DEBUG_TRANSPORT_ACTIONS) {
ALOGD("channel '%s' consumer ~ appended to batch event",
mChannel->getName().c_str());
@@ -675,18 +675,18 @@
// No need to process events that we are going to cancel anyways
const size_t count = batch.samples.size();
for (size_t i = 0; i < count; i++) {
- const InputMessage& msg = batch.samples.itemAt(i);
- sendFinishedSignal(msg.body.motion.seq, false);
+ const InputMessage& msg = batch.samples[i];
+ sendFinishedSignal(msg.header.seq, false);
}
- batch.samples.removeItemsAt(0, count);
- mBatches.removeAt(batchIndex);
+ batch.samples.erase(batch.samples.begin(), batch.samples.begin() + count);
+ mBatches.erase(mBatches.begin() + batchIndex);
} else {
// We cannot append to the batch in progress, so we need to consume
// the previous batch right now and defer the new message until later.
mMsgDeferred = true;
status_t result = consumeSamples(factory, batch, batch.samples.size(),
outSeq, outEvent);
- mBatches.removeAt(batchIndex);
+ mBatches.erase(mBatches.begin() + batchIndex);
if (result) {
return result;
}
@@ -702,9 +702,9 @@
// Start a new batch if needed.
if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE ||
mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
- mBatches.push();
- Batch& batch = mBatches.editTop();
- batch.samples.push(mMsg);
+ Batch batch;
+ batch.samples.push_back(mMsg);
+ mBatches.push_back(batch);
if (DEBUG_TRANSPORT_ACTIONS) {
ALOGD("channel '%s' consumer ~ started batch event",
mChannel->getName().c_str());
@@ -717,7 +717,7 @@
updateTouchState(mMsg);
initializeMotionEvent(motionEvent, &mMsg);
- *outSeq = mMsg.body.motion.seq;
+ *outSeq = mMsg.header.seq;
*outEvent = motionEvent;
if (DEBUG_TRANSPORT_ACTIONS) {
@@ -738,7 +738,7 @@
if (!focusEvent) return NO_MEMORY;
initializeFocusEvent(focusEvent, &mMsg);
- *outSeq = mMsg.body.focus.seq;
+ *outSeq = mMsg.header.seq;
*outEvent = focusEvent;
break;
}
@@ -752,10 +752,10 @@
status_t result;
for (size_t i = mBatches.size(); i > 0; ) {
i--;
- Batch& batch = mBatches.editItemAt(i);
+ Batch& batch = mBatches[i];
if (frameTime < 0) {
result = consumeSamples(factory, batch, batch.samples.size(), outSeq, outEvent);
- mBatches.removeAt(i);
+ mBatches.erase(mBatches.begin() + i);
return result;
}
@@ -770,11 +770,11 @@
result = consumeSamples(factory, batch, split + 1, outSeq, outEvent);
const InputMessage* next;
- if (batch.samples.isEmpty()) {
- mBatches.removeAt(i);
+ if (batch.samples.empty()) {
+ mBatches.erase(mBatches.begin() + i);
next = nullptr;
} else {
- next = &batch.samples.itemAt(0);
+ next = &batch.samples[0];
}
if (!result && mResampleTouch) {
resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next);
@@ -792,20 +792,20 @@
uint32_t chain = 0;
for (size_t i = 0; i < count; i++) {
- InputMessage& msg = batch.samples.editItemAt(i);
+ InputMessage& msg = batch.samples[i];
updateTouchState(msg);
if (i) {
SeqChain seqChain;
- seqChain.seq = msg.body.motion.seq;
+ seqChain.seq = msg.header.seq;
seqChain.chain = chain;
- mSeqChains.push(seqChain);
+ mSeqChains.push_back(seqChain);
addSample(motionEvent, &msg);
} else {
initializeMotionEvent(motionEvent, &msg);
}
- chain = msg.body.motion.seq;
+ chain = msg.header.seq;
}
- batch.samples.removeItemsAt(0, count);
+ batch.samples.erase(batch.samples.begin(), batch.samples.begin() + count);
*outSeq = chain;
*outEvent = motionEvent;
@@ -827,10 +827,10 @@
case AMOTION_EVENT_ACTION_DOWN: {
ssize_t index = findTouchState(deviceId, source);
if (index < 0) {
- mTouchStates.push();
+ mTouchStates.push_back({});
index = mTouchStates.size() - 1;
}
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
touchState.initialize(deviceId, source);
touchState.addHistory(msg);
break;
@@ -839,7 +839,7 @@
case AMOTION_EVENT_ACTION_MOVE: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
touchState.addHistory(msg);
rewriteMessage(touchState, msg);
}
@@ -849,7 +849,7 @@
case AMOTION_EVENT_ACTION_POINTER_DOWN: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
rewriteMessage(touchState, msg);
}
@@ -859,7 +859,7 @@
case AMOTION_EVENT_ACTION_POINTER_UP: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
rewriteMessage(touchState, msg);
touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
}
@@ -869,7 +869,7 @@
case AMOTION_EVENT_ACTION_SCROLL: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
rewriteMessage(touchState, msg);
}
break;
@@ -879,9 +879,9 @@
case AMOTION_EVENT_ACTION_CANCEL: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
rewriteMessage(touchState, msg);
- mTouchStates.removeAt(index);
+ mTouchStates.erase(mTouchStates.begin() + index);
}
break;
}
@@ -938,7 +938,7 @@
return;
}
- TouchState& touchState = mTouchStates.editItemAt(index);
+ TouchState& touchState = mTouchStates[index];
if (touchState.historySize < 1) {
#if DEBUG_RESAMPLING
ALOGD("Not resampled, no history for device.");
@@ -1084,11 +1084,11 @@
size_t chainIndex = 0;
for (size_t i = seqChainCount; i > 0; ) {
i--;
- const SeqChain& seqChain = mSeqChains.itemAt(i);
+ const SeqChain& seqChain = mSeqChains[i];
if (seqChain.seq == currentSeq) {
currentSeq = seqChain.chain;
chainSeqs[chainIndex++] = currentSeq;
- mSeqChains.removeAt(i);
+ mSeqChains.erase(mSeqChains.begin() + i);
}
}
status_t status = OK;
@@ -1102,7 +1102,7 @@
SeqChain seqChain;
seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
seqChain.chain = chainSeqs[chainIndex];
- mSeqChains.push(seqChain);
+ mSeqChains.push_back(seqChain);
if (!chainIndex) break;
chainIndex--;
}
@@ -1117,7 +1117,7 @@
status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
InputMessage msg;
msg.header.type = InputMessage::Type::FINISHED;
- msg.body.finished.seq = seq;
+ msg.header.seq = seq;
msg.body.finished.handled = handled ? 1 : 0;
return mChannel->sendMessage(&msg);
}
@@ -1127,23 +1127,23 @@
}
bool InputConsumer::hasPendingBatch() const {
- return !mBatches.isEmpty();
+ return !mBatches.empty();
}
int32_t InputConsumer::getPendingBatchSource() const {
- if (mBatches.isEmpty()) {
+ if (mBatches.empty()) {
return AINPUT_SOURCE_CLASS_NONE;
}
- const Batch& batch = mBatches.itemAt(0);
- const InputMessage& head = batch.samples.itemAt(0);
+ const Batch& batch = mBatches[0];
+ const InputMessage& head = batch.samples[0];
return head.body.motion.source;
}
ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const {
for (size_t i = 0; i < mBatches.size(); i++) {
- const Batch& batch = mBatches.itemAt(i);
- const InputMessage& head = batch.samples.itemAt(0);
+ const Batch& batch = mBatches[i];
+ const InputMessage& head = batch.samples[0];
if (head.body.motion.deviceId == deviceId && head.body.motion.source == source) {
return i;
}
@@ -1153,7 +1153,7 @@
ssize_t InputConsumer::findTouchState(int32_t deviceId, int32_t source) const {
for (size_t i = 0; i < mTouchStates.size(); i++) {
- const TouchState& touchState = mTouchStates.itemAt(i);
+ const TouchState& touchState = mTouchStates[i];
if (touchState.deviceId == deviceId && touchState.source == source) {
return i;
}
@@ -1207,7 +1207,7 @@
}
bool InputConsumer::canAddSample(const Batch& batch, const InputMessage *msg) {
- const InputMessage& head = batch.samples.itemAt(0);
+ const InputMessage& head = batch.samples[0];
uint32_t pointerCount = msg->body.motion.pointerCount;
if (head.body.motion.pointerCount != pointerCount
|| head.body.motion.action != msg->body.motion.action) {
@@ -1225,11 +1225,72 @@
ssize_t InputConsumer::findSampleNoLaterThan(const Batch& batch, nsecs_t time) {
size_t numSamples = batch.samples.size();
size_t index = 0;
- while (index < numSamples
- && batch.samples.itemAt(index).body.motion.eventTime <= time) {
+ while (index < numSamples && batch.samples[index].body.motion.eventTime <= time) {
index += 1;
}
return ssize_t(index) - 1;
}
+std::string InputConsumer::dump() const {
+ std::string out;
+ out = out + "mResampleTouch = " + toString(mResampleTouch) + "\n";
+ out = out + "mChannel = " + mChannel->getName() + "\n";
+ out = out + "mMsgDeferred: " + toString(mMsgDeferred) + "\n";
+ if (mMsgDeferred) {
+ out = out + "mMsg : " + InputMessage::typeToString(mMsg.header.type) + "\n";
+ }
+ out += "Batches:\n";
+ for (const Batch& batch : mBatches) {
+ out += " Batch:\n";
+ for (const InputMessage& msg : batch.samples) {
+ out += android::base::StringPrintf(" Message %" PRIu32 ": %s ", msg.header.seq,
+ InputMessage::typeToString(msg.header.type));
+ switch (msg.header.type) {
+ case InputMessage::Type::KEY: {
+ out += android::base::StringPrintf("action=%s keycode=%" PRId32,
+ KeyEvent::actionToString(
+ msg.body.key.action),
+ msg.body.key.keyCode);
+ break;
+ }
+ case InputMessage::Type::MOTION: {
+ out = out + "action=" + MotionEvent::actionToString(msg.body.motion.action);
+ for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
+ const float x = msg.body.motion.pointers[i].coords.getX();
+ const float y = msg.body.motion.pointers[i].coords.getY();
+ out += android::base::StringPrintf("\n Pointer %" PRIu32
+ " : x=%.1f y=%.1f",
+ i, x, y);
+ }
+ break;
+ }
+ case InputMessage::Type::FINISHED: {
+ out += android::base::StringPrintf("handled=%s",
+ toString(msg.body.finished.handled));
+ break;
+ }
+ case InputMessage::Type::FOCUS: {
+ out += android::base::StringPrintf("hasFocus=%s inTouchMode=%s",
+ toString(msg.body.focus.hasFocus),
+ toString(msg.body.focus.inTouchMode));
+ break;
+ }
+ }
+ out += "\n";
+ }
+ }
+ if (mBatches.empty()) {
+ out += " <empty>\n";
+ }
+ out += "mSeqChains:\n";
+ for (const SeqChain& chain : mSeqChains) {
+ out += android::base::StringPrintf(" chain: seq = %" PRIu32 " chain=%" PRIu32, chain.seq,
+ chain.chain);
+ }
+ if (mSeqChains.empty()) {
+ out += " <empty>\n";
+ }
+ return out;
+}
+
} // namespace android
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index 3700e8f..36c1f80 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <type_traits>
#define LOG_TAG "InputWindow"
#define LOG_NDEBUG 0
@@ -24,122 +25,8 @@
#include <log/log.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-
namespace android {
-const char* inputWindowFlagToString(uint32_t 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 "UNKNOWN";
-}
-
-std::string inputWindowFlagsToString(uint32_t flags) {
- std::string result;
- for (BitSet32 bits(flags); !bits.isEmpty();) {
- uint32_t bit = bits.clearLastMarkedBit(); // counts from left
- const uint32_t flag = 1 << (32 - bit - 1);
- result += android::base::StringPrintf("%s | ", inputWindowFlagToString(flag));
- }
- return result;
-}
// --- InputWindowInfo ---
void InputWindowInfo::addTouchableRegion(const Rect& region) {
@@ -156,7 +43,7 @@
}
bool InputWindowInfo::supportsSplitTouch() const {
- return layoutParamsFlags & FLAG_SPLIT_TOUCH;
+ return flags.test(Flag::SPLIT_TOUCH);
}
bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
@@ -164,96 +51,140 @@
&& frameTop < other->frameBottom && frameBottom > other->frameTop;
}
-status_t InputWindowInfo::write(Parcel& output) const {
+bool InputWindowInfo::operator==(const InputWindowInfo& info) const {
+ return info.token == token && info.id == id && info.name == name && info.flags == flags &&
+ info.type == type && info.dispatchingTimeout == dispatchingTimeout &&
+ 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.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible &&
+ info.canReceiveKeys == canReceiveKeys && info.trustedOverlay == trustedOverlay &&
+ info.hasFocus == hasFocus && info.hasWallpaper == hasWallpaper &&
+ info.paused == paused && info.ownerPid == ownerPid && info.ownerUid == ownerUid &&
+ info.inputFeatures == inputFeatures && info.displayId == displayId &&
+ info.portalToDisplayId == portalToDisplayId &&
+ info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop &&
+ info.applicationInfo.name == applicationInfo.name &&
+ info.applicationInfo.token == applicationInfo.token &&
+ info.applicationInfo.dispatchingTimeout == applicationInfo.dispatchingTimeout;
+}
+
+status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __func__);
+ return BAD_VALUE;
+ }
if (name.empty()) {
- output.writeInt32(0);
+ parcel->writeInt32(0);
return OK;
}
- output.writeInt32(1);
- status_t s = output.writeStrongBinder(token);
- if (s != OK) return s;
+ parcel->writeInt32(1);
- output.writeInt32(id);
- output.writeString8(String8(name.c_str()));
- output.writeInt32(layoutParamsFlags);
- output.writeInt32(layoutParamsType);
- output.writeInt64(dispatchingTimeout.count());
- output.writeInt32(frameLeft);
- output.writeInt32(frameTop);
- output.writeInt32(frameRight);
- output.writeInt32(frameBottom);
- output.writeInt32(surfaceInset);
- output.writeFloat(globalScaleFactor);
- output.writeFloat(windowXScale);
- output.writeFloat(windowYScale);
- output.writeBool(visible);
- output.writeBool(canReceiveKeys);
- output.writeBool(hasFocus);
- output.writeBool(hasWallpaper);
- output.writeBool(paused);
- output.writeBool(trustedOverlay);
- output.writeInt32(ownerPid);
- output.writeInt32(ownerUid);
- output.writeInt32(inputFeatures);
- output.writeInt32(displayId);
- output.writeInt32(portalToDisplayId);
- applicationInfo.write(output);
- output.write(touchableRegion);
- output.writeBool(replaceTouchableRegionWithCrop);
- output.writeStrongBinder(touchableRegionCropHandle.promote());
- return OK;
+ status_t status = parcel->writeStrongBinder(token) ?:
+ parcel->writeInt64(dispatchingTimeout.count()) ?:
+ parcel->writeInt32(id) ?:
+ parcel->writeUtf8AsUtf16(name) ?:
+ parcel->writeInt32(flags.get()) ?:
+ parcel->writeInt32(static_cast<std::underlying_type_t<InputWindowInfo::Type>>(type)) ?:
+ parcel->writeInt32(frameLeft) ?:
+ parcel->writeInt32(frameTop) ?:
+ parcel->writeInt32(frameRight) ?:
+ parcel->writeInt32(frameBottom) ?:
+ parcel->writeInt32(surfaceInset) ?:
+ parcel->writeFloat(globalScaleFactor) ?:
+ parcel->writeFloat(windowXScale) ?:
+ parcel->writeFloat(windowYScale) ?:
+ parcel->writeBool(visible) ?:
+ parcel->writeBool(canReceiveKeys) ?:
+ parcel->writeBool(hasFocus) ?:
+ parcel->writeBool(hasWallpaper) ?:
+ parcel->writeBool(paused) ?:
+ parcel->writeBool(trustedOverlay) ?:
+ parcel->writeInt32(ownerPid) ?:
+ parcel->writeInt32(ownerUid) ?:
+ parcel->writeInt32(inputFeatures.get()) ?:
+ parcel->writeInt32(displayId) ?:
+ parcel->writeInt32(portalToDisplayId) ?:
+ applicationInfo.writeToParcel(parcel) ?:
+ parcel->write(touchableRegion) ?:
+ parcel->writeBool(replaceTouchableRegionWithCrop) ?:
+ parcel->writeStrongBinder(touchableRegionCropHandle.promote());
+
+ return status;
}
-InputWindowInfo InputWindowInfo::read(const Parcel& from) {
- InputWindowInfo ret;
-
- if (from.readInt32() == 0) {
- return ret;
+status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __func__);
+ return BAD_VALUE;
+ }
+ if (parcel->readInt32() == 0) {
+ return OK;
}
- ret.token = from.readStrongBinder();
- ret.id = from.readInt32();
- ret.name = from.readString8().c_str();
- ret.layoutParamsFlags = from.readInt32();
- ret.layoutParamsType = from.readInt32();
- ret.dispatchingTimeout = decltype(ret.dispatchingTimeout)(from.readInt64());
- ret.frameLeft = from.readInt32();
- ret.frameTop = from.readInt32();
- ret.frameRight = from.readInt32();
- ret.frameBottom = from.readInt32();
- ret.surfaceInset = from.readInt32();
- ret.globalScaleFactor = from.readFloat();
- ret.windowXScale = from.readFloat();
- ret.windowYScale = from.readFloat();
- ret.visible = from.readBool();
- ret.canReceiveKeys = from.readBool();
- ret.hasFocus = from.readBool();
- ret.hasWallpaper = from.readBool();
- ret.paused = from.readBool();
- ret.trustedOverlay = from.readBool();
- ret.ownerPid = from.readInt32();
- ret.ownerUid = from.readInt32();
- ret.inputFeatures = from.readInt32();
- ret.displayId = from.readInt32();
- ret.portalToDisplayId = from.readInt32();
- ret.applicationInfo = InputApplicationInfo::read(from);
- from.read(ret.touchableRegion);
- ret.replaceTouchableRegionWithCrop = from.readBool();
- ret.touchableRegionCropHandle = from.readStrongBinder();
+ token = parcel->readStrongBinder();
+ dispatchingTimeout = static_cast<decltype(dispatchingTimeout)>(parcel->readInt64());
+ status_t status = parcel->readInt32(&id) ?: parcel->readUtf8FromUtf16(&name);
+ if (status != OK) {
+ return status;
+ }
- return ret;
-}
+ flags = Flags<Flag>(parcel->readInt32());
+ type = static_cast<Type>(parcel->readInt32());
+ 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->readBool(&visible) ?:
+ parcel->readBool(&canReceiveKeys) ?:
+ parcel->readBool(&hasFocus) ?:
+ parcel->readBool(&hasWallpaper) ?:
+ parcel->readBool(&paused) ?:
+ parcel->readBool(&trustedOverlay) ?:
+ parcel->readInt32(&ownerPid) ?:
+ parcel->readInt32(&ownerUid);
-InputWindowInfo::InputWindowInfo(const Parcel& from) {
- *this = read(from);
+ if (status != OK) {
+ return status;
+ }
+
+ inputFeatures = Flags<Feature>(parcel->readInt32());
+ status = parcel->readInt32(&displayId) ?:
+ parcel->readInt32(&portalToDisplayId) ?:
+ applicationInfo.readFromParcel(parcel) ?:
+ parcel->read(touchableRegion) ?:
+ parcel->readBool(&replaceTouchableRegionWithCrop);
+
+ if (status != OK) {
+ return status;
+ }
+
+ touchableRegionCropHandle = parcel->readStrongBinder();
+
+ return OK;
}
// --- InputWindowHandle ---
-InputWindowHandle::InputWindowHandle() {
+InputWindowHandle::InputWindowHandle() {}
+
+InputWindowHandle::~InputWindowHandle() {}
+
+InputWindowHandle::InputWindowHandle(const InputWindowHandle& other) : mInfo(other.mInfo) {}
+
+InputWindowHandle::InputWindowHandle(const InputWindowInfo& other) : mInfo(other) {}
+
+status_t InputWindowHandle::writeToParcel(android::Parcel* parcel) const {
+ return mInfo.writeToParcel(parcel);
}
-InputWindowHandle::~InputWindowHandle() {
+status_t InputWindowHandle::readFromParcel(const android::Parcel* parcel) {
+ return mInfo.readFromParcel(parcel);
}
void InputWindowHandle::releaseChannel() {
@@ -268,4 +199,106 @@
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/Keyboard.cpp b/libs/input/Keyboard.cpp
index 56900c1..25025f2 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -105,8 +105,7 @@
status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,
const std::string& name) {
- std::string path(getPath(deviceIdentifier, name,
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
+ std::string path(getPath(deviceIdentifier, name, InputDeviceConfigurationFileType::KEY_LAYOUT));
if (path.empty()) {
return NAME_NOT_FOUND;
}
@@ -122,8 +121,8 @@
status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
const std::string& name) {
- std::string path = getPath(deviceIdentifier, name,
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP);
+ std::string path =
+ getPath(deviceIdentifier, name, InputDeviceConfigurationFileType::KEY_CHARACTER_MAP);
if (path.empty()) {
return NAME_NOT_FOUND;
}
diff --git a/libs/input/android/InputChannelInfo.aidl b/libs/input/android/InputChannelInfo.aidl
new file mode 100644
index 0000000..2e83b96
--- /dev/null
+++ b/libs/input/android/InputChannelInfo.aidl
@@ -0,0 +1,20 @@
+/* //device/java/android/android/view/InputChannel.aidl
+**
+** Copyright 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.
+*/
+
+package android;
+
+parcelable InputChannelInfo cpp_header "input/InputTransport.h";
diff --git a/libs/input/android/InputWindowInfo.aidl b/libs/input/android/InputWindowInfo.aidl
new file mode 100644
index 0000000..eeaf400
--- /dev/null
+++ b/libs/input/android/InputWindowInfo.aidl
@@ -0,0 +1,20 @@
+/* //device/java/android/android/view/InputChannel.aidl
+**
+** Copyright 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.
+*/
+
+package android;
+
+parcelable InputWindowInfo cpp_header "input/InputWindow.h";
diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl
new file mode 100644
index 0000000..8ff9dae
--- /dev/null
+++ b/libs/input/android/os/IInputFlinger.aidl
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+package android.os;
+
+import android.InputChannelInfo;
+import android.InputWindowInfo;
+import android.os.ISetInputWindowsListener;
+
+/** @hide */
+interface IInputFlinger
+{
+ void setInputWindows(in InputWindowInfo[] inputHandles,
+ in @nullable ISetInputWindowsListener setInputWindowsListener);
+ void registerInputChannel(in InputChannelInfo info);
+ void unregisterInputChannel(in InputChannelInfo info);
+}
diff --git a/libs/input/android/os/ISetInputWindowsListener.aidl b/libs/input/android/os/ISetInputWindowsListener.aidl
new file mode 100644
index 0000000..bb58fb6
--- /dev/null
+++ b/libs/input/android/os/ISetInputWindowsListener.aidl
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+
+package android.os;
+
+/** @hide */
+oneway interface ISetInputWindowsListener
+{
+ void onSetInputWindowsFinished();
+}
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 3b57146..9782c1a 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -2,6 +2,7 @@
cc_test {
name: "libinput_tests",
srcs: [
+ "Flags_test.cpp",
"IdGenerator_test.cpp",
"InputChannel_test.cpp",
"InputDevice_test.cpp",
diff --git a/libs/input/tests/Flags_test.cpp b/libs/input/tests/Flags_test.cpp
new file mode 100644
index 0000000..800404d
--- /dev/null
+++ b/libs/input/tests/Flags_test.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright 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 <gtest/gtest.h>
+#include <input/Flags.h>
+
+#include <type_traits>
+
+namespace android::test {
+
+using namespace android::flag_operators;
+
+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));
+ ASSERT_FALSE(flags.test(TestFlags::TWO));
+ ASSERT_FALSE(flags.test(TestFlags::THREE));
+}
+
+TEST(Flags, Any) {
+ Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
+ ASSERT_TRUE(flags.any(TestFlags::ONE));
+ ASSERT_TRUE(flags.any(TestFlags::TWO));
+ ASSERT_FALSE(flags.any(TestFlags::THREE));
+ ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO));
+ ASSERT_TRUE(flags.any(TestFlags::TWO | TestFlags::THREE));
+ ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::THREE));
+ ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, All) {
+ Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
+ ASSERT_TRUE(flags.all(TestFlags::ONE));
+ ASSERT_TRUE(flags.all(TestFlags::TWO));
+ ASSERT_FALSE(flags.all(TestFlags::THREE));
+ ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO));
+ ASSERT_FALSE(flags.all(TestFlags::TWO | TestFlags::THREE));
+ ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::THREE));
+ ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, DefaultConstructor_hasNoFlagsSet) {
+ Flags<TestFlags> flags;
+ ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, NotOperator_onEmptyFlagsSetsAllFlags) {
+ Flags<TestFlags> flags;
+ flags = ~flags;
+ ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, NotOperator_onNonEmptyFlagsInvertsFlags) {
+ Flags<TestFlags> flags = TestFlags::TWO;
+ flags = ~flags;
+ ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE));
+ ASSERT_FALSE(flags.test(TestFlags::TWO));
+}
+
+TEST(Flags, OrOperator_withNewFlag) {
+ Flags<TestFlags> flags = TestFlags::ONE;
+ Flags<TestFlags> flags2 = flags | TestFlags::TWO;
+ ASSERT_FALSE(flags2.test(TestFlags::THREE));
+ ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::TWO));
+}
+
+TEST(Flags, OrOperator_withExistingFlag) {
+ Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+ Flags<TestFlags> flags2 = flags | TestFlags::THREE;
+ ASSERT_FALSE(flags2.test(TestFlags::TWO));
+ ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::THREE));
+}
+
+TEST(Flags, OrEqualsOperator_withNewFlag) {
+ Flags<TestFlags> flags;
+ flags |= TestFlags::THREE;
+ ASSERT_TRUE(flags.test(TestFlags::THREE));
+ ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO));
+}
+
+TEST(Flags, OrEqualsOperator_withExistingFlag) {
+ Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+ flags |= TestFlags::THREE;
+ ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE));
+ ASSERT_FALSE(flags.test(TestFlags::TWO));
+}
+
+TEST(Flags, AndOperator_withOneSetFlag) {
+ Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+ Flags<TestFlags> andFlags = flags & TestFlags::THREE;
+ ASSERT_TRUE(andFlags.test(TestFlags::THREE));
+ ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO));
+}
+
+TEST(Flags, AndOperator_withMultipleSetFlags) {
+ Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+ Flags<TestFlags> andFlags = flags & (TestFlags::ONE | TestFlags::THREE);
+ ASSERT_TRUE(andFlags.all(TestFlags::ONE | TestFlags::THREE));
+ ASSERT_FALSE(andFlags.test(TestFlags::TWO));
+}
+
+TEST(Flags, AndOperator_withNoSetFlags) {
+ Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+ Flags<TestFlags> andFlags = flags & TestFlags::TWO;
+ ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, Equality) {
+ Flags<TestFlags> flags1 = TestFlags::ONE | TestFlags::TWO;
+ Flags<TestFlags> flags2 = TestFlags::ONE | TestFlags::TWO;
+ ASSERT_EQ(flags1, flags2);
+}
+
+TEST(Flags, Inequality) {
+ Flags<TestFlags> flags1 = TestFlags::ONE | TestFlags::TWO;
+ Flags<TestFlags> flags2 = TestFlags::ONE | TestFlags::THREE;
+ ASSERT_NE(flags1, flags2);
+}
+
+TEST(Flags, EqualsOperator) {
+ Flags<TestFlags> flags;
+ flags = TestFlags::ONE;
+ ASSERT_TRUE(flags.test(TestFlags::ONE));
+ ASSERT_FALSE(flags.any(TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, EqualsOperator_DontShareState) {
+ Flags<TestFlags> flags1 = TestFlags::ONE | TestFlags::TWO;
+ Flags<TestFlags> flags2 = flags1;
+ ASSERT_EQ(flags1, flags2);
+
+ flags1 &= TestFlags::TWO;
+ ASSERT_NE(flags1, flags2);
+}
+
+TEST(Flags, String_NoFlagsWithDefaultStringify) {
+ Flags<TestFlags> flags;
+ ASSERT_EQ(flags.string(), "0x0");
+}
+
+TEST(Flags, String_NoFlagsWithNonDefaultStringify) {
+ Flags<TestFlags> flags;
+ ASSERT_EQ(flags.string(toStringComplete), "0x0");
+}
+
+TEST(Flags, String_WithDefaultStringify) {
+ Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
+ ASSERT_EQ(flags.string(), "0x00000003");
+}
+
+TEST(Flags, String_WithCompleteStringify) {
+ Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
+ ASSERT_EQ(flags.string(toStringComplete), "ONE | TWO");
+}
+
+TEST(Flags, String_WithIncompleteStringify) {
+ Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+ ASSERT_EQ(flags.string(toStringIncomplete), "ONE | 0x00000004");
+}
+
+} // 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 ada275d..4187ca9 100644
--- a/libs/input/tests/InputChannel_test.cpp
+++ b/libs/input/tests/InputChannel_test.cpp
@@ -23,6 +23,7 @@
#include <errno.h>
#include <binder/Binder.h>
+#include <binder/Parcel.h>
#include <gtest/gtest.h>
#include <input/InputTransport.h>
#include <utils/StopWatch.h>
@@ -102,7 +103,7 @@
InputMessage clientReply;
memset(&clientReply, 0, sizeof(InputMessage));
clientReply.header.type = InputMessage::Type::FINISHED;
- clientReply.body.finished.seq = 0x11223344;
+ clientReply.header.seq = 0x11223344;
clientReply.body.finished.handled = true;
EXPECT_EQ(OK, clientChannel->sendMessage(&clientReply))
<< "client channel should be able to send message to server channel";
@@ -112,7 +113,7 @@
<< "server channel should be able to receive message from client channel";
EXPECT_EQ(clientReply.header.type, serverReply.header.type)
<< "server channel should receive the correct message from client channel";
- EXPECT_EQ(clientReply.body.finished.seq, serverReply.body.finished.seq)
+ EXPECT_EQ(clientReply.header.seq, serverReply.header.seq)
<< "server channel should receive the correct message from client channel";
EXPECT_EQ(clientReply.body.finished.handled, serverReply.body.finished.handled)
<< "server channel should receive the correct message from client channel";
@@ -180,7 +181,7 @@
InputMessage serverMsg = {}, clientMsg;
serverMsg.header.type = InputMessage::Type::MOTION;
- serverMsg.body.motion.seq = 1;
+ serverMsg.header.seq = 1;
serverMsg.body.motion.pointerCount = 1;
for (MotionClassification classification : classifications) {
@@ -197,5 +198,36 @@
}
}
+TEST_F(InputChannelTest, InputChannelParcelAndUnparcel) {
+ sp<InputChannel> serverChannel, clientChannel;
+
+ status_t result =
+ InputChannel::openInputChannelPair("channel parceling", serverChannel, clientChannel);
+
+ ASSERT_EQ(OK, result) << "should have successfully opened a channel pair";
+
+ InputChannel chan;
+ Parcel parcel;
+ ASSERT_EQ(OK, serverChannel->writeToParcel(&parcel));
+ parcel.setDataPosition(0);
+ chan.readFromParcel(&parcel);
+
+ EXPECT_EQ(chan == *serverChannel, true)
+ << "inputchannel should be equal after parceling and unparceling.\n"
+ << "name " << chan.getName() << " name " << serverChannel->getName();
+}
+
+TEST_F(InputChannelTest, DuplicateChannelAndAssertEqual) {
+ sp<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();
+
+ EXPECT_EQ(*serverChannel == *dupChan, true) << "inputchannel should be equal after duplication";
+}
} // namespace android
diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp
index 8750532..e7a4587 100644
--- a/libs/input/tests/InputWindow_test.cpp
+++ b/libs/input/tests/InputWindow_test.cpp
@@ -28,13 +28,13 @@
namespace test {
TEST(InputWindowInfo, ParcellingWithoutToken) {
- InputWindowInfo i;
+ InputWindowInfo i, i2;
i.token = nullptr;
Parcel p;
- ASSERT_EQ(OK, i.write(p));
+ ASSERT_EQ(OK, i.writeToParcel(&p));
p.setDataPosition(0);
- InputWindowInfo i2 = InputWindowInfo::read(p);
+ i2.readFromParcel(&p);
ASSERT_TRUE(i2.token == nullptr);
}
@@ -44,8 +44,8 @@
i.token = new BBinder();
i.id = 1;
i.name = "Foobar";
- i.layoutParamsFlags = 7;
- i.layoutParamsType = 39;
+ i.flags = InputWindowInfo::Flag::SLIPPERY;
+ i.type = InputWindowInfo::Type::INPUT_METHOD;
i.dispatchingTimeout = 12s;
i.frameLeft = 93;
i.frameTop = 34;
@@ -62,22 +62,22 @@
i.paused = false;
i.ownerPid = 19;
i.ownerUid = 24;
- i.inputFeatures = 29;
+ i.inputFeatures = InputWindowInfo::Feature::DISABLE_USER_ACTIVITY;
i.displayId = 34;
i.portalToDisplayId = 2;
i.replaceTouchableRegionWithCrop = true;
i.touchableRegionCropHandle = touchableRegionCropHandle;
Parcel p;
- i.write(p);
-
+ i.writeToParcel(&p);
p.setDataPosition(0);
- InputWindowInfo i2 = InputWindowInfo::read(p);
+ InputWindowInfo i2;
+ i2.readFromParcel(&p);
ASSERT_EQ(i.token, i2.token);
ASSERT_EQ(i.id, i2.id);
ASSERT_EQ(i.name, i2.name);
- ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags);
- ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType);
+ ASSERT_EQ(i.flags, i2.flags);
+ ASSERT_EQ(i.type, i2.type);
ASSERT_EQ(i.dispatchingTimeout, i2.dispatchingTimeout);
ASSERT_EQ(i.frameLeft, i2.frameLeft);
ASSERT_EQ(i.frameTop, i2.frameTop);
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 1fe7bb9..50be9ad 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -34,8 +34,7 @@
void TestInputMessageAlignment() {
CHECK_OFFSET(InputMessage, body, 8);
- CHECK_OFFSET(InputMessage::Body::Key, seq, 0);
- CHECK_OFFSET(InputMessage::Body::Key, eventId, 4);
+ CHECK_OFFSET(InputMessage::Body::Key, eventId, 0);
CHECK_OFFSET(InputMessage::Body::Key, eventTime, 8);
CHECK_OFFSET(InputMessage::Body::Key, deviceId, 16);
CHECK_OFFSET(InputMessage::Body::Key, source, 20);
@@ -49,8 +48,7 @@
CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 80);
CHECK_OFFSET(InputMessage::Body::Key, downTime, 88);
- CHECK_OFFSET(InputMessage::Body::Motion, seq, 0);
- CHECK_OFFSET(InputMessage::Body::Motion, eventId, 4);
+ CHECK_OFFSET(InputMessage::Body::Motion, eventId, 0);
CHECK_OFFSET(InputMessage::Body::Motion, eventTime, 8);
CHECK_OFFSET(InputMessage::Body::Motion, deviceId, 16);
CHECK_OFFSET(InputMessage::Body::Motion, source, 20);
@@ -75,16 +73,16 @@
CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 128);
CHECK_OFFSET(InputMessage::Body::Motion, pointers, 136);
- CHECK_OFFSET(InputMessage::Body::Focus, seq, 0);
- CHECK_OFFSET(InputMessage::Body::Focus, eventId, 4);
- CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 12);
- CHECK_OFFSET(InputMessage::Body::Focus, inTouchMode, 14);
+ CHECK_OFFSET(InputMessage::Body::Focus, eventId, 0);
+ CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 4);
+ CHECK_OFFSET(InputMessage::Body::Focus, inTouchMode, 6);
- CHECK_OFFSET(InputMessage::Body::Finished, seq, 0);
CHECK_OFFSET(InputMessage::Body::Finished, handled, 4);
}
void TestHeaderSize() {
+ CHECK_OFFSET(InputMessage::Header, type, 0);
+ CHECK_OFFSET(InputMessage::Header, seq, 4);
static_assert(sizeof(InputMessage::Header) == 8);
}
@@ -98,7 +96,7 @@
offsetof(InputMessage::Body::Motion, pointers) +
sizeof(InputMessage::Body::Motion::Pointer) * MAX_POINTERS);
static_assert(sizeof(InputMessage::Body::Finished) == 8);
- static_assert(sizeof(InputMessage::Body::Focus) == 16);
+ static_assert(sizeof(InputMessage::Body::Focus) == 8);
}
// --- VerifiedInputEvent ---
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index e2d036b..f371667 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -79,6 +79,8 @@
/**
* ASurfaceTexture_dequeueBuffer returns the next available AHardwareBuffer.
+ * The caller gets ownership of the buffer and need to release it with
+ * AHardwareBuffer_release.
*/
AHardwareBuffer* ASurfaceTexture_dequeueBuffer(ASurfaceTexture* st, int* outSlotid,
android_dataspace* outDataspace,
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index d1bcd8d..ebe4484 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -208,7 +208,15 @@
*outNewContent = true;
}
} while (buffer.get() && (!queueEmpty));
- return reinterpret_cast<AHardwareBuffer*>(buffer.get());
+ AHardwareBuffer* result = nullptr;
+ if (buffer.get()) {
+ result = buffer->toAHardwareBuffer();
+ // add a reference to keep the hardware buffer alive, even if
+ // BufferQueueProducer is disconnected. This is needed, because
+ // sp reference is destroyed at the end of this function.
+ AHardwareBuffer_acquire(result);
+ }
+ return result;
}
} // namespace android
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index f3edd3c..2acc5bb 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -51,22 +51,30 @@
min_sdk_version: "apex_inherit",
shared_libs: [
+ "libbase",
"libutils",
],
static_libs: [
+ "libarect",
"libmath",
],
srcs: [
"ColorSpace.cpp",
+ "Rect.cpp",
+ "Region.cpp",
+ "Transform.cpp",
],
export_include_dirs: [
+ "include",
+ "include_private",
"include_types",
],
export_static_lib_headers: [
+ "libarect",
"libmath",
],
@@ -111,10 +119,7 @@
"HdrCapabilities.cpp",
"PixelFormat.cpp",
"PublicFormat.cpp",
- "Rect.cpp",
- "Region.cpp",
"Size.cpp",
- "Transform.cpp",
"UiConfig.cpp",
],
diff --git a/libs/ui/Transform.cpp b/libs/ui/Transform.cpp
index 06b6bfe..3bf3903 100644
--- a/libs/ui/Transform.cpp
+++ b/libs/ui/Transform.cpp
@@ -55,7 +55,6 @@
mMatrix[1][1] == other.mMatrix[1][1] && mMatrix[1][2] == other.mMatrix[1][2] &&
mMatrix[2][0] == other.mMatrix[2][0] && mMatrix[2][1] == other.mMatrix[2][1] &&
mMatrix[2][2] == other.mMatrix[2][2];
- ;
}
Transform Transform::operator * (const Transform& rhs) const
@@ -87,6 +86,19 @@
return r;
}
+Transform Transform::operator * (float value) const {
+ Transform r(*this);
+ const mat33& M(mMatrix);
+ mat33& R(r.mMatrix);
+ for (size_t i = 0; i < 3; i++) {
+ for (size_t j = 0; j < 2; j++) {
+ R[i][j] = M[i][j] * value;
+ }
+ }
+ r.type();
+ return r;
+}
+
Transform& Transform::operator=(const Transform& other) {
mMatrix = other.mMatrix;
mType = other.mType;
@@ -105,11 +117,19 @@
return mMatrix[2][1];
}
-float Transform::sx() const {
+float Transform::dsdx() const {
return mMatrix[0][0];
}
-float Transform::sy() const {
+float Transform::dtdx() const {
+ return mMatrix[1][0];
+}
+
+float Transform::dtdy() const {
+ return mMatrix[0][1];
+}
+
+float Transform::dsdy() const {
return mMatrix[1][1];
}
@@ -187,6 +207,15 @@
return NO_ERROR;
}
+void Transform::set(const std::array<float, 9>& matrix) {
+ mat33& M(mMatrix);
+ M[0][0] = matrix[0]; M[1][0] = matrix[1]; M[2][0] = matrix[2];
+ M[0][1] = matrix[3]; M[1][1] = matrix[4]; M[2][1] = matrix[5];
+ M[0][2] = matrix[6]; M[1][2] = matrix[7]; M[2][2] = matrix[8];
+ mType = UNKNOWN_TYPE;
+ type();
+}
+
vec2 Transform::transform(const vec2& v) const {
vec2 r;
const mat33& M(mMatrix);
@@ -204,9 +233,8 @@
return r;
}
-vec2 Transform::transform(int x, int y) const
-{
- return transform(vec2(x,y));
+vec2 Transform::transform(float x, float y) const {
+ return transform(vec2(x, y));
}
Rect Transform::makeBounds(int w, int h) const
diff --git a/libs/ui/include/ui/Transform.h b/libs/ui/include/ui/Transform.h
index c6bb598..cf59467 100644
--- a/libs/ui/include/ui/Transform.h
+++ b/libs/ui/include/ui/Transform.h
@@ -18,10 +18,10 @@
#include <stdint.h>
#include <sys/types.h>
+#include <array>
#include <ostream>
#include <string>
-#include <hardware/hardware.h>
#include <math/mat4.h>
#include <math/vec2.h>
#include <math/vec3.h>
@@ -44,9 +44,9 @@
enum RotationFlags : uint32_t {
ROT_0 = 0,
- FLIP_H = HAL_TRANSFORM_FLIP_H,
- FLIP_V = HAL_TRANSFORM_FLIP_V,
- ROT_90 = HAL_TRANSFORM_ROT_90,
+ FLIP_H = 1, // HAL_TRANSFORM_FLIP_H
+ FLIP_V = 2, // HAL_TRANSFORM_FLIP_V
+ ROT_90 = 4, // HAL_TRANSFORM_ROT_90
ROT_180 = FLIP_H | FLIP_V,
ROT_270 = ROT_180 | ROT_90,
ROT_INVALID = 0x80
@@ -69,24 +69,28 @@
const vec3& operator [] (size_t i) const; // returns column i
float tx() const;
float ty() const;
- float sx() const;
- float sy() const;
+ float dsdx() const;
+ float dtdx() const;
+ float dtdy() const;
+ float dsdy() const;
// modify the transform
void reset();
void set(float tx, float ty);
void set(float a, float b, float c, float d);
status_t set(uint32_t flags, float w, float h);
+ void set(const std::array<float, 9>& matrix);
// transform data
Rect makeBounds(int w, int h) const;
- vec2 transform(int x, int y) const;
+ vec2 transform(float x, float y) const;
Region transform(const Region& reg) const;
Rect transform(const Rect& bounds,
bool roundOutwards = false) const;
FloatRect transform(const FloatRect& bounds) const;
Transform& operator = (const Transform& other);
Transform operator * (const Transform& rhs) const;
+ Transform operator * (float value) const;
// assumes the last row is < 0 , 0 , 1 >
vec2 transform(const vec2& v) const;
vec3 transform(const vec3& v) const;
diff --git a/libs/vr/libpdx/fuzz/Android.bp b/libs/vr/libpdx/fuzz/Android.bp
index 8ab09f3..b36e0de 100644
--- a/libs/vr/libpdx/fuzz/Android.bp
+++ b/libs/vr/libpdx/fuzz/Android.bp
@@ -1,5 +1,5 @@
cc_fuzz {
- name: "libpdx_fuzz",
+ name: "libpdx_service_dispatcher_fuzzer",
clang: true,
srcs: [
"service_dispatcher_fuzzer.cpp",
@@ -15,6 +15,48 @@
shared_libs: [
"libutils",
"liblog",
- "libcutils",
+ "libcutils"
+ ],
+}
+
+cc_fuzz {
+ name: "libpdx_message_fuzzer",
+ clang: true,
+ srcs: [
+ "message_fuzzer.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ static_libs: [
+ "libpdx",
+ ],
+ shared_libs: [
+ "libutils",
+ "liblog",
+ "libcutils"
+ ],
+}
+
+cc_fuzz {
+ name: "libpdx_serialization_fuzzer",
+ clang: true,
+ srcs: [
+ "serialization_fuzzer.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ static_libs: [
+ "libpdx",
+ ],
+ shared_libs: [
+ "libutils",
+ "liblog",
+ "libcutils"
],
}
diff --git a/libs/vr/libpdx/fuzz/message_fuzzer.cpp b/libs/vr/libpdx/fuzz/message_fuzzer.cpp
new file mode 100644
index 0000000..b627045
--- /dev/null
+++ b/libs/vr/libpdx/fuzz/message_fuzzer.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright 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.
+ */
+// Authors: corbin.souffrant@leviathansecurity.com
+// brian.balling@leviathansecurity.com
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <helpers.h>
+#include <pdx/client_channel.h>
+#include <pdx/service.h>
+#include <pdx/service_dispatcher.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/eventfd.h>
+#include <thread>
+
+using namespace android::pdx;
+
+// Fuzzer for Message object functions.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+
+ FuzzEndpoint* endpoint = new FuzzEndpoint(&fdp);
+ std::shared_ptr<Service> service(
+ new Service("FuzzService", std::unique_ptr<Endpoint>(endpoint)));
+ std::shared_ptr<Channel> channel(nullptr);
+
+ // Generate a random Message object to call functions in.
+ MessageInfo info;
+ info.pid = fdp.ConsumeIntegral<int>();
+ info.tid = fdp.ConsumeIntegral<int>();
+ info.cid = fdp.ConsumeIntegral<int>();
+ info.mid = fdp.ConsumeIntegral<int>();
+ info.euid = fdp.ConsumeIntegral<int>();
+ info.egid = fdp.ConsumeIntegral<int>();
+ info.op = fdp.ConsumeIntegral<int32_t>();
+ info.flags = fdp.ConsumeIntegral<uint32_t>();
+ info.service = service.get();
+ info.channel = channel.get();
+ info.send_len = fdp.ConsumeIntegral<size_t>();
+ info.recv_len = fdp.ConsumeIntegral<size_t>();
+ info.fd_count = fdp.ConsumeIntegral<size_t>();
+ if (fdp.remaining_bytes() >= 32) {
+ std::vector<uint8_t> impulse_vec = fdp.ConsumeBytes<uint8_t>(32);
+ memcpy(info.impulse, impulse_vec.data(), 32);
+ }
+
+ Message message = Message(info);
+
+ // A bunch of getters that probably won't do much, but might as well
+ // get coverage, while we are here.
+ message.GetProcessId();
+ message.GetThreadId();
+ message.GetEffectiveUserId();
+ message.GetEffectiveGroupId();
+ message.GetChannelId();
+ message.GetMessageId();
+ message.GetOp();
+ message.GetFlags();
+ message.GetSendLength();
+ message.GetReceiveLength();
+ message.GetFileDescriptorCount();
+ message.ImpulseEnd();
+ message.replied();
+ message.IsChannelExpired();
+ message.IsServiceExpired();
+ message.GetState();
+ message.GetState();
+
+ // Some misc. functions.
+ unsigned int fd = fdp.ConsumeIntegral<unsigned int>();
+ int clear_mask = fdp.ConsumeIntegral<int>();
+ int set_mask = fdp.ConsumeIntegral<int>();
+ Status<void> status = {};
+ message.ModifyChannelEvents(clear_mask, set_mask);
+
+ // Fuzz the handle functions.
+ LocalHandle l_handle = {};
+ BorrowedHandle b_handle = {};
+ RemoteHandle r_handle = {};
+ LocalChannelHandle lc_handle = {};
+ BorrowedChannelHandle bc_handle = {};
+ RemoteChannelHandle rc_handle = {};
+ FileReference f_ref = fdp.ConsumeIntegral<int32_t>();
+ ChannelReference c_ref = fdp.ConsumeIntegral<int32_t>();
+
+ // These don't actually modify any state in the Message or params.
+ // They can be called in any order.
+ message.PushFileHandle(b_handle);
+ message.PushFileHandle(r_handle);
+ message.PushChannelHandle(lc_handle);
+ message.PushChannelHandle(bc_handle);
+ message.PushChannelHandle(rc_handle);
+ message.GetFileHandle(f_ref, &l_handle);
+ message.GetChannelHandle(c_ref, &lc_handle);
+
+ // Can only reply once, pick at random.
+ switch (fdp.ConsumeIntegral<uint8_t>()) {
+ case 0:
+ message.ReplyFileDescriptor(fd);
+ break;
+ case 1:
+ message.Reply(status);
+ break;
+ case 2:
+ message.Reply(l_handle);
+ break;
+ case 3:
+ message.Reply(b_handle);
+ break;
+ case 4:
+ message.Reply(r_handle);
+ break;
+ case 5:
+ message.Reply(lc_handle);
+ break;
+ case 6:
+ message.Reply(bc_handle);
+ break;
+ case 7:
+ message.Reply(rc_handle);
+ }
+
+ // Fuzz the channel functions.
+ int flags = fdp.ConsumeIntegral<int>();
+ int channel_id = 0;
+ message.PushChannel(flags, channel, &channel_id);
+ message.CheckChannel(service.get(), c_ref, &channel);
+ message.CheckChannel(c_ref, &channel);
+ message.PushChannel(service.get(), flags, channel, &channel_id);
+ size_t iovec_size = sizeof(iovec);
+ struct iovec* iovecs = nullptr;
+
+ // Fuzz the read/write functions. Needs at least one iovec, plus one byte.
+ if (fdp.remaining_bytes() >= iovec_size + 1) {
+ std::vector<uint8_t> tmp_vec = fdp.ConsumeBytes<uint8_t>(iovec_size);
+ struct iovec* vector = reinterpret_cast<struct iovec*>(tmp_vec.data());
+ std::vector<uint8_t> tmp_buf =
+ fdp.ConsumeBytes<uint8_t>(fdp.remaining_bytes());
+ void* buf = reinterpret_cast<void*>(tmp_buf.data());
+ size_t buf_size = fdp.ConsumeIntegral<size_t>();
+
+ // Capping num_vecs to 1024 so it doesn't allocate too much memory.
+ size_t num_vecs = fdp.ConsumeIntegralInRange<size_t>(0, 1024);
+
+ if (num_vecs > 0)
+ iovecs = new struct iovec[num_vecs];
+ for (size_t i = 0; i < num_vecs; i++) {
+ iovecs[i] = *vector;
+ }
+
+ message.ReadAll(vector, buf_size);
+ message.WriteAll(buf, buf_size);
+ message.ReadVectorAll(vector, num_vecs);
+ message.WriteVectorAll(vector, num_vecs);
+ message.ReadVector(vector, buf_size);
+ message.WriteVector(vector, buf_size);
+ }
+
+ if (iovecs != nullptr)
+ delete[] iovecs;
+ return 0;
+}
diff --git a/libs/vr/libpdx/fuzz/serialization_fuzzer.cpp b/libs/vr/libpdx/fuzz/serialization_fuzzer.cpp
new file mode 100644
index 0000000..afde5f7
--- /dev/null
+++ b/libs/vr/libpdx/fuzz/serialization_fuzzer.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright 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.
+ */
+// Authors: corbin.souffrant@leviathansecurity.com
+// brian.balling@leviathansecurity.com
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <memory>
+#include <string>
+#include <thread>
+#include <utility>
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <pdx/rpc/argument_encoder.h>
+#include <pdx/rpc/array_wrapper.h>
+#include <pdx/rpc/default_initialization_allocator.h>
+#include <pdx/rpc/payload.h>
+#include <pdx/rpc/serializable.h>
+#include <pdx/rpc/serialization.h>
+#include <pdx/rpc/string_wrapper.h>
+#include <pdx/utility.h>
+
+using namespace android::pdx;
+using namespace android::pdx::rpc;
+
+struct FuzzType {
+ int a;
+ float b;
+ std::string c;
+
+ FuzzType() {}
+ FuzzType(int a, float b, const std::string& c) : a(a), b(b), c(c) {}
+
+ private:
+ PDX_SERIALIZABLE_MEMBERS(FuzzType, a, b, c);
+};
+
+// Fuzzer for Serialization operations, this is mostly just lifted from the
+// existing test cases to use fuzzed values as inputs.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ Payload result;
+
+ // Currently, only fuzzing subset of types. In the future, may want
+ // to add more difficult to generate types like array, map, enum, etc...
+ bool b_val = fdp.ConsumeBool();
+ uint8_t u8_val = fdp.ConsumeIntegral<uint8_t>();
+ uint16_t u16_val = fdp.ConsumeIntegral<uint16_t>();
+ uint32_t u32_val = fdp.ConsumeIntegral<uint32_t>();
+ uint64_t u64_val = fdp.ConsumeIntegral<uint64_t>();
+ int8_t i8_val = fdp.ConsumeIntegral<int8_t>();
+ int16_t i16_val = fdp.ConsumeIntegral<uint16_t>();
+ int32_t i32_val = fdp.ConsumeIntegral<uint32_t>();
+ int64_t i64_val = fdp.ConsumeIntegral<uint64_t>();
+ float f_val = fdp.ConsumeFloatingPoint<float>();
+ double d_val = fdp.ConsumeFloatingPoint<double>();
+ std::string s_val = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+ std::vector<uint8_t> vec_val =
+ fdp.ConsumeBytes<uint8_t>(fdp.remaining_bytes());
+ FuzzType t1_val{reinterpret_cast<int>(i32_val), f_val, s_val};
+
+ // Types need to be individually fuzzed because code path changes depending
+ // on which type is being serialized/deserialized.
+ Serialize(b_val, &result);
+ Deserialize(&b_val, &result);
+ Serialize(u8_val, &result);
+ Deserialize(&u8_val, &result);
+ Serialize(u16_val, &result);
+ Deserialize(&u16_val, &result);
+ Serialize(u32_val, &result);
+ Deserialize(&u32_val, &result);
+ Serialize(u64_val, &result);
+ Deserialize(&u64_val, &result);
+ Serialize(i8_val, &result);
+ Deserialize(&i8_val, &result);
+ Serialize(i16_val, &result);
+ Deserialize(&i16_val, &result);
+ Serialize(i32_val, &result);
+ Deserialize(&i32_val, &result);
+ Serialize(i64_val, &result);
+ Deserialize(&i64_val, &result);
+ Serialize(f_val, &result);
+ Deserialize(&f_val, &result);
+ Serialize(d_val, &result);
+ Deserialize(&d_val, &result);
+ Serialize(s_val, &result);
+ Deserialize(&s_val, &result);
+ Serialize(WrapString(s_val), &result);
+ Deserialize(&s_val, &result);
+ Serialize(vec_val, &result);
+ Deserialize(&vec_val, &result);
+ Serialize(t1_val, &result);
+ Deserialize(&t1_val, &result);
+
+ return 0;
+}
diff --git a/services/gpuservice/gpumem/GpuMem.cpp b/services/gpuservice/gpumem/GpuMem.cpp
index 9b4053b..245edb8 100644
--- a/services/gpuservice/gpumem/GpuMem.cpp
+++ b/services/gpuservice/gpumem/GpuMem.cpp
@@ -48,7 +48,6 @@
return;
}
- // TODO(http://b/159963505): Figure out a nicer way to wait until GPU driver loaded.
// Attach the program to the tracepoint, and the tracepoint is automatically enabled here.
int count = 0;
while (bpf_attach_tracepoint(fd, kGpuMemTraceGroup, kGpuMemTotalTracepoint) < 0) {
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index f685628..5930f0a 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -111,6 +111,7 @@
"libcutils",
"libinput",
"liblog",
+ "libui",
"libutils",
],
header_libs: [
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index f2a0014..c5f60ad 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -93,16 +93,15 @@
class BinderWindowHandle : public InputWindowHandle {
public:
- BinderWindowHandle(const InputWindowInfo& info) {
- mInfo = info;
- }
+ BinderWindowHandle(const InputWindowInfo& info) { mInfo = info; }
bool updateInfo() override {
return true;
}
};
-void InputManager::setInputWindows(const std::vector<InputWindowInfo>& infos,
+binder::Status InputManager::setInputWindows(
+ const std::vector<InputWindowInfo>& infos,
const sp<ISetInputWindowsListener>& setInputWindowsListener) {
std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> handlesPerDisplay;
@@ -116,22 +115,38 @@
if (setInputWindowsListener) {
setInputWindowsListener->onSetInputWindowsFinished();
}
+ return binder::Status::ok();
}
// Used by tests only.
-void InputManager::registerInputChannel(const sp<InputChannel>& channel) {
+binder::Status InputManager::registerInputChannel(const InputChannelInfo& info) {
IPCThreadState* ipc = IPCThreadState::self();
const int uid = ipc->getCallingUid();
if (uid != AID_SHELL && uid != AID_ROOT) {
ALOGE("Invalid attempt to register input channel over IPC"
"from non shell/root entity (PID: %d)", ipc->getCallingPid());
- return;
+ 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);
+ return binder::Status::ok();
}
-void InputManager::unregisterInputChannel(const sp<InputChannel>& channel) {
+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);
mDispatcher->unregisterInputChannel(channel);
+ return binder::Status::ok();
+}
+
+status_t InputManager::dump(int fd, const Vector<String16>& args) {
+ std::string dump;
+
+ dump += " InputFlinger dump\n";
+
+ ::write(fd, dump.c_str(), dump.size());
+ return NO_ERROR;
}
} // namespace android
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 41d9478..4993b54 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -26,18 +26,23 @@
#include <InputDispatcherInterface.h>
#include <InputDispatcherPolicyInterface.h>
-#include <input/ISetInputWindowsListener.h>
+#include <android/os/ISetInputWindowsListener.h>
#include <input/Input.h>
#include <input/InputTransport.h>
-#include <input/IInputFlinger.h>
+#include <android/os/BnInputFlinger.h>
+#include <android/os/IInputFlinger.h>
#include <utils/Errors.h>
-#include <utils/Vector.h>
-#include <utils/Timers.h>
#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/Vector.h>
+
+using android::os::BnInputFlinger;
+using android::os::ISetInputWindowsListener;
namespace android {
class InputChannel;
+class InputDispatcherThread;
/*
* The input manager is the core of the system event processing.
@@ -98,11 +103,13 @@
sp<InputClassifierInterface> getClassifier() override;
sp<InputDispatcherInterface> getDispatcher() override;
- void setInputWindows(const std::vector<InputWindowInfo>& handles,
- const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
+ status_t dump(int fd, const Vector<String16>& args) override;
+ binder::Status setInputWindows(
+ const std::vector<InputWindowInfo>& handles,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
- void registerInputChannel(const sp<InputChannel>& channel) override;
- void unregisterInputChannel(const sp<InputChannel>& channel) override;
+ binder::Status registerInputChannel(const InputChannelInfo& info) override;
+ binder::Status unregisterInputChannel(const InputChannelInfo& info) override;
private:
sp<InputReaderInterface> mReader;
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 7d8ab75..a15b7b2 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -157,8 +157,7 @@
virtual bool updateInfo() override {
mInfo.token = mServerChannel->getConnectionToken();
mInfo.name = "FakeWindowHandle";
- mInfo.layoutParamsFlags = 0;
- mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
+ mInfo.type = InputWindowInfo::Type::APPLICATION;
mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
mInfo.frameLeft = mFrame.left;
mInfo.frameTop = mFrame.top;
@@ -174,7 +173,6 @@
mInfo.paused = false;
mInfo.ownerPid = INJECTOR_PID;
mInfo.ownerUid = INJECTOR_UID;
- mInfo.inputFeatures = 0;
mInfo.displayId = ADISPLAY_ID_DEFAULT;
return true;
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index 390c6b8..d29d8df 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -68,4 +68,5 @@
export_header_lib_headers: [
"libinputdispatcher_headers",
],
+ logtags: ["EventLogTags.logtags"],
}
diff --git a/services/inputflinger/dispatcher/EventLogTags.logtags b/services/inputflinger/dispatcher/EventLogTags.logtags
new file mode 100644
index 0000000..9c0f80e
--- /dev/null
+++ b/services/inputflinger/dispatcher/EventLogTags.logtags
@@ -0,0 +1,42 @@
+# The entries in this file map a sparse set of log tag numbers to tag names.
+# This is installed on the device, in /system/etc, and parsed by logcat.
+#
+# Tag numbers are decimal integers, from 0 to 2^31. (Let's leave the
+# negative values alone for now.)
+#
+# Tag names are one or more ASCII letters and numbers or underscores, i.e.
+# "[A-Z][a-z][0-9]_". Do not include spaces or punctuation (the former
+# impacts log readability, the latter makes regex searches more annoying).
+#
+# Tag numbers and names are separated by whitespace. Blank lines and lines
+# starting with '#' are ignored.
+#
+# Optionally, after the tag names can be put a description for the value(s)
+# of the tag. Description are in the format
+# (<name>|data type[|data unit])
+# Multiple values are separated by commas.
+#
+# The data type is a number from the following values:
+# 1: int
+# 2: long
+# 3: string
+# 4: list
+#
+# The data unit is a number taken from the following list:
+# 1: Number of objects
+# 2: Number of bytes
+# 3: Number of milliseconds
+# 4: Number of allocations
+# 5: Id
+# 6: Percent
+# Default value for data of type int/long is 2 (bytes).
+#
+# See system/core/logcat/event.logtags for the master copy of the tags.
+
+# 62000 - 62199 reserved for inputflinger
+
+62000 input_interaction (windows|4)
+62001 input_focus (window|3)
+
+# NOTE - the range 1000000-2000000 is reserved for partners and others who
+# want to define their own log tags without conflicting with the core platform.
\ No newline at end of file
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 0fa2332..3bdbcce 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -45,28 +45,30 @@
#include "InputDispatcher.h"
-#include "Connection.h"
-
-#include <errno.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <statslog.h>
-#include <stddef.h>
-#include <time.h>
-#include <unistd.h>
-#include <queue>
-#include <sstream>
-
#include <android-base/chrono_utils.h>
#include <android-base/stringprintf.h>
#include <binder/Binder.h>
#include <input/InputDevice.h>
+#include <input/InputWindow.h>
#include <log/log.h>
+#include <log/log_event_list.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <powermanager/PowerManager.h>
+#include <statslog.h>
+#include <unistd.h>
#include <utils/Trace.h>
+#include <cerrno>
+#include <cinttypes>
+#include <climits>
+#include <cstddef>
+#include <ctime>
+#include <queue>
+#include <sstream>
+
+#include "Connection.h"
+
#define INDENT " "
#define INDENT2 " "
#define INDENT3 " "
@@ -103,6 +105,10 @@
// Number of recent events to keep for debugging purposes.
constexpr size_t RECENT_QUEUE_MAX_SIZE = 10;
+// Event log tags. See EventLogTags.logtags for reference
+constexpr int LOGTAG_INPUT_INTERACTION = 62000;
+constexpr int LOGTAG_INPUT_FOCUS = 62001;
+
static inline nsecs_t now() {
return systemTime(SYSTEM_TIME_MONOTONIC);
}
@@ -816,13 +822,12 @@
for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId == displayId) {
- int32_t flags = windowInfo->layoutParamsFlags;
+ auto flags = windowInfo->flags;
if (windowInfo->visible) {
- if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
- bool isTouchModal = (flags &
- (InputWindowInfo::FLAG_NOT_FOCUSABLE |
- InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
+ if (!flags.test(InputWindowInfo::Flag::NOT_TOUCHABLE)) {
+ bool isTouchModal = !flags.test(InputWindowInfo::Flag::NOT_FOCUSABLE) &&
+ !flags.test(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
int32_t portalToDisplayId = windowInfo->portalToDisplayId;
if (portalToDisplayId != ADISPLAY_ID_NONE &&
@@ -839,7 +844,7 @@
}
}
- if (addOutsideTargets && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
+ if (addOutsideTargets && flags.test(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH)) {
touchState->addOrUpdateWindow(windowHandle,
InputTarget::FLAG_DISPATCH_AS_OUTSIDE,
BitSet32(0));
@@ -1108,7 +1113,9 @@
target.inputChannel = channel;
target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
entry->dispatchInProgress = true;
-
+ std::string message = std::string("Focus ") + (entry->hasFocus ? "entering " : "leaving ") +
+ channel->getName();
+ android_log_event_list(LOGTAG_INPUT_FOCUS) << message << LOG_ID_EVENTS;
dispatchEventLocked(currentTime, entry, {target});
}
@@ -1346,6 +1353,8 @@
ALOGD("dispatchEventToCurrentInputTargets");
#endif
+ updateInteractionTokensLocked(*eventEntry, inputTargets);
+
ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
pokeUserActivityLocked(*eventEntry);
@@ -1584,7 +1593,8 @@
// Update the touch state as needed based on the properties of the touch event.
int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
- sp<InputWindowHandle> newHoverWindowHandle;
+ sp<InputWindowHandle> newHoverWindowHandle(mLastHoverWindowHandle);
+ sp<InputWindowHandle> newTouchedWindowHandle;
// Copy current touch state into tempTouchState.
// This state will be used to update mTouchStatesByDisplay at the end of this function.
@@ -1653,7 +1663,7 @@
y = int32_t(entry.pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_Y));
}
bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN;
- sp<InputWindowHandle> newTouchedWindowHandle =
+ newTouchedWindowHandle =
findTouchedWindowAtLocked(displayId, x, y, &tempTouchState,
isDown /*addOutsideTargets*/, true /*addPortalWindows*/);
@@ -1722,10 +1732,10 @@
}
// Update hover state.
- if (isHoverAction) {
+ if (maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT) {
+ newHoverWindowHandle = nullptr;
+ } else if (isHoverAction) {
newHoverWindowHandle = newTouchedWindowHandle;
- } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
- newHoverWindowHandle = mLastHoverWindowHandle;
}
// Update the temporary touch state.
@@ -1760,8 +1770,7 @@
sp<InputWindowHandle> oldTouchedWindowHandle =
tempTouchState.getFirstForegroundWindowHandle();
- sp<InputWindowHandle> newTouchedWindowHandle =
- findTouchedWindowAtLocked(displayId, x, y, &tempTouchState);
+ newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState);
if (oldTouchedWindowHandle != newTouchedWindowHandle &&
oldTouchedWindowHandle != nullptr && newTouchedWindowHandle != nullptr) {
if (DEBUG_FOCUS) {
@@ -1798,8 +1807,11 @@
}
if (newHoverWindowHandle != mLastHoverWindowHandle) {
- // Let the previous window know that the hover sequence is over.
- if (mLastHoverWindowHandle != nullptr) {
+ // Let the previous window know that the hover sequence is over, unless we already did it
+ // when dispatching it as is to newTouchedWindowHandle.
+ if (mLastHoverWindowHandle != nullptr &&
+ (maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT ||
+ mLastHoverWindowHandle != newTouchedWindowHandle)) {
#if DEBUG_HOVER
ALOGD("Sending hover exit event to window %s.",
mLastHoverWindowHandle->getName().c_str());
@@ -1808,8 +1820,11 @@
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0));
}
- // Let the new window know that the hover sequence is starting.
- if (newHoverWindowHandle != nullptr) {
+ // Let the new window know that the hover sequence is starting, unless we already did it
+ // when dispatching it as is to newTouchedWindowHandle.
+ if (newHoverWindowHandle != nullptr &&
+ (maskedAction != AMOTION_EVENT_ACTION_HOVER_ENTER ||
+ newHoverWindowHandle != newTouchedWindowHandle)) {
#if DEBUG_HOVER
ALOGD("Sending hover enter event to window %s.",
newHoverWindowHandle->getName().c_str());
@@ -1882,7 +1897,7 @@
for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
const InputWindowInfo* info = windowHandle->getInfo();
if (info->displayId == displayId &&
- windowHandle->getInfo()->layoutParamsType == InputWindowInfo::TYPE_WALLPAPER) {
+ windowHandle->getInfo()->type == InputWindowInfo::Type::WALLPAPER) {
tempTouchState
.addOrUpdateWindow(windowHandle,
InputTarget::FLAG_WINDOW_IS_OBSCURED |
@@ -2164,7 +2179,7 @@
getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
if (focusedWindowHandle != nullptr) {
const InputWindowInfo* info = focusedWindowHandle->getInfo();
- if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
+ if (info->inputFeatures.test(InputWindowInfo::Feature::DISABLE_USER_ACTIVITY)) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("Not poking user activity: disabled by window '%s'.", info->name.c_str());
#endif
@@ -2428,6 +2443,75 @@
traceOutboundQueueLength(connection);
}
+/**
+ * This function is purely for debugging. It helps us understand where the user interaction
+ * was taking place. For example, if user is touching launcher, we will see a log that user
+ * started interacting with launcher. In that example, the event would go to the wallpaper as well.
+ * We will see both launcher and wallpaper in that list.
+ * Once the interaction with a particular set of connections starts, no new logs will be printed
+ * until the set of interacted connections changes.
+ *
+ * The following items are skipped, to reduce the logspam:
+ * ACTION_OUTSIDE: any windows that are receiving ACTION_OUTSIDE are not logged
+ * ACTION_UP: any windows that receive ACTION_UP are not logged (for both keys and motions).
+ * This includes situations like the soft BACK button key. When the user releases (lifts up the
+ * finger) the back button, then navigation bar will inject KEYCODE_BACK with ACTION_UP.
+ * Both of those ACTION_UP events would not be logged
+ * Monitors (both gesture and global): any gesture monitors or global monitors receiving events
+ * will not be logged. This is omitted to reduce the amount of data printed.
+ * If you see <none>, it's likely that one of the gesture monitors pilfered the event, and therefore
+ * gesture monitor is the only connection receiving the remainder of the gesture.
+ */
+void InputDispatcher::updateInteractionTokensLocked(const EventEntry& entry,
+ const std::vector<InputTarget>& targets) {
+ // Skip ACTION_UP events, and all events other than keys and motions
+ if (entry.type == EventEntry::Type::KEY) {
+ const KeyEntry& keyEntry = static_cast<const KeyEntry&>(entry);
+ if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
+ return;
+ }
+ } else if (entry.type == EventEntry::Type::MOTION) {
+ const MotionEntry& motionEntry = static_cast<const MotionEntry&>(entry);
+ if (motionEntry.action == AMOTION_EVENT_ACTION_UP ||
+ motionEntry.action == AMOTION_EVENT_ACTION_CANCEL) {
+ return;
+ }
+ } else {
+ return; // Not a key or a motion
+ }
+
+ std::unordered_set<sp<IBinder>, IBinderHash> newConnectionTokens;
+ std::vector<sp<Connection>> newConnections;
+ for (const InputTarget& target : targets) {
+ if ((target.flags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) ==
+ InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
+ continue; // Skip windows that receive ACTION_OUTSIDE
+ }
+
+ sp<IBinder> token = target.inputChannel->getConnectionToken();
+ sp<Connection> connection = getConnectionLocked(token);
+ if (connection == nullptr || connection->monitor) {
+ continue; // We only need to keep track of the non-monitor connections.
+ }
+ newConnectionTokens.insert(std::move(token));
+ newConnections.emplace_back(connection);
+ }
+ if (newConnectionTokens == mInteractionConnectionTokens) {
+ return; // no change
+ }
+ mInteractionConnectionTokens = newConnectionTokens;
+
+ std::string windowList;
+ for (const sp<Connection>& connection : newConnections) {
+ windowList += connection->getWindowName() + ", ";
+ }
+ std::string message = "Interaction with windows: " + windowList;
+ if (windowList.empty()) {
+ message += "<none>";
+ }
+ android_log_event_list(LOGTAG_INPUT_INTERACTION) << message << LOG_ID_EVENTS;
+}
+
void InputDispatcher::dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
const sp<IBinder>& newToken) {
int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
@@ -3641,10 +3725,9 @@
if ((getInputChannelLocked(handle->getToken()) == nullptr &&
info->portalToDisplayId == ADISPLAY_ID_NONE)) {
const bool noInputChannel =
- info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL;
- const bool canReceiveInput =
- !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) ||
- !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE);
+ info->inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
+ const bool canReceiveInput = !info->flags.test(InputWindowInfo::Flag::NOT_TOUCHABLE) ||
+ !info->flags.test(InputWindowInfo::Flag::NOT_FOCUSABLE);
if (canReceiveInput && !noInputChannel) {
ALOGV("Window handle %s has no registered input channel",
handle->getName().c_str());
@@ -4134,7 +4217,7 @@
dump += StringPrintf(INDENT3 "%zu: name='%s', displayId=%d, "
"portalToDisplayId=%d, paused=%s, hasFocus=%s, "
"hasWallpaper=%s, visible=%s, canReceiveKeys=%s, "
- "flags=0x%08x, type=0x%08x, "
+ "flags=%s, type=0x%08x, "
"frame=[%d,%d][%d,%d], globalScale=%f, "
"windowScale=(%f,%f), touchableRegion=",
i, windowInfo->name.c_str(), windowInfo->displayId,
@@ -4144,20 +4227,20 @@
toString(windowInfo->hasWallpaper),
toString(windowInfo->visible),
toString(windowInfo->canReceiveKeys),
- windowInfo->layoutParamsFlags,
- windowInfo->layoutParamsType, windowInfo->frameLeft,
- windowInfo->frameTop, windowInfo->frameRight,
- windowInfo->frameBottom, windowInfo->globalScaleFactor,
- windowInfo->windowXScale, windowInfo->windowYScale);
+ windowInfo->flags.string(InputWindowInfo::flagToString)
+ .c_str(),
+ static_cast<int32_t>(windowInfo->type),
+ windowInfo->frameLeft, windowInfo->frameTop,
+ windowInfo->frameRight, windowInfo->frameBottom,
+ windowInfo->globalScaleFactor, windowInfo->windowXScale,
+ windowInfo->windowYScale);
dumpRegion(dump, windowInfo->touchableRegion);
- dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures);
+ dump += StringPrintf(", inputFeatures=%s",
+ windowInfo->inputFeatures.string().c_str());
dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%" PRId64
"ms\n",
windowInfo->ownerPid, windowInfo->ownerUid,
millis(windowInfo->dispatchingTimeout));
- dump += StringPrintf(INDENT4 " flags: %s\n",
- inputWindowFlagsToString(windowInfo->layoutParamsFlags)
- .c_str());
}
} else {
dump += INDENT2 "Windows: <none>\n";
@@ -4263,10 +4346,10 @@
dump += INDENT4;
entry->eventEntry->appendDescription(dump);
dump += StringPrintf(", targetFlags=0x%08x, resolvedAction=%d, "
- "age=%" PRId64 "ms, wait=%" PRId64 "ms\n",
+ "age=%" PRId64 "ms, wait=%" PRId64 "ms seq=%" PRIu32 "\n",
entry->targetFlags, entry->resolvedAction,
ns2ms(currentTime - entry->eventEntry->eventTime),
- ns2ms(currentTime - entry->deliveryTime));
+ ns2ms(currentTime - entry->deliveryTime), entry->seq);
}
} else {
dump += INDENT3 "WaitQueue: <empty>\n";
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 42583bc..824bbf5 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -49,6 +49,7 @@
#include <deque>
#include <optional>
#include <unordered_map>
+#include <unordered_set>
#include <InputListener.h>
#include <InputReporterInterface.h>
@@ -326,6 +327,11 @@
// Dispatcher state at time of last ANR.
std::string mLastAnrState GUARDED_BY(mLock);
+ // The connection tokens of the channels that the user last interacted, for debugging
+ std::unordered_set<sp<IBinder>, IBinderHash> mInteractionConnectionTokens GUARDED_BY(mLock);
+ void updateInteractionTokensLocked(const EventEntry& entry,
+ const std::vector<InputTarget>& targets) REQUIRES(mLock);
+
// Dispatch inbound events.
bool dispatchConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry)
REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 2baceba..81b3cf0 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -137,8 +137,7 @@
for (const TouchedWindow& window : windows) {
if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
if (haveSlipperyForegroundWindow ||
- !(window.windowHandle->getInfo()->layoutParamsFlags &
- InputWindowInfo::FLAG_SLIPPERY)) {
+ !window.windowHandle->getInfo()->flags.test(InputWindowInfo::Flag::SLIPPERY)) {
return false;
}
haveSlipperyForegroundWindow = true;
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 9b002f4..f25131c 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -18,15 +18,14 @@
#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H
#include <InputListener.h>
-#include <input/ISetInputWindowsListener.h>
+#include <android/os/ISetInputWindowsListener.h>
+#include <input/InputApplication.h>
+#include <input/InputTransport.h>
+#include <input/InputWindow.h>
#include <unordered_map>
namespace android {
-class InputApplicationHandle;
-class InputChannel;
-class InputWindowHandle;
-
/*
* Constants used to report the outcome of input event injection.
*/
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index 21255dd..c886bee 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -21,11 +21,11 @@
#include <binder/IBinder.h>
#include <input/Input.h>
+#include <input/InputApplication.h>
#include <utils/RefBase.h>
namespace android {
-class InputApplicationHandle;
/*
* Input dispatcher policy interface.
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
index b56f356..3496a24 100644
--- a/services/inputflinger/host/Android.bp
+++ b/services/inputflinger/host/Android.bp
@@ -59,9 +59,11 @@
shared_libs: [
"libbinder",
"libinputflingerhost",
- "libutils"
+ "libutils",
+ "libinput"
],
static_libs: [
"libarect",
+ "libui-types",
],
}
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index 683c05d..ff69800 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -217,8 +217,10 @@
idi.product = id->productId;
idi.version = id->version;
- std::string configFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
- idi, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
+ std::string configFile =
+ getInputDeviceConfigurationFilePathByDeviceIdentifier(idi,
+ InputDeviceConfigurationFileType::
+ CONFIGURATION);
if (configFile.empty()) {
ALOGD("No input device configuration file found for device '%s'.",
idi.name.c_str());
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index 973b4f9..9364a2a 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -22,13 +22,17 @@
#include "InputHost.h"
+#include <android/os/BnInputFlinger.h>
+#include <android/os/ISetInputWindowsListener.h>
+#include <binder/Binder.h>
#include <cutils/compiler.h>
-#include <input/IInputFlinger.h>
-#include <input/ISetInputWindowsListener.h>
-#include <utils/String8.h>
#include <utils/String16.h>
+#include <utils/String8.h>
#include <utils/StrongPointer.h>
+using android::os::BnInputFlinger;
+using android::os::ISetInputWindowsListener;
+
namespace android {
class InputFlinger : public BnInputFlinger {
@@ -40,10 +44,12 @@
InputFlinger() ANDROID_API;
virtual status_t dump(int fd, const Vector<String16>& args);
- void setInputWindows(const std::vector<InputWindowInfo>&,
- const sp<ISetInputWindowsListener>&) {}
- void registerInputChannel(const sp<InputChannel>&) {}
- void unregisterInputChannel(const sp<InputChannel>&) {}
+ binder::Status setInputWindows(const std::vector<InputWindowInfo>&,
+ 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(); }
private:
virtual ~InputFlinger();
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 83a610f..0ccada9 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -81,4 +81,7 @@
export_header_lib_headers: [
"libinputreader_headers",
],
+ static_libs: [
+ "libc++fs"
+ ],
}
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 18fcaed..5e590d0 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -34,20 +34,20 @@
#define LOG_TAG "EventHub"
// #define LOG_NDEBUG 0
-
-#include "EventHub.h"
-
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
+#include <input/KeyCharacterMap.h>
+#include <input/KeyLayoutMap.h>
+#include <input/VirtualKeyMap.h>
#include <openssl/sha.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/Timers.h>
#include <utils/threads.h>
-#include <input/KeyCharacterMap.h>
-#include <input/KeyLayoutMap.h>
-#include <input/VirtualKeyMap.h>
+#include <filesystem>
+
+#include "EventHub.h"
/* this macro is used to tell if "bit" is set in "array"
* it selects a byte from the array, and does a boolean AND
@@ -94,8 +94,8 @@
/**
* Return true if name matches "v4l-touch*"
*/
-static bool isV4lTouchNode(const char* name) {
- return strstr(name, "v4l-touch") == name;
+static bool isV4lTouchNode(std::string name) {
+ return name.find("v4l-touch") != std::string::npos;
}
/**
@@ -810,7 +810,7 @@
return index >= 0 ? mDevices.valueAt(index) : NULL;
}
-EventHub::Device* EventHub::getDeviceByPathLocked(const char* devicePath) const {
+EventHub::Device* EventHub::getDeviceByPathLocked(const std::string& devicePath) const {
for (size_t i = 0; i < mDevices.size(); i++) {
Device* device = mDevices.valueAt(i);
if (device->path == devicePath) {
@@ -1215,14 +1215,14 @@
}
}
-status_t EventHub::openDeviceLocked(const char* devicePath) {
+status_t EventHub::openDeviceLocked(const std::string& devicePath) {
char buffer[80];
- ALOGV("Opening device: %s", devicePath);
+ ALOGV("Opening device: %s", devicePath.c_str());
- int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+ int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
if (fd < 0) {
- ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
+ ALOGE("could not open %s, %s\n", devicePath.c_str(), strerror(errno));
return -1;
}
@@ -1230,7 +1230,7 @@
// Get device name.
if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
- ALOGE("Could not get device name for %s: %s", devicePath, strerror(errno));
+ ALOGE("Could not get device name for %s: %s", devicePath.c_str(), strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.name = buffer;
@@ -1240,7 +1240,7 @@
for (size_t i = 0; i < mExcludedDevices.size(); i++) {
const std::string& item = mExcludedDevices[i];
if (identifier.name == item) {
- ALOGI("ignoring event id %s driver %s\n", devicePath, item.c_str());
+ ALOGI("ignoring event id %s driver %s\n", devicePath.c_str(), item.c_str());
close(fd);
return -1;
}
@@ -1249,7 +1249,7 @@
// Get device driver version.
int driverVersion;
if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
- ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
+ ALOGE("could not get driver version for %s, %s\n", devicePath.c_str(), strerror(errno));
close(fd);
return -1;
}
@@ -1257,7 +1257,7 @@
// Get device identifier.
struct input_id inputId;
if (ioctl(fd, EVIOCGID, &inputId)) {
- ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
+ ALOGE("could not get device input id for %s, %s\n", devicePath.c_str(), strerror(errno));
close(fd);
return -1;
}
@@ -1289,7 +1289,7 @@
int32_t deviceId = mNextDeviceId++;
Device* device = new Device(fd, deviceId, devicePath, identifier);
- ALOGV("add device %d: %s\n", deviceId, devicePath);
+ ALOGV("add device %d: %s\n", deviceId, devicePath.c_str());
ALOGV(" bus: %04x\n"
" vendor %04x\n"
" product %04x\n"
@@ -1446,7 +1446,7 @@
// If the device isn't recognized as something we handle, don't monitor it.
if (device->classes == 0) {
- ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath,
+ ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(),
device->identifier.name.c_str());
delete device;
return -1;
@@ -1492,7 +1492,7 @@
ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
"configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
- deviceId, fd, devicePath, device->identifier.name.c_str(), device->classes,
+ deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(), device->classes,
device->configurationFile.c_str(), device->keyMap.keyLayoutFile.c_str(),
device->keyMap.keyCharacterMapFile.c_str(), toString(mBuiltInKeyboardId == deviceId));
@@ -1613,8 +1613,10 @@
}
void EventHub::loadConfigurationLocked(Device* device) {
- device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
- device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
+ device->configurationFile =
+ getInputDeviceConfigurationFilePathByDeviceIdentifier(device->identifier,
+ InputDeviceConfigurationFileType::
+ CONFIGURATION);
if (device->configurationFile.empty()) {
ALOGD("No input device configuration file found for device '%s'.",
device->identifier.name.c_str());
@@ -1724,13 +1726,13 @@
return NAME_NOT_FOUND;
}
-void EventHub::closeDeviceByPathLocked(const char* devicePath) {
+void EventHub::closeDeviceByPathLocked(const std::string& devicePath) {
Device* device = getDeviceByPathLocked(devicePath);
if (device) {
closeDeviceLocked(device);
return;
}
- ALOGV("Remove device: %s not found, device may already have been removed.", devicePath);
+ ALOGV("Remove device: %s not found, device may already have been removed.", devicePath.c_str());
}
/**
@@ -1835,16 +1837,16 @@
event = (struct inotify_event*)(event_buf + event_pos);
if (event->len) {
if (event->wd == mInputWd) {
- std::string filename = StringPrintf("%s/%s", DEVICE_PATH, event->name);
+ std::string filename = std::string(DEVICE_PATH) + "/" + event->name;
if (event->mask & IN_CREATE) {
- openDeviceLocked(filename.c_str());
+ openDeviceLocked(filename);
} else {
ALOGI("Removing device '%s' due to inotify event\n", filename.c_str());
- closeDeviceByPathLocked(filename.c_str());
+ closeDeviceByPathLocked(filename);
}
} else if (event->wd == mVideoWd) {
if (isV4lTouchNode(event->name)) {
- std::string filename = StringPrintf("%s/%s", VIDEO_DEVICE_PATH, event->name);
+ std::string filename = std::string(VIDEO_DEVICE_PATH) + "/" + event->name;
if (event->mask & IN_CREATE) {
openVideoDeviceLocked(filename);
} else {
@@ -1863,24 +1865,10 @@
return 0;
}
-status_t EventHub::scanDirLocked(const char* dirname) {
- char devname[PATH_MAX];
- char* filename;
- DIR* dir;
- struct dirent* de;
- dir = opendir(dirname);
- if (dir == nullptr) return -1;
- strcpy(devname, dirname);
- filename = devname + strlen(devname);
- *filename++ = '/';
- while ((de = readdir(dir))) {
- if (de->d_name[0] == '.' &&
- (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
- continue;
- strcpy(filename, de->d_name);
- openDeviceLocked(devname);
+status_t EventHub::scanDirLocked(const std::string& dirname) {
+ for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
+ openDeviceLocked(entry.path());
}
- closedir(dir);
return 0;
}
@@ -1888,22 +1876,12 @@
* Look for all dirname/v4l-touch* devices, and open them.
*/
status_t EventHub::scanVideoDirLocked(const std::string& dirname) {
- DIR* dir;
- struct dirent* de;
- dir = opendir(dirname.c_str());
- if (!dir) {
- ALOGE("Could not open video directory %s", dirname.c_str());
- return BAD_VALUE;
- }
-
- while ((de = readdir(dir))) {
- const char* name = de->d_name;
- if (isV4lTouchNode(name)) {
- ALOGI("Found touch video device %s", name);
- openVideoDeviceLocked(dirname + "/" + name);
+ for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
+ if (isV4lTouchNode(entry.path())) {
+ ALOGI("Found touch video device %s", entry.path().c_str());
+ openVideoDeviceLocked(entry.path());
}
}
- closedir(dir);
return OK;
}
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index c17f3a1..ee62c9a 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -373,13 +373,13 @@
}
};
- status_t openDeviceLocked(const char* devicePath);
+ status_t openDeviceLocked(const std::string& devicePath);
void openVideoDeviceLocked(const std::string& devicePath);
void createVirtualKeyboardLocked();
void addDeviceLocked(Device* device);
void assignDescriptorLocked(InputDeviceIdentifier& identifier);
- void closeDeviceByPathLocked(const char* devicePath);
+ void closeDeviceByPathLocked(const std::string& devicePath);
void closeVideoDeviceByPathLocked(const std::string& devicePath);
void closeDeviceLocked(Device* device);
void closeAllDevicesLocked();
@@ -396,14 +396,14 @@
status_t unregisterDeviceFromEpollLocked(Device* device);
void unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice);
- status_t scanDirLocked(const char* dirname);
+ status_t scanDirLocked(const std::string& dirname);
status_t scanVideoDirLocked(const std::string& dirname);
void scanDevicesLocked();
status_t readNotifyLocked();
Device* getDeviceByDescriptorLocked(const std::string& descriptor) const;
Device* getDeviceLocked(int32_t deviceId) const;
- Device* getDeviceByPathLocked(const char* devicePath) const;
+ Device* getDeviceByPathLocked(const std::string& devicePath) const;
/**
* Look through all available fd's (both for input devices and for video devices),
* and return the device pointer.
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 1a4d551..d1f20c7 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -14,7 +14,9 @@
* limitations under the License.
*/
+// clang-format off
#include "../Macros.h"
+// clang-format on
#include "CursorInputMapper.h"
@@ -184,7 +186,7 @@
mOrientation = DISPLAY_ORIENTATION_0;
if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
std::optional<DisplayViewport> internalViewport =
- config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ config->getDisplayViewportByType(ViewportType::INTERNAL);
if (internalViewport) {
mOrientation = internalViewport->orientation;
}
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index e009221..bd4232d 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -14,7 +14,9 @@
* limitations under the License.
*/
+// clang-format off
#include "../Macros.h"
+// clang-format on
#include "KeyboardInputMapper.h"
@@ -138,7 +140,7 @@
// No associated display defined, try to find default display if orientationAware.
if (mParameters.orientationAware) {
- return config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ return config->getDisplayViewportByType(ViewportType::INTERNAL);
}
return std::nullopt;
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
index 89ef41d..190282f 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
@@ -92,15 +92,15 @@
class MultiTouchInputMapper : public TouchInputMapper {
public:
explicit MultiTouchInputMapper(InputDeviceContext& deviceContext);
- virtual ~MultiTouchInputMapper();
+ ~MultiTouchInputMapper() override;
- virtual void reset(nsecs_t when) override;
- virtual void process(const RawEvent* rawEvent) override;
+ void reset(nsecs_t when) override;
+ void process(const RawEvent* rawEvent) override;
protected:
- virtual void syncTouch(nsecs_t when, RawState* outState);
- virtual void configureRawPointerAxes();
- virtual bool hasStylus() const;
+ void syncTouch(nsecs_t when, RawState* outState) override;
+ void configureRawPointerAxes() override;
+ bool hasStylus() const override;
private:
MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index 9885889..594ff42 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -14,7 +14,9 @@
* limitations under the License.
*/
+// clang-format off
#include "../Macros.h"
+// clang-format on
#include "RotaryEncoderInputMapper.h"
@@ -66,7 +68,7 @@
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
std::optional<DisplayViewport> internalViewport =
- config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ config->getDisplayViewportByType(ViewportType::INTERNAL);
if (internalViewport) {
mOrientation = internalViewport->orientation;
} else {
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
index f5befb3..9cb3f67 100644
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
@@ -25,15 +25,15 @@
class SingleTouchInputMapper : public TouchInputMapper {
public:
explicit SingleTouchInputMapper(InputDeviceContext& deviceContext);
- virtual ~SingleTouchInputMapper();
+ ~SingleTouchInputMapper() override;
- virtual void reset(nsecs_t when) override;
- virtual void process(const RawEvent* rawEvent) override;
+ void reset(nsecs_t when) override;
+ void process(const RawEvent* rawEvent) override;
protected:
- virtual void syncTouch(nsecs_t when, RawState* outState);
- virtual void configureRawPointerAxes();
- virtual bool hasStylus() const;
+ void syncTouch(nsecs_t when, RawState* outState) override;
+ void configureRawPointerAxes() override;
+ bool hasStylus() const override;
private:
SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index efdc84f..4274ca8 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -14,7 +14,9 @@
* limitations under the License.
*/
+// clang-format off
#include "../Macros.h"
+// clang-format on
#include "TouchInputMapper.h"
@@ -159,7 +161,7 @@
TouchInputMapper::TouchInputMapper(InputDeviceContext& deviceContext)
: InputMapper(deviceContext),
mSource(0),
- mDeviceMode(DEVICE_MODE_DISABLED),
+ mDeviceMode(DeviceMode::DISABLED),
mRawSurfaceWidth(-1),
mRawSurfaceHeight(-1),
mSurfaceLeft(0),
@@ -179,7 +181,7 @@
void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
InputMapper::populateDeviceInfo(info);
- if (mDeviceMode != DEVICE_MODE_DISABLED) {
+ if (mDeviceMode != DeviceMode::DISABLED) {
info->addMotionRange(mOrientedRanges.x);
info->addMotionRange(mOrientedRanges.y);
info->addMotionRange(mOrientedRanges.pressure);
@@ -218,7 +220,7 @@
info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
0.0f);
}
- if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
+ if (mCalibration.coverageCalibration == Calibration::CoverageCalibration::BOX) {
const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
@@ -311,7 +313,7 @@
dump += INDENT3 "External Stylus State:\n";
dumpStylusState(dump, mExternalStylusState);
- if (mDeviceMode == DEVICE_MODE_POINTER) {
+ if (mDeviceMode == DeviceMode::POINTER) {
dump += StringPrintf(INDENT3 "Pointer Gesture Detector:\n");
dump += StringPrintf(INDENT4 "XMovementScale: %0.3f\n", mPointerXMovementScale);
dump += StringPrintf(INDENT4 "YMovementScale: %0.3f\n", mPointerYMovementScale);
@@ -323,15 +325,15 @@
const char* TouchInputMapper::modeToString(DeviceMode deviceMode) {
switch (deviceMode) {
- case DEVICE_MODE_DISABLED:
+ case DeviceMode::DISABLED:
return "disabled";
- case DEVICE_MODE_DIRECT:
+ case DeviceMode::DIRECT:
return "direct";
- case DEVICE_MODE_UNSCALED:
+ case DeviceMode::UNSCALED:
return "unscaled";
- case DEVICE_MODE_NAVIGATION:
+ case DeviceMode::NAVIGATION:
return "navigation";
- case DEVICE_MODE_POINTER:
+ case DeviceMode::POINTER:
return "pointer";
}
return "unknown";
@@ -406,16 +408,16 @@
// multitouch. The spot-based presentation relies on being able to accurately
// locate two or more fingers on the touch pad.
mParameters.gestureMode = getDeviceContext().hasInputProperty(INPUT_PROP_SEMI_MT)
- ? Parameters::GESTURE_MODE_SINGLE_TOUCH
- : Parameters::GESTURE_MODE_MULTI_TOUCH;
+ ? Parameters::GestureMode::SINGLE_TOUCH
+ : Parameters::GestureMode::MULTI_TOUCH;
String8 gestureModeString;
if (getDeviceContext().getConfiguration().tryGetProperty(String8("touch.gestureMode"),
gestureModeString)) {
if (gestureModeString == "single-touch") {
- mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH;
+ mParameters.gestureMode = Parameters::GestureMode::SINGLE_TOUCH;
} else if (gestureModeString == "multi-touch") {
- mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH;
+ mParameters.gestureMode = Parameters::GestureMode::MULTI_TOUCH;
} else if (gestureModeString != "default") {
ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
}
@@ -423,18 +425,18 @@
if (getDeviceContext().hasInputProperty(INPUT_PROP_DIRECT)) {
// The device is a touch screen.
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+ mParameters.deviceType = Parameters::DeviceType::TOUCH_SCREEN;
} else if (getDeviceContext().hasInputProperty(INPUT_PROP_POINTER)) {
// The device is a pointing device like a track pad.
- mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
+ mParameters.deviceType = Parameters::DeviceType::POINTER;
} else if (getDeviceContext().hasRelativeAxis(REL_X) ||
getDeviceContext().hasRelativeAxis(REL_Y)) {
// The device is a cursor device with a touch pad attached.
// By default don't use the touch pad to move the pointer.
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
+ mParameters.deviceType = Parameters::DeviceType::TOUCH_PAD;
} else {
// The device is a touch pad of unknown purpose.
- mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
+ mParameters.deviceType = Parameters::DeviceType::POINTER;
}
mParameters.hasButtonUnderPad = getDeviceContext().hasInputProperty(INPUT_PROP_BUTTONPAD);
@@ -443,29 +445,29 @@
if (getDeviceContext().getConfiguration().tryGetProperty(String8("touch.deviceType"),
deviceTypeString)) {
if (deviceTypeString == "touchScreen") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+ mParameters.deviceType = Parameters::DeviceType::TOUCH_SCREEN;
} else if (deviceTypeString == "touchPad") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
+ mParameters.deviceType = Parameters::DeviceType::TOUCH_PAD;
} else if (deviceTypeString == "touchNavigation") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
+ mParameters.deviceType = Parameters::DeviceType::TOUCH_NAVIGATION;
} else if (deviceTypeString == "pointer") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
+ mParameters.deviceType = Parameters::DeviceType::POINTER;
} else if (deviceTypeString != "default") {
ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
}
}
- mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+ mParameters.orientationAware = mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN;
getDeviceContext().getConfiguration().tryGetProperty(String8("touch.orientationAware"),
mParameters.orientationAware);
mParameters.hasAssociatedDisplay = false;
mParameters.associatedDisplayIsExternal = false;
if (mParameters.orientationAware ||
- mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN ||
- mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
+ mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN ||
+ mParameters.deviceType == Parameters::DeviceType::POINTER) {
mParameters.hasAssociatedDisplay = true;
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
+ if (mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN) {
mParameters.associatedDisplayIsExternal = getDeviceContext().isExternal();
String8 uniqueDisplayId;
getDeviceContext().getConfiguration().tryGetProperty(String8("touch.displayId"),
@@ -488,10 +490,10 @@
dump += INDENT3 "Parameters:\n";
switch (mParameters.gestureMode) {
- case Parameters::GESTURE_MODE_SINGLE_TOUCH:
+ case Parameters::GestureMode::SINGLE_TOUCH:
dump += INDENT4 "GestureMode: single-touch\n";
break;
- case Parameters::GESTURE_MODE_MULTI_TOUCH:
+ case Parameters::GestureMode::MULTI_TOUCH:
dump += INDENT4 "GestureMode: multi-touch\n";
break;
default:
@@ -499,16 +501,16 @@
}
switch (mParameters.deviceType) {
- case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
+ case Parameters::DeviceType::TOUCH_SCREEN:
dump += INDENT4 "DeviceType: touchScreen\n";
break;
- case Parameters::DEVICE_TYPE_TOUCH_PAD:
+ case Parameters::DeviceType::TOUCH_PAD:
dump += INDENT4 "DeviceType: touchPad\n";
break;
- case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
+ case Parameters::DeviceType::TOUCH_NAVIGATION:
dump += INDENT4 "DeviceType: touchNavigation\n";
break;
- case Parameters::DEVICE_TYPE_POINTER:
+ case Parameters::DeviceType::POINTER:
dump += INDENT4 "DeviceType: pointer\n";
break;
default:
@@ -565,7 +567,7 @@
return getDeviceContext().getAssociatedViewport();
}
- if (mDeviceMode == DEVICE_MODE_POINTER) {
+ if (mDeviceMode == DeviceMode::POINTER) {
std::optional<DisplayViewport> viewport =
mConfig.getDisplayViewportById(mConfig.defaultPointerDisplayId);
if (viewport) {
@@ -583,18 +585,18 @@
ViewportType viewportTypeToUse;
if (mParameters.associatedDisplayIsExternal) {
- viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
+ viewportTypeToUse = ViewportType::EXTERNAL;
} else {
- viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
+ viewportTypeToUse = ViewportType::INTERNAL;
}
std::optional<DisplayViewport> viewport =
mConfig.getDisplayViewportByType(viewportTypeToUse);
- if (!viewport && viewportTypeToUse == ViewportType::VIEWPORT_EXTERNAL) {
+ if (!viewport && viewportTypeToUse == ViewportType::EXTERNAL) {
ALOGW("Input device %s should be associated with external display, "
"fallback to internal one for the external viewport is not found.",
getDeviceName().c_str());
- viewport = mConfig.getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ viewport = mConfig.getDisplayViewportByType(ViewportType::INTERNAL);
}
return viewport;
@@ -610,34 +612,34 @@
}
void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
- int32_t oldDeviceMode = mDeviceMode;
+ DeviceMode oldDeviceMode = mDeviceMode;
resolveExternalStylusPresence();
// Determine device mode.
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER &&
+ if (mParameters.deviceType == Parameters::DeviceType::POINTER &&
mConfig.pointerGesturesEnabled) {
mSource = AINPUT_SOURCE_MOUSE;
- mDeviceMode = DEVICE_MODE_POINTER;
+ mDeviceMode = DeviceMode::POINTER;
if (hasStylus()) {
mSource |= AINPUT_SOURCE_STYLUS;
}
- } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN &&
+ } else if (mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN &&
mParameters.hasAssociatedDisplay) {
mSource = AINPUT_SOURCE_TOUCHSCREEN;
- mDeviceMode = DEVICE_MODE_DIRECT;
+ mDeviceMode = DeviceMode::DIRECT;
if (hasStylus()) {
mSource |= AINPUT_SOURCE_STYLUS;
}
if (hasExternalStylus()) {
mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
}
- } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
+ } else if (mParameters.deviceType == Parameters::DeviceType::TOUCH_NAVIGATION) {
mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
- mDeviceMode = DEVICE_MODE_NAVIGATION;
+ mDeviceMode = DeviceMode::NAVIGATION;
} else {
mSource = AINPUT_SOURCE_TOUCHPAD;
- mDeviceMode = DEVICE_MODE_UNSCALED;
+ mDeviceMode = DeviceMode::UNSCALED;
}
// Ensure we have valid X and Y axes.
@@ -645,7 +647,7 @@
ALOGW("Touch device '%s' did not report support for X or Y axis! "
"The device will be inoperable.",
getDeviceName().c_str());
- mDeviceMode = DEVICE_MODE_DISABLED;
+ mDeviceMode = DeviceMode::DISABLED;
return;
}
@@ -656,7 +658,7 @@
"display. The device will be inoperable until the display size "
"becomes available.",
getDeviceName().c_str());
- mDeviceMode = DEVICE_MODE_DISABLED;
+ mDeviceMode = DeviceMode::DISABLED;
return;
}
@@ -668,7 +670,7 @@
if (viewportChanged) {
mViewport = *newViewport;
- if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
+ if (mDeviceMode == DeviceMode::DIRECT || mDeviceMode == DeviceMode::POINTER) {
// Convert rotated viewport to natural surface coordinates.
int32_t naturalLogicalWidth, naturalLogicalHeight;
int32_t naturalPhysicalWidth, naturalPhysicalHeight;
@@ -759,8 +761,8 @@
}
// Create pointer controller if needed.
- if (mDeviceMode == DEVICE_MODE_POINTER ||
- (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
+ if (mDeviceMode == DeviceMode::POINTER ||
+ (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches)) {
if (mPointerController == nullptr) {
mPointerController = getContext()->getPointerController(getDeviceId());
}
@@ -798,7 +800,7 @@
float diagonalSize = hypotf(mRawSurfaceWidth, mRawSurfaceHeight);
// Size factors.
- if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
+ if (mCalibration.sizeCalibration != Calibration::SizeCalibration::NONE) {
if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.touchMajor.maxValue != 0) {
mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
} else if (mRawPointerAxes.toolMajor.valid && mRawPointerAxes.toolMajor.maxValue != 0) {
@@ -847,8 +849,8 @@
// Pressure factors.
mPressureScale = 0;
float pressureMax = 1.0;
- if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL ||
- mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
+ if (mCalibration.pressureCalibration == Calibration::PressureCalibration::PHYSICAL ||
+ mCalibration.pressureCalibration == Calibration::PressureCalibration::AMPLITUDE) {
if (mCalibration.havePressureScale) {
mPressureScale = mCalibration.pressureScale;
pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue;
@@ -901,9 +903,9 @@
mOrientedRanges.orientation.fuzz = 0;
mOrientedRanges.orientation.resolution = 0;
} else if (mCalibration.orientationCalibration !=
- Calibration::ORIENTATION_CALIBRATION_NONE) {
+ Calibration::OrientationCalibration::NONE) {
if (mCalibration.orientationCalibration ==
- Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
+ Calibration::OrientationCalibration::INTERPOLATED) {
if (mRawPointerAxes.orientation.valid) {
if (mRawPointerAxes.orientation.maxValue > 0) {
mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
@@ -928,8 +930,8 @@
// Distance
mDistanceScale = 0;
- if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
- if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_SCALED) {
+ if (mCalibration.distanceCalibration != Calibration::DistanceCalibration::NONE) {
+ if (mCalibration.distanceCalibration == Calibration::DistanceCalibration::SCALED) {
if (mCalibration.haveDistanceScale) {
mDistanceScale = mCalibration.distanceScale;
} else {
@@ -991,7 +993,7 @@
// Location
updateAffineTransformation();
- if (mDeviceMode == DEVICE_MODE_POINTER) {
+ if (mDeviceMode == DeviceMode::POINTER) {
// Compute pointer gesture detection parameters.
float rawDiagonal = hypotf(rawWidth, rawHeight);
float displayDiagonal = hypotf(mRawSurfaceWidth, mRawSurfaceHeight);
@@ -1112,19 +1114,19 @@
Calibration& out = mCalibration;
// Size
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
+ out.sizeCalibration = Calibration::SizeCalibration::DEFAULT;
String8 sizeCalibrationString;
if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
if (sizeCalibrationString == "none") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
+ out.sizeCalibration = Calibration::SizeCalibration::NONE;
} else if (sizeCalibrationString == "geometric") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
+ out.sizeCalibration = Calibration::SizeCalibration::GEOMETRIC;
} else if (sizeCalibrationString == "diameter") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
+ out.sizeCalibration = Calibration::SizeCalibration::DIAMETER;
} else if (sizeCalibrationString == "box") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
+ out.sizeCalibration = Calibration::SizeCalibration::BOX;
} else if (sizeCalibrationString == "area") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
+ out.sizeCalibration = Calibration::SizeCalibration::AREA;
} else if (sizeCalibrationString != "default") {
ALOGW("Invalid value for touch.size.calibration: '%s'", sizeCalibrationString.string());
}
@@ -1135,15 +1137,15 @@
out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"), out.sizeIsSummed);
// Pressure
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
+ out.pressureCalibration = Calibration::PressureCalibration::DEFAULT;
String8 pressureCalibrationString;
if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
if (pressureCalibrationString == "none") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
+ out.pressureCalibration = Calibration::PressureCalibration::NONE;
} else if (pressureCalibrationString == "physical") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
+ out.pressureCalibration = Calibration::PressureCalibration::PHYSICAL;
} else if (pressureCalibrationString == "amplitude") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
+ out.pressureCalibration = Calibration::PressureCalibration::AMPLITUDE;
} else if (pressureCalibrationString != "default") {
ALOGW("Invalid value for touch.pressure.calibration: '%s'",
pressureCalibrationString.string());
@@ -1153,15 +1155,15 @@
out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"), out.pressureScale);
// Orientation
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
+ out.orientationCalibration = Calibration::OrientationCalibration::DEFAULT;
String8 orientationCalibrationString;
if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
if (orientationCalibrationString == "none") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
+ out.orientationCalibration = Calibration::OrientationCalibration::NONE;
} else if (orientationCalibrationString == "interpolated") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
+ out.orientationCalibration = Calibration::OrientationCalibration::INTERPOLATED;
} else if (orientationCalibrationString == "vector") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
+ out.orientationCalibration = Calibration::OrientationCalibration::VECTOR;
} else if (orientationCalibrationString != "default") {
ALOGW("Invalid value for touch.orientation.calibration: '%s'",
orientationCalibrationString.string());
@@ -1169,13 +1171,13 @@
}
// Distance
- out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
+ out.distanceCalibration = Calibration::DistanceCalibration::DEFAULT;
String8 distanceCalibrationString;
if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
if (distanceCalibrationString == "none") {
- out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
+ out.distanceCalibration = Calibration::DistanceCalibration::NONE;
} else if (distanceCalibrationString == "scaled") {
- out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
+ out.distanceCalibration = Calibration::DistanceCalibration::SCALED;
} else if (distanceCalibrationString != "default") {
ALOGW("Invalid value for touch.distance.calibration: '%s'",
distanceCalibrationString.string());
@@ -1184,13 +1186,13 @@
out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"), out.distanceScale);
- out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
+ out.coverageCalibration = Calibration::CoverageCalibration::DEFAULT;
String8 coverageCalibrationString;
if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
if (coverageCalibrationString == "none") {
- out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
+ out.coverageCalibration = Calibration::CoverageCalibration::NONE;
} else if (coverageCalibrationString == "box") {
- out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
+ out.coverageCalibration = Calibration::CoverageCalibration::BOX;
} else if (coverageCalibrationString != "default") {
ALOGW("Invalid value for touch.coverage.calibration: '%s'",
coverageCalibrationString.string());
@@ -1201,43 +1203,43 @@
void TouchInputMapper::resolveCalibration() {
// Size
if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
- if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
- mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
+ if (mCalibration.sizeCalibration == Calibration::SizeCalibration::DEFAULT) {
+ mCalibration.sizeCalibration = Calibration::SizeCalibration::GEOMETRIC;
}
} else {
- mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
+ mCalibration.sizeCalibration = Calibration::SizeCalibration::NONE;
}
// Pressure
if (mRawPointerAxes.pressure.valid) {
- if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
- mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
+ if (mCalibration.pressureCalibration == Calibration::PressureCalibration::DEFAULT) {
+ mCalibration.pressureCalibration = Calibration::PressureCalibration::PHYSICAL;
}
} else {
- mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
+ mCalibration.pressureCalibration = Calibration::PressureCalibration::NONE;
}
// Orientation
if (mRawPointerAxes.orientation.valid) {
- if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
- mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
+ if (mCalibration.orientationCalibration == Calibration::OrientationCalibration::DEFAULT) {
+ mCalibration.orientationCalibration = Calibration::OrientationCalibration::INTERPOLATED;
}
} else {
- mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
+ mCalibration.orientationCalibration = Calibration::OrientationCalibration::NONE;
}
// Distance
if (mRawPointerAxes.distance.valid) {
- if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
- mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
+ if (mCalibration.distanceCalibration == Calibration::DistanceCalibration::DEFAULT) {
+ mCalibration.distanceCalibration = Calibration::DistanceCalibration::SCALED;
}
} else {
- mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
+ mCalibration.distanceCalibration = Calibration::DistanceCalibration::NONE;
}
// Coverage
- if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
- mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
+ if (mCalibration.coverageCalibration == Calibration::CoverageCalibration::DEFAULT) {
+ mCalibration.coverageCalibration = Calibration::CoverageCalibration::NONE;
}
}
@@ -1246,19 +1248,19 @@
// Size
switch (mCalibration.sizeCalibration) {
- case Calibration::SIZE_CALIBRATION_NONE:
+ case Calibration::SizeCalibration::NONE:
dump += INDENT4 "touch.size.calibration: none\n";
break;
- case Calibration::SIZE_CALIBRATION_GEOMETRIC:
+ case Calibration::SizeCalibration::GEOMETRIC:
dump += INDENT4 "touch.size.calibration: geometric\n";
break;
- case Calibration::SIZE_CALIBRATION_DIAMETER:
+ case Calibration::SizeCalibration::DIAMETER:
dump += INDENT4 "touch.size.calibration: diameter\n";
break;
- case Calibration::SIZE_CALIBRATION_BOX:
+ case Calibration::SizeCalibration::BOX:
dump += INDENT4 "touch.size.calibration: box\n";
break;
- case Calibration::SIZE_CALIBRATION_AREA:
+ case Calibration::SizeCalibration::AREA:
dump += INDENT4 "touch.size.calibration: area\n";
break;
default:
@@ -1280,13 +1282,13 @@
// Pressure
switch (mCalibration.pressureCalibration) {
- case Calibration::PRESSURE_CALIBRATION_NONE:
+ case Calibration::PressureCalibration::NONE:
dump += INDENT4 "touch.pressure.calibration: none\n";
break;
- case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
+ case Calibration::PressureCalibration::PHYSICAL:
dump += INDENT4 "touch.pressure.calibration: physical\n";
break;
- case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
+ case Calibration::PressureCalibration::AMPLITUDE:
dump += INDENT4 "touch.pressure.calibration: amplitude\n";
break;
default:
@@ -1299,13 +1301,13 @@
// Orientation
switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_NONE:
+ case Calibration::OrientationCalibration::NONE:
dump += INDENT4 "touch.orientation.calibration: none\n";
break;
- case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
+ case Calibration::OrientationCalibration::INTERPOLATED:
dump += INDENT4 "touch.orientation.calibration: interpolated\n";
break;
- case Calibration::ORIENTATION_CALIBRATION_VECTOR:
+ case Calibration::OrientationCalibration::VECTOR:
dump += INDENT4 "touch.orientation.calibration: vector\n";
break;
default:
@@ -1314,10 +1316,10 @@
// Distance
switch (mCalibration.distanceCalibration) {
- case Calibration::DISTANCE_CALIBRATION_NONE:
+ case Calibration::DistanceCalibration::NONE:
dump += INDENT4 "touch.distance.calibration: none\n";
break;
- case Calibration::DISTANCE_CALIBRATION_SCALED:
+ case Calibration::DistanceCalibration::SCALED:
dump += INDENT4 "touch.distance.calibration: scaled\n";
break;
default:
@@ -1329,10 +1331,10 @@
}
switch (mCalibration.coverageCalibration) {
- case Calibration::COVERAGE_CALIBRATION_NONE:
+ case Calibration::CoverageCalibration::NONE:
dump += INDENT4 "touch.coverage.calibration: none\n";
break;
- case Calibration::COVERAGE_CALIBRATION_BOX:
+ case Calibration::CoverageCalibration::BOX:
dump += INDENT4 "touch.coverage.calibration: box\n";
break;
default:
@@ -1370,7 +1372,7 @@
mCurrentCookedState.clear();
mLastRawState.clear();
mLastCookedState.clear();
- mPointerUsage = POINTER_USAGE_NONE;
+ mPointerUsage = PointerUsage::NONE;
mSentHoverEnter = false;
mHavePointerIds = false;
mCurrentMotionAborted = false;
@@ -1452,7 +1454,7 @@
}
void TouchInputMapper::processRawTouches(bool timeout) {
- if (mDeviceMode == DEVICE_MODE_DISABLED) {
+ if (mDeviceMode == DeviceMode::DISABLED) {
// Drop all input if the device is disabled.
mCurrentRawState.clear();
mRawStatesPending.clear();
@@ -1517,7 +1519,7 @@
bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
if (initialDown || buttonsPressed) {
// If this is a touch screen, hide the pointer on an initial down.
- if (mDeviceMode == DEVICE_MODE_DIRECT) {
+ if (mDeviceMode == DeviceMode::DIRECT) {
getContext()->fadePointer();
}
@@ -1546,7 +1548,7 @@
mCurrentCookedState.buttonState);
// Dispatch the touches either directly or by translation through a pointer on screen.
- if (mDeviceMode == DEVICE_MODE_POINTER) {
+ if (mDeviceMode == DeviceMode::POINTER) {
for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits); !idBits.isEmpty();) {
uint32_t id = idBits.clearFirstMarkedBit();
const RawPointerData::Pointer& pointer =
@@ -1576,18 +1578,18 @@
if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
mCurrentCookedState.mouseIdBits.clear();
mCurrentCookedState.fingerIdBits.clear();
- pointerUsage = POINTER_USAGE_STYLUS;
+ pointerUsage = PointerUsage::STYLUS;
} else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
mCurrentCookedState.fingerIdBits.clear();
- pointerUsage = POINTER_USAGE_MOUSE;
+ pointerUsage = PointerUsage::MOUSE;
} else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
isPointerDown(mCurrentRawState.buttonState)) {
- pointerUsage = POINTER_USAGE_GESTURES;
+ pointerUsage = PointerUsage::GESTURES;
}
dispatchPointerUsage(when, policyFlags, pointerUsage);
} else {
- if (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches &&
+ if (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches &&
mPointerController != nullptr) {
mPointerController->setPresentation(PointerControllerInterface::Presentation::SPOT);
mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
@@ -1627,7 +1629,7 @@
}
void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
- if (mDeviceMode == DEVICE_MODE_DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
+ if (mDeviceMode == DeviceMode::DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
mCurrentRawState.buttonState |= mExternalStylusState.buttons;
}
}
@@ -1654,7 +1656,7 @@
}
bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
- if (mDeviceMode != DEVICE_MODE_DIRECT || !hasExternalStylus()) {
+ if (mDeviceMode != DeviceMode::DIRECT || !hasExternalStylus()) {
return false;
}
@@ -1697,11 +1699,11 @@
}
void TouchInputMapper::timeoutExpired(nsecs_t when) {
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- if (mPointerUsage == POINTER_USAGE_GESTURES) {
+ if (mDeviceMode == DeviceMode::POINTER) {
+ if (mPointerUsage == PointerUsage::GESTURES) {
dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
}
- } else if (mDeviceMode == DEVICE_MODE_DIRECT) {
+ } else if (mDeviceMode == DeviceMode::DIRECT) {
if (mExternalStylusFusionTimeout < when) {
processRawTouches(true /*timeout*/);
} else if (mExternalStylusFusionTimeout != LLONG_MAX) {
@@ -2038,10 +2040,10 @@
// Size
float touchMajor, touchMinor, toolMajor, toolMinor, size;
switch (mCalibration.sizeCalibration) {
- case Calibration::SIZE_CALIBRATION_GEOMETRIC:
- case Calibration::SIZE_CALIBRATION_DIAMETER:
- case Calibration::SIZE_CALIBRATION_BOX:
- case Calibration::SIZE_CALIBRATION_AREA:
+ case Calibration::SizeCalibration::GEOMETRIC:
+ case Calibration::SizeCalibration::DIAMETER:
+ case Calibration::SizeCalibration::BOX:
+ case Calibration::SizeCalibration::AREA:
if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
touchMajor = in.touchMajor;
touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
@@ -2083,17 +2085,17 @@
}
}
- if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
+ if (mCalibration.sizeCalibration == Calibration::SizeCalibration::GEOMETRIC) {
touchMajor *= mGeometricScale;
touchMinor *= mGeometricScale;
toolMajor *= mGeometricScale;
toolMinor *= mGeometricScale;
- } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
+ } else if (mCalibration.sizeCalibration == Calibration::SizeCalibration::AREA) {
touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
touchMinor = touchMajor;
toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
toolMinor = toolMajor;
- } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
+ } else if (mCalibration.sizeCalibration == Calibration::SizeCalibration::DIAMETER) {
touchMinor = touchMajor;
toolMinor = toolMajor;
}
@@ -2116,8 +2118,8 @@
// Pressure
float pressure;
switch (mCalibration.pressureCalibration) {
- case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
- case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
+ case Calibration::PressureCalibration::PHYSICAL:
+ case Calibration::PressureCalibration::AMPLITUDE:
pressure = in.pressure * mPressureScale;
break;
default:
@@ -2137,10 +2139,10 @@
tilt = 0;
switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
+ case Calibration::OrientationCalibration::INTERPOLATED:
orientation = in.orientation * mOrientationScale;
break;
- case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
+ case Calibration::OrientationCalibration::VECTOR: {
int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
int32_t c2 = signExtendNybble(in.orientation & 0x0f);
if (c1 != 0 || c2 != 0) {
@@ -2164,7 +2166,7 @@
// Distance
float distance;
switch (mCalibration.distanceCalibration) {
- case Calibration::DISTANCE_CALIBRATION_SCALED:
+ case Calibration::DistanceCalibration::SCALED:
distance = in.distance * mDistanceScale;
break;
default:
@@ -2174,7 +2176,7 @@
// Coverage
int32_t rawLeft, rawTop, rawRight, rawBottom;
switch (mCalibration.coverageCalibration) {
- case Calibration::COVERAGE_CALIBRATION_BOX:
+ case Calibration::CoverageCalibration::BOX:
rawLeft = (in.toolMinor & 0xffff0000) >> 16;
rawRight = in.toolMinor & 0x0000ffff;
rawBottom = in.toolMajor & 0x0000ffff;
@@ -2251,7 +2253,7 @@
out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
- if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
+ if (mCalibration.coverageCalibration == Calibration::CoverageCalibration::BOX) {
out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
@@ -2281,36 +2283,36 @@
}
switch (mPointerUsage) {
- case POINTER_USAGE_GESTURES:
+ case PointerUsage::GESTURES:
dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
break;
- case POINTER_USAGE_STYLUS:
+ case PointerUsage::STYLUS:
dispatchPointerStylus(when, policyFlags);
break;
- case POINTER_USAGE_MOUSE:
+ case PointerUsage::MOUSE:
dispatchPointerMouse(when, policyFlags);
break;
- default:
+ case PointerUsage::NONE:
break;
}
}
void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
switch (mPointerUsage) {
- case POINTER_USAGE_GESTURES:
+ case PointerUsage::GESTURES:
abortPointerGestures(when, policyFlags);
break;
- case POINTER_USAGE_STYLUS:
+ case PointerUsage::STYLUS:
abortPointerStylus(when, policyFlags);
break;
- case POINTER_USAGE_MOUSE:
+ case PointerUsage::MOUSE:
abortPointerMouse(when, policyFlags);
break;
- default:
+ case PointerUsage::NONE:
break;
}
- mPointerUsage = POINTER_USAGE_NONE;
+ mPointerUsage = PointerUsage::NONE;
}
void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout) {
@@ -2326,13 +2328,13 @@
}
// Update the pointer presentation and spots.
- if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
+ if (mParameters.gestureMode == Parameters::GestureMode::MULTI_TOUCH) {
mPointerController->setPresentation(PointerControllerInterface::Presentation::POINTER);
if (finishPreviousGesture || cancelPreviousGesture) {
mPointerController->clearSpots();
}
- if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
+ if (mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM) {
mPointerController->setSpots(mPointerGesture.currentGestureCoords,
mPointerGesture.currentGestureIdToIndex,
mPointerGesture.currentGestureIdBits,
@@ -2344,28 +2346,28 @@
// Show or hide the pointer if needed.
switch (mPointerGesture.currentGestureMode) {
- case PointerGesture::NEUTRAL:
- case PointerGesture::QUIET:
- if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH &&
- mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) {
+ case PointerGesture::Mode::NEUTRAL:
+ case PointerGesture::Mode::QUIET:
+ if (mParameters.gestureMode == Parameters::GestureMode::MULTI_TOUCH &&
+ mPointerGesture.lastGestureMode == PointerGesture::Mode::FREEFORM) {
// Remind the user of where the pointer is after finishing a gesture with spots.
mPointerController->unfade(PointerControllerInterface::Transition::GRADUAL);
}
break;
- case PointerGesture::TAP:
- case PointerGesture::TAP_DRAG:
- case PointerGesture::BUTTON_CLICK_OR_DRAG:
- case PointerGesture::HOVER:
- case PointerGesture::PRESS:
- case PointerGesture::SWIPE:
+ case PointerGesture::Mode::TAP:
+ case PointerGesture::Mode::TAP_DRAG:
+ case PointerGesture::Mode::BUTTON_CLICK_OR_DRAG:
+ case PointerGesture::Mode::HOVER:
+ case PointerGesture::Mode::PRESS:
+ case PointerGesture::Mode::SWIPE:
// Unfade the pointer when the current gesture manipulates the
// area directly under the pointer.
mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
break;
- case PointerGesture::FREEFORM:
+ case PointerGesture::Mode::FREEFORM:
// Fade the pointer when the current gesture manipulates a different
// area and there are spots to guide the user experience.
- if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
+ if (mParameters.gestureMode == Parameters::GestureMode::MULTI_TOUCH) {
mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
} else {
mPointerController->unfade(PointerControllerInterface::Transition::IMMEDIATE);
@@ -2379,12 +2381,12 @@
// Update last coordinates of pointers that have moved so that we observe the new
// pointer positions at the same time as other pointers that have just gone up.
- bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP ||
- mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG ||
- mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG ||
- mPointerGesture.currentGestureMode == PointerGesture::PRESS ||
- mPointerGesture.currentGestureMode == PointerGesture::SWIPE ||
- mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
+ bool down = mPointerGesture.currentGestureMode == PointerGesture::Mode::TAP ||
+ mPointerGesture.currentGestureMode == PointerGesture::Mode::TAP_DRAG ||
+ mPointerGesture.currentGestureMode == PointerGesture::Mode::BUTTON_CLICK_OR_DRAG ||
+ mPointerGesture.currentGestureMode == PointerGesture::Mode::PRESS ||
+ mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE ||
+ mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM;
bool moveNeeded = false;
if (down && !cancelPreviousGesture && !finishPreviousGesture &&
!mPointerGesture.lastGestureIdBits.isEmpty() &&
@@ -2467,7 +2469,7 @@
}
// Send motion events for hover.
- if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
+ if (mPointerGesture.currentGestureMode == PointerGesture::Mode::HOVER) {
dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.currentGestureProperties,
@@ -2553,7 +2555,7 @@
ALOGD("Gestures: Processing timeout");
#endif
- if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
+ if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP) {
if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
// The tap/drag timeout has not yet expired.
getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime +
@@ -2566,7 +2568,7 @@
*outFinishPreviousGesture = true;
mPointerGesture.activeGestureId = -1;
- mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::NEUTRAL;
mPointerGesture.currentGestureIdBits.clear();
mPointerVelocityControl.reset();
@@ -2598,9 +2600,9 @@
// If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
// to NEUTRAL, then we should not generate tap event.
- if (mPointerGesture.lastGestureMode != PointerGesture::HOVER &&
- mPointerGesture.lastGestureMode != PointerGesture::TAP &&
- mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
+ if (mPointerGesture.lastGestureMode != PointerGesture::Mode::HOVER &&
+ mPointerGesture.lastGestureMode != PointerGesture::Mode::TAP &&
+ mPointerGesture.lastGestureMode != PointerGesture::Mode::TAP_DRAG) {
mPointerGesture.resetTap();
}
@@ -2633,15 +2635,16 @@
} else {
isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
if (!isQuietTime) {
- if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS ||
- mPointerGesture.lastGestureMode == PointerGesture::SWIPE ||
- mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) &&
+ if ((mPointerGesture.lastGestureMode == PointerGesture::Mode::PRESS ||
+ mPointerGesture.lastGestureMode == PointerGesture::Mode::SWIPE ||
+ mPointerGesture.lastGestureMode == PointerGesture::Mode::FREEFORM) &&
currentFingerCount < 2) {
// Enter quiet time when exiting swipe or freeform state.
// This is to prevent accidentally entering the hover state and flinging the
// pointer when finishing a swipe and there is still one pointer left onscreen.
isQuietTime = true;
- } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG &&
+ } else if (mPointerGesture.lastGestureMode ==
+ PointerGesture::Mode::BUTTON_CLICK_OR_DRAG &&
currentFingerCount >= 2 && !isPointerDown(mCurrentRawState.buttonState)) {
// Enter quiet time when releasing the button and there are still two or more
// fingers down. This may indicate that one finger was used to press the button
@@ -2661,12 +2664,12 @@
ALOGD("Gestures: QUIET for next %0.3fms",
(mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
#endif
- if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
+ if (mPointerGesture.lastGestureMode != PointerGesture::Mode::QUIET) {
*outFinishPreviousGesture = true;
}
mPointerGesture.activeGestureId = -1;
- mPointerGesture.currentGestureMode = PointerGesture::QUIET;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::QUIET;
mPointerGesture.currentGestureIdBits.clear();
mPointerVelocityControl.reset();
@@ -2690,7 +2693,7 @@
activeTouchId, currentFingerCount);
#endif
// Reset state when just starting.
- if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
+ if (mPointerGesture.lastGestureMode != PointerGesture::Mode::BUTTON_CLICK_OR_DRAG) {
*outFinishPreviousGesture = true;
mPointerGesture.activeGestureId = 0;
}
@@ -2744,7 +2747,7 @@
float x, y;
mPointerController->getPosition(&x, &y);
- mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::BUTTON_CLICK_OR_DRAG;
mPointerGesture.currentGestureIdBits.clear();
mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
@@ -2757,15 +2760,15 @@
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
} else if (currentFingerCount == 0) {
// Case 3. No fingers down and button is not pressed. (NEUTRAL)
- if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
+ if (mPointerGesture.lastGestureMode != PointerGesture::Mode::NEUTRAL) {
*outFinishPreviousGesture = true;
}
// Watch for taps coming out of HOVER or TAP_DRAG mode.
// Checking for taps after TAP_DRAG allows us to detect double-taps.
bool tapped = false;
- if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER ||
- mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) &&
+ if ((mPointerGesture.lastGestureMode == PointerGesture::Mode::HOVER ||
+ mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP_DRAG) &&
lastFingerCount == 1) {
if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
float x, y;
@@ -2781,7 +2784,7 @@
mConfig.pointerGestureTapDragInterval);
mPointerGesture.activeGestureId = 0;
- mPointerGesture.currentGestureMode = PointerGesture::TAP;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP;
mPointerGesture.currentGestureIdBits.clear();
mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
@@ -2824,7 +2827,7 @@
ALOGD("Gestures: NEUTRAL");
#endif
mPointerGesture.activeGestureId = -1;
- mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::NEUTRAL;
mPointerGesture.currentGestureIdBits.clear();
}
} else if (currentFingerCount == 1) {
@@ -2834,14 +2837,14 @@
// When in TAP_DRAG, emit MOVE events at the pointer location.
ALOG_ASSERT(activeTouchId >= 0);
- mPointerGesture.currentGestureMode = PointerGesture::HOVER;
- if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::HOVER;
+ if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP) {
if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
float x, y;
mPointerController->getPosition(&x, &y);
if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop &&
fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
- mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP_DRAG;
} else {
#if DEBUG_GESTURES
ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
@@ -2854,8 +2857,8 @@
(when - mPointerGesture.tapUpTime) * 0.000001f);
#endif
}
- } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
- mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
+ } else if (mPointerGesture.lastGestureMode == PointerGesture::Mode::TAP_DRAG) {
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::TAP_DRAG;
}
float deltaX = 0, deltaY = 0;
@@ -2878,7 +2881,7 @@
}
bool down;
- if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
+ if (mPointerGesture.currentGestureMode == PointerGesture::Mode::TAP_DRAG) {
#if DEBUG_GESTURES
ALOGD("Gestures: TAP_DRAG");
#endif
@@ -2887,7 +2890,7 @@
#if DEBUG_GESTURES
ALOGD("Gestures: HOVER");
#endif
- if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
+ if (mPointerGesture.lastGestureMode != PointerGesture::Mode::HOVER) {
*outFinishPreviousGesture = true;
}
mPointerGesture.activeGestureId = 0;
@@ -2933,9 +2936,9 @@
bool settled = when >=
mPointerGesture.firstTouchTime + mConfig.pointerGestureMultitouchSettleInterval;
- if (mPointerGesture.lastGestureMode != PointerGesture::PRESS &&
- mPointerGesture.lastGestureMode != PointerGesture::SWIPE &&
- mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
+ if (mPointerGesture.lastGestureMode != PointerGesture::Mode::PRESS &&
+ mPointerGesture.lastGestureMode != PointerGesture::Mode::SWIPE &&
+ mPointerGesture.lastGestureMode != PointerGesture::Mode::FREEFORM) {
*outFinishPreviousGesture = true;
} else if (!settled && currentFingerCount > lastFingerCount) {
// Additional pointers have gone down but not yet settled.
@@ -2953,7 +2956,7 @@
}
if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
- mPointerGesture.currentGestureMode = PointerGesture::PRESS;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::PRESS;
mPointerGesture.activeGestureId = 0;
mPointerGesture.referenceIdBits.clear();
mPointerVelocityControl.reset();
@@ -3005,7 +3008,7 @@
}
// Consider transitions from PRESS to SWIPE or MULTITOUCH.
- if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
+ if (mPointerGesture.currentGestureMode == PointerGesture::Mode::PRESS) {
float dist[MAX_POINTER_ID + 1];
int32_t distOverThreshold = 0;
for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) {
@@ -3027,7 +3030,7 @@
currentFingerCount);
#endif
*outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
} else {
// There are exactly two pointers.
BitSet32 idBits(mCurrentCookedState.fingerIdBits);
@@ -3046,7 +3049,7 @@
mutualDistance, mPointerGestureMaxSwipeWidth);
#endif
*outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
} else {
// There are two pointers. Wait for both pointers to start moving
// before deciding whether this is a SWIPE or FREEFORM gesture.
@@ -3077,7 +3080,7 @@
mConfig.pointerGestureMultitouchMinDistance, cosine,
mConfig.pointerGestureSwipeTransitionAngleCosine);
#endif
- mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::SWIPE;
} else {
// Pointers are moving in different directions. Switch to FREEFORM.
#if DEBUG_GESTURES
@@ -3089,13 +3092,13 @@
mConfig.pointerGestureSwipeTransitionAngleCosine);
#endif
*outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
}
}
}
}
}
- } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
+ } else if (mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE) {
// Switch from SWIPE to FREEFORM if additional pointers go down.
// Cancel previous gesture.
if (currentFingerCount > 2) {
@@ -3104,13 +3107,13 @@
currentFingerCount);
#endif
*outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ mPointerGesture.currentGestureMode = PointerGesture::Mode::FREEFORM;
}
}
// Move the reference points based on the overall group motion of the fingers
// except in PRESS mode while waiting for a transition to occur.
- if (mPointerGesture.currentGestureMode != PointerGesture::PRESS &&
+ if (mPointerGesture.currentGestureMode != PointerGesture::Mode::PRESS &&
(commonDeltaX || commonDeltaY)) {
for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) {
uint32_t id = idBits.clearFirstMarkedBit();
@@ -3133,8 +3136,8 @@
}
// Report gestures.
- if (mPointerGesture.currentGestureMode == PointerGesture::PRESS ||
- mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
+ if (mPointerGesture.currentGestureMode == PointerGesture::Mode::PRESS ||
+ mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE) {
// PRESS or SWIPE mode.
#if DEBUG_GESTURES
ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
@@ -3155,7 +3158,7 @@
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
mPointerGesture.referenceGestureY);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
+ } else if (mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM) {
// FREEFORM mode.
#if DEBUG_GESTURES
ALOGD("Gestures: FREEFORM activeTouchId=%d,"
@@ -3168,7 +3171,7 @@
BitSet32 mappedTouchIdBits;
BitSet32 usedGestureIdBits;
- if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
+ if (mPointerGesture.lastGestureMode != PointerGesture::Mode::FREEFORM) {
// Initially, assign the active gesture id to the active touch point
// if there is one. No other touch id bits are mapped yet.
if (!*outCancelPreviousGesture) {
@@ -3568,7 +3571,7 @@
}
float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
- if (mDeviceMode == DEVICE_MODE_POINTER) {
+ if (mDeviceMode == DeviceMode::POINTER) {
mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
}
const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE);
@@ -3907,7 +3910,7 @@
std::optional<int32_t> TouchInputMapper::getAssociatedDisplayId() {
if (mParameters.hasAssociatedDisplay) {
- if (mDeviceMode == DEVICE_MODE_POINTER) {
+ if (mDeviceMode == DeviceMode::POINTER) {
return std::make_optional(mPointerController->getDisplayId());
} else {
return std::make_optional(mViewport.displayId);
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 7f811a0..d437e01 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -17,6 +17,8 @@
#ifndef _UI_INPUTREADER_TOUCH_INPUT_MAPPER_H
#define _UI_INPUTREADER_TOUCH_INPUT_MAPPER_H
+#include <stdint.h>
+
#include "CursorButtonAccumulator.h"
#include "CursorScrollAccumulator.h"
#include "EventHub.h"
@@ -24,8 +26,6 @@
#include "InputReaderBase.h"
#include "TouchButtonAccumulator.h"
-#include <stdint.h>
-
namespace android {
/* Raw axis information from the driver. */
@@ -133,25 +133,24 @@
class TouchInputMapper : public InputMapper {
public:
explicit TouchInputMapper(InputDeviceContext& deviceContext);
- virtual ~TouchInputMapper();
+ ~TouchInputMapper() override;
- virtual uint32_t getSources() override;
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo) override;
- virtual void dump(std::string& dump) override;
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config,
- uint32_t changes) override;
- virtual void reset(nsecs_t when) override;
- virtual void process(const RawEvent* rawEvent) override;
+ uint32_t getSources() override;
+ void populateDeviceInfo(InputDeviceInfo* deviceInfo) override;
+ void dump(std::string& dump) override;
+ void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) override;
+ void reset(nsecs_t when) override;
+ void process(const RawEvent* rawEvent) override;
- virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) override;
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) override;
+ int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) override;
+ int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
+ bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes,
+ uint8_t* outFlags) override;
- virtual void cancelTouch(nsecs_t when) override;
- virtual void timeoutExpired(nsecs_t when) override;
- virtual void updateExternalStylusState(const StylusState& state) override;
- virtual std::optional<int32_t> getAssociatedDisplayId() override;
+ void cancelTouch(nsecs_t when) override;
+ void timeoutExpired(nsecs_t when) override;
+ void updateExternalStylusState(const StylusState& state) override;
+ std::optional<int32_t> getAssociatedDisplayId() override;
protected:
CursorButtonAccumulator mCursorButtonAccumulator;
@@ -177,12 +176,12 @@
// Input sources and device mode.
uint32_t mSource;
- enum DeviceMode {
- DEVICE_MODE_DISABLED, // input is disabled
- DEVICE_MODE_DIRECT, // direct mapping (touchscreen)
- DEVICE_MODE_UNSCALED, // unscaled mapping (touchpad)
- DEVICE_MODE_NAVIGATION, // unscaled mapping with assist gesture (touch navigation)
- DEVICE_MODE_POINTER, // pointer mapping (pointer)
+ enum class DeviceMode {
+ DISABLED, // input is disabled
+ DIRECT, // direct mapping (touchscreen)
+ UNSCALED, // unscaled mapping (touchpad)
+ NAVIGATION, // unscaled mapping with assist gesture (touch navigation)
+ POINTER, // pointer mapping (pointer)
};
DeviceMode mDeviceMode;
@@ -191,11 +190,11 @@
// Immutable configuration parameters.
struct Parameters {
- enum DeviceType {
- DEVICE_TYPE_TOUCH_SCREEN,
- DEVICE_TYPE_TOUCH_PAD,
- DEVICE_TYPE_TOUCH_NAVIGATION,
- DEVICE_TYPE_POINTER,
+ enum class DeviceType {
+ TOUCH_SCREEN,
+ TOUCH_PAD,
+ TOUCH_NAVIGATION,
+ POINTER,
};
DeviceType deviceType;
@@ -205,9 +204,9 @@
bool hasButtonUnderPad;
std::string uniqueDisplayId;
- enum GestureMode {
- GESTURE_MODE_SINGLE_TOUCH,
- GESTURE_MODE_MULTI_TOUCH,
+ enum class GestureMode {
+ SINGLE_TOUCH,
+ MULTI_TOUCH,
};
GestureMode gestureMode;
@@ -217,13 +216,13 @@
// Immutable calibration parameters in parsed form.
struct Calibration {
// Size
- enum SizeCalibration {
- SIZE_CALIBRATION_DEFAULT,
- SIZE_CALIBRATION_NONE,
- SIZE_CALIBRATION_GEOMETRIC,
- SIZE_CALIBRATION_DIAMETER,
- SIZE_CALIBRATION_BOX,
- SIZE_CALIBRATION_AREA,
+ enum class SizeCalibration {
+ DEFAULT,
+ NONE,
+ GEOMETRIC,
+ DIAMETER,
+ BOX,
+ AREA,
};
SizeCalibration sizeCalibration;
@@ -236,11 +235,11 @@
bool sizeIsSummed;
// Pressure
- enum PressureCalibration {
- PRESSURE_CALIBRATION_DEFAULT,
- PRESSURE_CALIBRATION_NONE,
- PRESSURE_CALIBRATION_PHYSICAL,
- PRESSURE_CALIBRATION_AMPLITUDE,
+ enum class PressureCalibration {
+ DEFAULT,
+ NONE,
+ PHYSICAL,
+ AMPLITUDE,
};
PressureCalibration pressureCalibration;
@@ -248,30 +247,30 @@
float pressureScale;
// Orientation
- enum OrientationCalibration {
- ORIENTATION_CALIBRATION_DEFAULT,
- ORIENTATION_CALIBRATION_NONE,
- ORIENTATION_CALIBRATION_INTERPOLATED,
- ORIENTATION_CALIBRATION_VECTOR,
+ enum class OrientationCalibration {
+ DEFAULT,
+ NONE,
+ INTERPOLATED,
+ VECTOR,
};
OrientationCalibration orientationCalibration;
// Distance
- enum DistanceCalibration {
- DISTANCE_CALIBRATION_DEFAULT,
- DISTANCE_CALIBRATION_NONE,
- DISTANCE_CALIBRATION_SCALED,
+ enum class DistanceCalibration {
+ DEFAULT,
+ NONE,
+ SCALED,
};
DistanceCalibration distanceCalibration;
bool haveDistanceScale;
float distanceScale;
- enum CoverageCalibration {
- COVERAGE_CALIBRATION_DEFAULT,
- COVERAGE_CALIBRATION_NONE,
- COVERAGE_CALIBRATION_BOX,
+ enum class CoverageCalibration {
+ DEFAULT,
+ NONE,
+ BOX,
};
CoverageCalibration coverageCalibration;
@@ -524,16 +523,16 @@
uint64_t distance : 48; // squared distance
};
- enum PointerUsage {
- POINTER_USAGE_NONE,
- POINTER_USAGE_GESTURES,
- POINTER_USAGE_STYLUS,
- POINTER_USAGE_MOUSE,
+ enum class PointerUsage {
+ NONE,
+ GESTURES,
+ STYLUS,
+ MOUSE,
};
PointerUsage mPointerUsage;
struct PointerGesture {
- enum Mode {
+ enum class Mode {
// No fingers, button is not pressed.
// Nothing happening.
NEUTRAL,
@@ -646,9 +645,9 @@
firstTouchTime = LLONG_MIN;
activeTouchId = -1;
activeGestureId = -1;
- currentGestureMode = NEUTRAL;
+ currentGestureMode = Mode::NEUTRAL;
currentGestureIdBits.clear();
- lastGestureMode = NEUTRAL;
+ lastGestureMode = Mode::NEUTRAL;
lastGestureIdBits.clear();
downTime = 0;
velocityTracker.clear();
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index a0d2f4f..eb9ac68 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -35,7 +35,17 @@
"InputClassifierConverter_test.cpp",
"InputDispatcher_test.cpp",
"InputReader_test.cpp",
+ "InputFlingerService_test.cpp",
"UinputDevice.cpp",
+ "IInputFlingerQuery.aidl"
+ ],
+ aidl: {
+ include_dirs: [
+ "frameworks/native/libs/input",
+ ],
+ },
+ static_libs: [
+ "libc++fs"
],
require_root: true,
}
diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl
new file mode 100644
index 0000000..1edc089
--- /dev/null
+++ b/services/inputflinger/tests/IInputFlingerQuery.aidl
@@ -0,0 +1,27 @@
+/**
+ * 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.
+ */
+
+import android.InputChannelInfo;
+import android.InputWindowInfo;
+import android.os.ISetInputWindowsListener;
+
+/** @hide */
+interface IInputFlingerQuery
+{
+ /* Test interfaces */
+ void getInputWindows(out InputWindowInfo[] inputHandles);
+ void getInputChannels(out InputChannelInfo[] infos);
+}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index cf5a3ab..c749806 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -29,6 +29,7 @@
#include <vector>
using android::base::StringPrintf;
+using namespace android::flag_operators;
namespace android::inputdispatcher {
@@ -766,8 +767,7 @@
mInfo.token = token;
mInfo.id = sId++;
mInfo.name = name;
- mInfo.layoutParamsFlags = 0;
- mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
+ mInfo.type = InputWindowInfo::Type::APPLICATION;
mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
mInfo.frameLeft = 0;
mInfo.frameTop = 0;
@@ -783,7 +783,6 @@
mInfo.paused = false;
mInfo.ownerPid = INJECTOR_PID;
mInfo.ownerUid = INJECTOR_UID;
- mInfo.inputFeatures = 0;
mInfo.displayId = displayId;
}
@@ -806,7 +805,7 @@
mInfo.addTouchableRegion(frame);
}
- void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
+ void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
void setWindowScale(float xScale, float yScale) {
mInfo.windowXScale = xScale;
@@ -939,6 +938,126 @@
return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
}
+class PointerBuilder {
+public:
+ PointerBuilder(int32_t id, int32_t toolType) {
+ mProperties.clear();
+ mProperties.id = id;
+ mProperties.toolType = toolType;
+ mCoords.clear();
+ }
+
+ PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
+
+ PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
+
+ PointerBuilder& axis(int32_t axis, float value) {
+ mCoords.setAxisValue(axis, value);
+ return *this;
+ }
+
+ PointerProperties buildProperties() const { return mProperties; }
+
+ PointerCoords buildCoords() const { return mCoords; }
+
+private:
+ PointerProperties mProperties;
+ PointerCoords mCoords;
+};
+
+class MotionEventBuilder {
+public:
+ MotionEventBuilder(int32_t action, int32_t source) {
+ mAction = action;
+ mSource = source;
+ mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ }
+
+ MotionEventBuilder& eventTime(nsecs_t eventTime) {
+ mEventTime = eventTime;
+ return *this;
+ }
+
+ MotionEventBuilder& displayId(int32_t displayId) {
+ mDisplayId = displayId;
+ return *this;
+ }
+
+ MotionEventBuilder& actionButton(int32_t actionButton) {
+ mActionButton = actionButton;
+ return *this;
+ }
+
+ MotionEventBuilder& buttonState(int32_t actionButton) {
+ mActionButton = actionButton;
+ return *this;
+ }
+
+ MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
+ mRawXCursorPosition = rawXCursorPosition;
+ return *this;
+ }
+
+ MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
+ mRawYCursorPosition = rawYCursorPosition;
+ return *this;
+ }
+
+ MotionEventBuilder& pointer(PointerBuilder pointer) {
+ mPointers.push_back(pointer);
+ return *this;
+ }
+
+ MotionEvent build() {
+ std::vector<PointerProperties> pointerProperties;
+ std::vector<PointerCoords> pointerCoords;
+ for (const PointerBuilder& pointer : mPointers) {
+ pointerProperties.push_back(pointer.buildProperties());
+ pointerCoords.push_back(pointer.buildCoords());
+ }
+
+ // Set mouse cursor position for the most common cases to avoid boilerplate.
+ if (mSource == AINPUT_SOURCE_MOUSE &&
+ !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
+ mPointers.size() == 1) {
+ mRawXCursorPosition = pointerCoords[0].getX();
+ mRawYCursorPosition = pointerCoords[0].getY();
+ }
+
+ MotionEvent event;
+ event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
+ mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
+ mButtonState, MotionClassification::NONE, /* xScale */ 1, /* yScale */ 1,
+ /* xOffset */ 0,
+ /* yOffset */ 0, /* xPrecision */ 0, /* yPrecision */ 0,
+ mRawXCursorPosition, mRawYCursorPosition, mEventTime, mEventTime,
+ mPointers.size(), pointerProperties.data(), pointerCoords.data());
+
+ return event;
+ }
+
+private:
+ int32_t mAction;
+ int32_t mSource;
+ nsecs_t mEventTime;
+ int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
+ int32_t mActionButton{0};
+ int32_t mButtonState{0};
+ float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
+ float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
+
+ std::vector<PointerBuilder> mPointers;
+};
+
+static int32_t injectMotionEvent(
+ const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
+ std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
+ int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT) {
+ return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
+ injectionTimeout,
+ POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
+}
+
static int32_t injectMotionEvent(
const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
const PointF& position,
@@ -947,32 +1066,18 @@
std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
- MotionEvent event;
- PointerProperties pointerProperties[1];
- PointerCoords pointerCoords[1];
-
- pointerProperties[0].clear();
- pointerProperties[0].id = 0;
- pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-
- pointerCoords[0].clear();
- pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, position.x);
- pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, position.y);
-
- // Define a valid motion down event.
- event.initialize(InputEvent::nextId(), DEVICE_ID, source, displayId, INVALID_HMAC, action,
- /* actionButton */ 0,
- /* flags */ 0,
- /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
- /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
- /* xPrecision */ 0, /* yPrecision */ 0, cursorPosition.x, cursorPosition.y,
- eventTime, eventTime,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
+ MotionEvent event = MotionEventBuilder(action, source)
+ .displayId(displayId)
+ .eventTime(eventTime)
+ .rawXCursorPosition(cursorPosition.x)
+ .rawYCursorPosition(cursorPosition.y)
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(position.x)
+ .y(position.y))
+ .build();
// Inject event until dispatch out.
- return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
- injectionTimeout,
- POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
+ return injectMotionEvent(dispatcher, event);
}
static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
@@ -1059,7 +1164,7 @@
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
window->setFrame(Rect(0, 0, 100, 100));
- window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+ window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
@@ -1082,7 +1187,7 @@
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
window->setFrame(Rect(0, 0, 100, 100));
- window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+ window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
@@ -1187,17 +1292,209 @@
windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
}
+TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> windowLeft =
+ new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+ windowLeft->setFrame(Rect(0, 0, 600, 800));
+ windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+ sp<FakeWindowHandle> windowRight =
+ new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+ windowRight->setFrame(Rect(600, 0, 1200, 800));
+ windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
+
+ // Start cursor position in right window so that we can move the cursor to left window.
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
+ AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(900)
+ .y(400))
+ .build()));
+ windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+
+ // Move cursor into left window
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
+ AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+
+ // Inject a series of mouse events for a mouse click
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
+ AINPUT_SOURCE_MOUSE)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
+ AINPUT_SOURCE_MOUSE)
+ .buttonState(0)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
+ .buttonState(0)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+
+ // Move mouse cursor back to right window
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
+ AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(900)
+ .y(400))
+ .build()));
+ windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+}
+
+// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
+// directly in this test.
+TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+ window->setFrame(Rect(0, 0, 1200, 800));
+ window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
+
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
+ AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+
+ // Inject a series of mouse events for a mouse click
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
+ AINPUT_SOURCE_MOUSE)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
+ AINPUT_SOURCE_MOUSE)
+ .buttonState(0)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
+ .buttonState(0)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
+ AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(300)
+ .y(400))
+ .build()));
+ window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
+ ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+}
+
TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
sp<FakeApplicationHandle> application = new FakeApplicationHandle();
sp<FakeWindowHandle> windowLeft =
new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
windowLeft->setFrame(Rect(0, 0, 600, 800));
- windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+ windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
sp<FakeWindowHandle> windowRight =
new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
windowRight->setFrame(Rect(600, 0, 1200, 800));
- windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+ windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -1356,15 +1653,15 @@
sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
"First Window", ADISPLAY_ID_DEFAULT);
firstWindow->setFrame(Rect(0, 0, 600, 400));
- firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
- | InputWindowInfo::FLAG_SPLIT_TOUCH);
+ firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
+ InputWindowInfo::Flag::SPLIT_TOUCH);
// Create a non touch modal window that supports split touch
sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
"Second Window", ADISPLAY_ID_DEFAULT);
secondWindow->setFrame(Rect(0, 400, 600, 800));
- secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
- | InputWindowInfo::FLAG_SPLIT_TOUCH);
+ secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
+ InputWindowInfo::Flag::SPLIT_TOUCH);
// Add the windows to the dispatcher
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
@@ -2049,12 +2346,12 @@
mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
// Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
// window.
- mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+ mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
mFocusedWindow =
new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
- mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+ mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
// Set focused application.
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -2142,14 +2439,14 @@
ADISPLAY_ID_DEFAULT);
// Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
// We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
- mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
- InputWindowInfo::FLAG_SPLIT_TOUCH);
+ mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
+ InputWindowInfo::Flag::SPLIT_TOUCH);
mWindow1->setFrame(Rect(0, 0, 100, 100));
mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
ADISPLAY_ID_DEFAULT, mWindow1->getToken());
- mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
- InputWindowInfo::FLAG_SPLIT_TOUCH);
+ mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
+ InputWindowInfo::Flag::SPLIT_TOUCH);
mWindow2->setFrame(Rect(100, 100, 200, 200));
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
@@ -2373,7 +2670,7 @@
mWindow->setFocus(true);
// Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
// window.
- mWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+ mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
// Set focused application.
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
@@ -2755,16 +3052,16 @@
// Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
// window.
// Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
- mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
- InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH |
- InputWindowInfo::FLAG_SPLIT_TOUCH);
+ mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
+ InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
+ InputWindowInfo::Flag::SPLIT_TOUCH);
mFocusedWindow =
new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
mFocusedWindow->setDispatchingTimeout(30ms);
mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
- mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
- InputWindowInfo::FLAG_SPLIT_TOUCH);
+ mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
+ InputWindowInfo::Flag::SPLIT_TOUCH);
// Set focused application.
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp
new file mode 100644
index 0000000..193fe77
--- /dev/null
+++ b/services/inputflinger/tests/InputFlingerService_test.cpp
@@ -0,0 +1,411 @@
+/*
+ * 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 <BnInputFlingerQuery.h>
+#include <IInputFlingerQuery.h>
+
+#include <android/os/BnInputFlinger.h>
+#include <android/os/BnSetInputWindowsListener.h>
+#include <android/os/IInputFlinger.h>
+#include <android/os/ISetInputWindowsListener.h>
+
+#include <binder/Binder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+
+#include <input/Input.h>
+#include <input/InputTransport.h>
+#include <input/InputWindow.h>
+
+#include <gtest/gtest.h>
+#include <inttypes.h>
+#include <linux/uinput.h>
+#include <log/log.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+#include <chrono>
+#include <thread>
+#include <unordered_map>
+
+#define TAG "InputFlingerServiceTest"
+
+using android::os::BnInputFlinger;
+using android::os::BnSetInputWindowsListener;
+using android::os::IInputFlinger;
+using android::os::ISetInputWindowsListener;
+
+using std::chrono_literals::operator""ms;
+using std::chrono_literals::operator""s;
+
+namespace android {
+
+static const sp<IBinder> TestInfoToken = new BBinder();
+static constexpr int32_t TestInfoId = 1;
+static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo";
+static constexpr Flags<InputWindowInfo::Flag> TestInfoFlags = InputWindowInfo::Flag::NOT_FOCUSABLE;
+static constexpr InputWindowInfo::Type TestInfoType = InputWindowInfo::Type::INPUT_METHOD;
+static constexpr std::chrono::duration TestInfoDispatchingTimeout = 2532ms;
+static constexpr int32_t TestInfoFrameLeft = 93;
+static constexpr int32_t TestInfoFrameTop = 34;
+static constexpr int32_t TestInfoFrameRight = 16;
+static constexpr int32_t TestInfoFrameBottom = 19;
+static constexpr int32_t TestInfoSurfaceInset = 17;
+static constexpr float TestInfoGlobalScaleFactor = 0.3;
+static constexpr float TestInfoWindowXScale = 0.4;
+static constexpr float TestInfoWindowYScale = 0.5;
+static const Rect TestInfoTouchableRegionRect = {100 /* left */, 150 /* top */, 400 /* right */,
+ 450 /* bottom */};
+static const Region TestInfoTouchableRegion(TestInfoTouchableRegionRect);
+static constexpr bool TestInfoVisible = false;
+static constexpr bool TestInfoCanReceiveKeys = false;
+static constexpr bool TestInfoTrustedOverlay = true;
+static constexpr bool TestInfoHasFocus = false;
+static constexpr bool TestInfoHasWallpaper = false;
+static constexpr bool TestInfoPaused = false;
+static constexpr int32_t TestInfoOwnerPid = 19;
+static constexpr int32_t TestInfoOwnerUid = 24;
+static constexpr InputWindowInfo::Feature TestInfoInputFeatures =
+ InputWindowInfo::Feature::NO_INPUT_CHANNEL;
+static constexpr int32_t TestInfoDisplayId = 34;
+static constexpr int32_t TestInfoPortalToDisplayId = 2;
+static constexpr bool TestInfoReplaceTouchableRegionWithCrop = true;
+static const sp<IBinder> TestInfoTouchableRegionCropHandle = new BBinder();
+
+static const std::string TestAppInfoName = "InputFlingerServiceTestInputApplicationInfo";
+static const sp<IBinder> TestAppInfoToken = new BBinder();
+static constexpr std::chrono::duration TestAppInfoDispatchingTimeout = 12345678ms;
+
+static const String16 kTestServiceName = String16("InputFlingerService");
+static const String16 kQueryServiceName = String16("InputFlingerQueryService");
+
+struct SetInputWindowsListener;
+// --- InputFlingerServiceTest ---
+class InputFlingerServiceTest : public testing::Test {
+public:
+ void SetUp() override;
+ void TearDown() override;
+
+protected:
+ void InitializeInputFlinger();
+ void setInputWindowsByInfos(std::vector<InputWindowInfo>& infos);
+
+ void setInputWindowsFinished();
+ void verifyInputWindowInfo(const InputWindowInfo& info) const;
+ InputWindowInfo& getInfo() const { return const_cast<InputWindowInfo&>(mInfo); }
+
+ sp<IInputFlinger> mService;
+ sp<IInputFlingerQuery> mQuery;
+
+private:
+ sp<SetInputWindowsListener> mSetInputWindowsListener;
+ sp<InputChannel> mServerChannel, mClientChannel;
+ InputWindowInfo mInfo;
+ std::mutex mLock;
+ std::condition_variable mSetInputWindowsFinishedCondition;
+};
+
+struct SetInputWindowsListener : BnSetInputWindowsListener {
+ explicit SetInputWindowsListener(std::function<void()> cbFunc) : mCbFunc(cbFunc) {}
+
+ binder::Status onSetInputWindowsFinished() override;
+
+ std::function<void()> mCbFunc;
+};
+
+class TestInputManager : public BnInputFlinger {
+protected:
+ virtual ~TestInputManager(){};
+
+public:
+ TestInputManager(){};
+ void checkFdFlags(const android::base::unique_fd& fd);
+
+ binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles);
+ binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos);
+
+ status_t dump(int fd, const Vector<String16>& args) override;
+
+ binder::Status setInputWindows(
+ const std::vector<InputWindowInfo>& handles,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
+
+ binder::Status registerInputChannel(const InputChannelInfo& channel) override;
+ binder::Status unregisterInputChannel(const InputChannelInfo& channel) override;
+
+private:
+ mutable Mutex mLock;
+ std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mHandlesPerDisplay;
+ std::vector<sp<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;
+
+private:
+ sp<android::TestInputManager> mManager;
+};
+
+binder::Status TestInputQuery::getInputWindows(
+ std::vector<::android::InputWindowInfo>* inputHandles) {
+ return mManager->getInputWindows(inputHandles);
+}
+
+binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannelInfo>* infos) {
+ return mManager->getInputChannels(infos);
+}
+
+binder::Status SetInputWindowsListener::onSetInputWindowsFinished() {
+ if (mCbFunc != nullptr) {
+ mCbFunc();
+ }
+ return binder::Status::ok();
+}
+
+binder::Status TestInputManager::setInputWindows(
+ const std::vector<InputWindowInfo>& infos,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener) {
+ AutoMutex _l(mLock);
+
+ for (const auto& info : infos) {
+ mHandlesPerDisplay.emplace(info.displayId, std::vector<sp<InputWindowHandle>>());
+ mHandlesPerDisplay[info.displayId].push_back(new InputWindowHandle(info));
+ }
+ if (setInputWindowsListener) {
+ setInputWindowsListener->onSetInputWindowsFinished();
+ }
+ return binder::Status::ok();
+}
+
+void TestInputManager::checkFdFlags(const android::base::unique_fd& fd) {
+ const int result = fcntl(fd, F_GETFL);
+ EXPECT_NE(result, -1);
+ EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK);
+}
+
+binder::Status TestInputManager::registerInputChannel(const InputChannelInfo& info) {
+ 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);
+ mInputChannels.push_back(channel);
+
+ return binder::Status::ok();
+}
+
+binder::Status TestInputManager::unregisterInputChannel(const InputChannelInfo& info) {
+ 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);
+
+ auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(),
+ [&](sp<InputChannel>& it) { return *it == *channel; });
+ if (it != mInputChannels.end()) {
+ mInputChannels.erase(it);
+ }
+
+ return binder::Status::ok();
+}
+
+status_t TestInputManager::dump(int fd, const Vector<String16>& args) {
+ std::string dump;
+
+ dump += " InputFlinger dump\n";
+
+ ::write(fd, dump.c_str(), dump.size());
+ return NO_ERROR;
+}
+
+binder::Status TestInputManager::getInputWindows(
+ std::vector<::android::InputWindowInfo>* inputInfos) {
+ for (auto& [displayId, inputHandles] : mHandlesPerDisplay) {
+ for (auto& inputHandle : inputHandles) {
+ inputInfos->push_back(*inputHandle->getInfo());
+ }
+ }
+ 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()));
+ }
+ return binder::Status::ok();
+}
+
+void InputFlingerServiceTest::SetUp() {
+ mSetInputWindowsListener = new SetInputWindowsListener([&]() {
+ std::unique_lock<std::mutex> lock(mLock);
+ mSetInputWindowsFinishedCondition.notify_all();
+ });
+ InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
+
+ mInfo.token = TestInfoToken;
+ mInfo.id = TestInfoId;
+ mInfo.name = TestInfoName;
+ mInfo.flags = TestInfoFlags;
+ mInfo.type = TestInfoType;
+ mInfo.dispatchingTimeout = TestInfoDispatchingTimeout;
+ mInfo.frameLeft = TestInfoFrameLeft;
+ mInfo.frameTop = TestInfoFrameTop;
+ mInfo.frameRight = TestInfoFrameRight;
+ mInfo.frameBottom = TestInfoFrameBottom;
+ mInfo.surfaceInset = TestInfoSurfaceInset;
+ mInfo.globalScaleFactor = TestInfoGlobalScaleFactor;
+ mInfo.windowXScale = TestInfoWindowXScale;
+ mInfo.windowYScale = TestInfoWindowYScale;
+ mInfo.touchableRegion = TestInfoTouchableRegion;
+ mInfo.visible = TestInfoVisible;
+ mInfo.canReceiveKeys = TestInfoCanReceiveKeys;
+ mInfo.trustedOverlay = TestInfoTrustedOverlay;
+ mInfo.hasFocus = TestInfoHasFocus;
+ mInfo.hasWallpaper = TestInfoHasWallpaper;
+ mInfo.paused = TestInfoPaused;
+ mInfo.ownerPid = TestInfoOwnerPid;
+ mInfo.ownerUid = TestInfoOwnerUid;
+ mInfo.inputFeatures = TestInfoInputFeatures;
+ mInfo.displayId = TestInfoDisplayId;
+ mInfo.portalToDisplayId = TestInfoPortalToDisplayId;
+ mInfo.replaceTouchableRegionWithCrop = TestInfoReplaceTouchableRegionWithCrop;
+ mInfo.touchableRegionCropHandle = TestInfoTouchableRegionCropHandle;
+
+ mInfo.applicationInfo.name = TestAppInfoName;
+ mInfo.applicationInfo.token = TestAppInfoToken;
+ mInfo.applicationInfo.dispatchingTimeout = TestAppInfoDispatchingTimeout;
+
+ InitializeInputFlinger();
+}
+
+void InputFlingerServiceTest::TearDown() {}
+
+void InputFlingerServiceTest::verifyInputWindowInfo(const InputWindowInfo& info) const {
+ EXPECT_EQ(mInfo, info);
+}
+
+void InputFlingerServiceTest::InitializeInputFlinger() {
+ sp<IBinder> input(defaultServiceManager()->waitForService(kTestServiceName));
+ ASSERT_TRUE(input != nullptr);
+ mService = interface_cast<IInputFlinger>(input);
+
+ input = defaultServiceManager()->waitForService(kQueryServiceName);
+ ASSERT_TRUE(input != nullptr);
+ mQuery = interface_cast<IInputFlingerQuery>(input);
+}
+
+void InputFlingerServiceTest::setInputWindowsByInfos(std::vector<InputWindowInfo>& infos) {
+ std::unique_lock<std::mutex> lock(mLock);
+ 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);
+ }
+}
+
+/**
+ * Test InputFlinger service interface SetInputWindows
+ */
+TEST_F(InputFlingerServiceTest, InputWindow_SetInputWindows) {
+ std::vector<InputWindowInfo> infos = {getInfo()};
+ setInputWindowsByInfos(infos);
+}
+
+/**
+ * Test InputFlinger service interface registerInputChannel
+ */
+TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) {
+ sp<InputChannel> serverChannel, clientChannel;
+
+ InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
+ mService->registerInputChannel(serverChannel->getInfo());
+
+ std::vector<::android::InputChannelInfo> infos(2);
+ mQuery->getInputChannels(&infos);
+ EXPECT_EQ(infos.size(), 1UL);
+
+ 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);
+}
+
+/**
+ * Test InputFlinger service interface registerInputChannel with invalid cases
+ */
+TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) {
+ sp<InputChannel> serverChannel, clientChannel;
+ InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
+
+ std::vector<::android::InputChannelInfo> infos(2);
+ mQuery->getInputChannels(&infos);
+ EXPECT_EQ(infos.size(), 0UL);
+
+ mService->registerInputChannel(InputChannelInfo());
+ mService->unregisterInputChannel(clientChannel->getInfo());
+
+ mService->registerInputChannel(serverChannel->getInfo());
+ mService->registerInputChannel(clientChannel->getInfo());
+ mQuery->getInputChannels(&infos);
+ EXPECT_EQ(infos.size(), 2UL);
+
+ mService->unregisterInputChannel(clientChannel->getInfo());
+ mService->unregisterInputChannel(serverChannel->getInfo());
+ mQuery->getInputChannels(&infos);
+ EXPECT_EQ(infos.size(), 0UL);
+}
+
+} // namespace android
+
+int main(int argc, char** argv) {
+ pid_t forkPid = fork();
+
+ if (forkPid == 0) {
+ // Server process
+ android::sp<android::TestInputManager> manager = new android::TestInputManager();
+ android::sp<android::TestInputQuery> query = new android::TestInputQuery(manager);
+
+ android::defaultServiceManager()->addService(android::kTestServiceName, manager,
+ false /*allowIsolated*/);
+ android::defaultServiceManager()->addService(android::kQueryServiceName, query,
+ false /*allowIsolated*/);
+ android::ProcessState::self()->startThreadPool();
+ android::IPCThreadState::self()->joinThreadPool();
+ } else {
+ android::ProcessState::self()->startThreadPool();
+ ::testing::InitGoogleTest(&argc, argv);
+ int result = RUN_ALL_TESTS();
+ kill(forkPid, SIGKILL);
+ return result;
+ }
+ return 0;
+}
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 18bd3d0..fae7e64 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1188,20 +1188,21 @@
// We didn't add any viewports yet, so there shouldn't be any.
std::optional<DisplayViewport> internalViewport =
- mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
ASSERT_FALSE(internalViewport);
// Add an internal viewport, then clear it
mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, uniqueId, NO_PORT, ViewportType::VIEWPORT_INTERNAL);
+ DISPLAY_ORIENTATION_0, uniqueId, NO_PORT,
+ ViewportType::INTERNAL);
// Check matching by uniqueId
internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
ASSERT_TRUE(internalViewport);
- ASSERT_EQ(ViewportType::VIEWPORT_INTERNAL, internalViewport->type);
+ ASSERT_EQ(ViewportType::INTERNAL, internalViewport->type);
// Check matching by viewport type
- internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
ASSERT_TRUE(internalViewport);
ASSERT_EQ(uniqueId, internalViewport->uniqueId);
@@ -1209,7 +1210,7 @@
// Make sure nothing is found after clear
internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
ASSERT_FALSE(internalViewport);
- internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
ASSERT_FALSE(internalViewport);
}
@@ -1223,26 +1224,30 @@
// Add an internal viewport
mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, internalUniqueId, NO_PORT, ViewportType::VIEWPORT_INTERNAL);
+ DISPLAY_ORIENTATION_0, internalUniqueId, NO_PORT,
+ ViewportType::INTERNAL);
// Add an external viewport
mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, externalUniqueId, NO_PORT, ViewportType::VIEWPORT_EXTERNAL);
+ DISPLAY_ORIENTATION_0, externalUniqueId, NO_PORT,
+ ViewportType::EXTERNAL);
// Add an virtual viewport
mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, virtualUniqueId1, NO_PORT, ViewportType::VIEWPORT_VIRTUAL);
+ DISPLAY_ORIENTATION_0, virtualUniqueId1, NO_PORT,
+ ViewportType::VIRTUAL);
// Add another virtual viewport
mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, virtualUniqueId2, NO_PORT, ViewportType::VIEWPORT_VIRTUAL);
+ DISPLAY_ORIENTATION_0, virtualUniqueId2, NO_PORT,
+ ViewportType::VIRTUAL);
// Check matching by type for internal
std::optional<DisplayViewport> internalViewport =
- mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
ASSERT_TRUE(internalViewport);
ASSERT_EQ(internalUniqueId, internalViewport->uniqueId);
// Check matching by type for external
std::optional<DisplayViewport> externalViewport =
- mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_EXTERNAL);
+ mFakePolicy->getDisplayViewportByType(ViewportType::EXTERNAL);
ASSERT_TRUE(externalViewport);
ASSERT_EQ(externalUniqueId, externalViewport->uniqueId);
@@ -1250,7 +1255,7 @@
std::optional<DisplayViewport> virtualViewport1 =
mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1);
ASSERT_TRUE(virtualViewport1);
- ASSERT_EQ(ViewportType::VIEWPORT_VIRTUAL, virtualViewport1->type);
+ ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport1->type);
ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId);
ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId);
@@ -1258,7 +1263,7 @@
std::optional<DisplayViewport> virtualViewport2 =
mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2);
ASSERT_TRUE(virtualViewport2);
- ASSERT_EQ(ViewportType::VIEWPORT_VIRTUAL, virtualViewport2->type);
+ ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport2->type);
ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId);
ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId);
}
@@ -1275,8 +1280,8 @@
constexpr int32_t displayId1 = 2;
constexpr int32_t displayId2 = 3;
- std::vector<ViewportType> types = {ViewportType::VIEWPORT_INTERNAL,
- ViewportType::VIEWPORT_EXTERNAL, ViewportType::VIEWPORT_VIRTUAL};
+ std::vector<ViewportType> types = {ViewportType::INTERNAL, ViewportType::EXTERNAL,
+ ViewportType::VIRTUAL};
for (const ViewportType& type : types) {
mFakePolicy->clearViewports();
// Add a viewport
@@ -1314,7 +1319,7 @@
* Check getDisplayViewportByPort
*/
TEST_F(InputReaderPolicyTest, Viewports_GetByPort) {
- constexpr ViewportType type = ViewportType::VIEWPORT_EXTERNAL;
+ constexpr ViewportType type = ViewportType::EXTERNAL;
const std::string uniqueId1 = "uniqueId1";
const std::string uniqueId2 = "uniqueId2";
constexpr int32_t displayId1 = 1;
@@ -1708,9 +1713,11 @@
// Add default and second display.
mFakePolicy->clearViewports();
mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, "local:0", NO_PORT, ViewportType::VIEWPORT_INTERNAL);
+ DISPLAY_ORIENTATION_0, "local:0", NO_PORT,
+ ViewportType::INTERNAL);
mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, "local:1", hdmi1, ViewportType::VIEWPORT_EXTERNAL);
+ DISPLAY_ORIENTATION_0, "local:1", hdmi1,
+ ViewportType::EXTERNAL);
mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
mReader->loopOnce();
@@ -1884,7 +1891,7 @@
// At least add an internal display.
setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_ORIENTATION_0, UNIQUE_ID, NO_PORT,
- ViewportType::VIEWPORT_INTERNAL);
+ ViewportType::INTERNAL);
mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
@@ -2220,8 +2227,7 @@
// Prepare displays.
mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, UNIQUE_ID, hdmi,
- ViewportType::VIEWPORT_INTERNAL);
+ DISPLAY_ORIENTATION_0, UNIQUE_ID, hdmi, ViewportType::INTERNAL);
mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::CHANGE_DISPLAY_INFO);
ASSERT_TRUE(mDevice->isEnabled());
@@ -2421,8 +2427,8 @@
* orientation.
*/
void KeyboardInputMapperTest::prepareDisplay(int32_t orientation) {
- setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- orientation, UNIQUE_ID, NO_PORT, ViewportType::VIEWPORT_INTERNAL);
+ setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
+ NO_PORT, ViewportType::INTERNAL);
}
void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
@@ -2727,7 +2733,7 @@
// ^--- already checked by the previous test
setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0,
- UNIQUE_ID, NO_PORT, ViewportType::VIEWPORT_INTERNAL);
+ UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0);
@@ -2737,7 +2743,7 @@
constexpr int32_t newDisplayId = 2;
clearViewports();
setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0,
- UNIQUE_ID, NO_PORT, ViewportType::VIEWPORT_INTERNAL);
+ UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0);
@@ -2898,9 +2904,9 @@
// Prepare second display.
constexpr int32_t newDisplayId = 2;
setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0,
- UNIQUE_ID, hdmi1, ViewportType::VIEWPORT_INTERNAL);
+ UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0,
- SECONDARY_UNIQUE_ID, hdmi2, ViewportType::VIEWPORT_EXTERNAL);
+ SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
// Default device will reconfigure above, need additional reconfiguration for another device.
device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::CHANGE_DISPLAY_INFO);
@@ -3035,7 +3041,7 @@
void prepareDisplay(int32_t orientation) {
const std::string uniqueId = "local:0";
- const ViewportType viewportType = ViewportType::VIEWPORT_INTERNAL;
+ const ViewportType viewportType = ViewportType::INTERNAL;
setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
orientation, uniqueId, NO_PORT, viewportType);
}
@@ -3780,8 +3786,7 @@
constexpr int32_t SECOND_DISPLAY_ID = 1;
const std::string SECOND_DISPLAY_UNIQUE_ID = "local:1";
mFakePolicy->addDisplayViewport(SECOND_DISPLAY_ID, 800, 480, DISPLAY_ORIENTATION_0,
- SECOND_DISPLAY_UNIQUE_ID, NO_PORT,
- ViewportType::VIEWPORT_EXTERNAL);
+ SECOND_DISPLAY_UNIQUE_ID, NO_PORT, ViewportType::EXTERNAL);
mFakePolicy->setDefaultPointerDisplayId(SECOND_DISPLAY_ID);
configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
@@ -3908,8 +3913,8 @@
};
void TouchInputMapperTest::prepareDisplay(int32_t orientation, std::optional<uint8_t> port) {
- setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation,
- UNIQUE_ID, port, ViewportType::VIEWPORT_INTERNAL);
+ setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
+ port, ViewportType::INTERNAL);
}
void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
@@ -3918,9 +3923,9 @@
}
void TouchInputMapperTest::prepareVirtualDisplay(int32_t orientation) {
- setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH,
- VIRTUAL_DISPLAY_HEIGHT, orientation,
- VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT, ViewportType::VIEWPORT_VIRTUAL);
+ setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
+ orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
+ ViewportType::VIRTUAL);
}
void TouchInputMapperTest::prepareVirtualKeys() {
@@ -6773,7 +6778,7 @@
const uint8_t hdmi1 = 0;
const uint8_t hdmi2 = 1;
const std::string secondaryUniqueId = "uniqueId2";
- constexpr ViewportType type = ViewportType::VIEWPORT_EXTERNAL;
+ constexpr ViewportType type = ViewportType::EXTERNAL;
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareAxes(POSITION);
@@ -6814,7 +6819,7 @@
mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
mFakePolicy->setDefaultPointerDisplayId(SECONDARY_DISPLAY_ID);
- prepareSecondaryDisplay(ViewportType::VIEWPORT_EXTERNAL);
+ prepareSecondaryDisplay(ViewportType::EXTERNAL);
prepareDisplay(DISPLAY_ORIENTATION_0);
prepareAxes(POSITION);
@@ -6881,11 +6886,11 @@
// Create displays.
prepareDisplay(DISPLAY_ORIENTATION_0, hdmi1);
- prepareSecondaryDisplay(ViewportType::VIEWPORT_EXTERNAL, hdmi2);
+ prepareSecondaryDisplay(ViewportType::EXTERNAL, hdmi2);
// Default device will reconfigure above, need additional reconfiguration for another device.
device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
- InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+ InputReaderConfiguration::CHANGE_DISPLAY_INFO);
// Two fingers down at default display.
int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
@@ -6992,7 +6997,7 @@
TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
constexpr uint8_t hdmi2 = 1;
const std::string secondaryUniqueId = "uniqueId2";
- constexpr ViewportType type = ViewportType::VIEWPORT_EXTERNAL;
+ constexpr ViewportType type = ViewportType::EXTERNAL;
mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
@@ -7206,7 +7211,7 @@
ASSERT_EQ(ADISPLAY_ID_DEFAULT, motionArgs.displayId);
// Expect the event to be sent to the external viewport if it is present.
- prepareSecondaryDisplay(ViewportType::VIEWPORT_EXTERNAL);
+ prepareSecondaryDisplay(ViewportType::EXTERNAL);
processPosition(mapper, 100, 100);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
@@ -7220,7 +7225,7 @@
protected:
void halfDisplayToCenterHorizontal(int32_t orientation) {
std::optional<DisplayViewport> internalViewport =
- mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
// Half display to (width/4, 0, width * 3/4, height) to make display has offset.
internalViewport->orientation = orientation;
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 8a282e2..e355594 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -153,12 +153,18 @@
SensorDeviceUtils::defaultResolutionForType(sensor.type);
}
- double promotedResolution = sensor.resolution;
- double promotedMaxRange = sensor.maxRange;
- if (fmod(promotedMaxRange, promotedResolution) != 0) {
- ALOGW("%s's max range %f is not a multiple of the resolution %f",
- sensor.name, sensor.maxRange, sensor.resolution);
- SensorDeviceUtils::quantizeValue(&sensor.maxRange, promotedResolution);
+ // Some sensors don't have a default resolution and will be left at 0.
+ // Don't crash in this case since CTS will verify that devices don't go to
+ // production with a resolution of 0.
+ if (sensor.resolution != 0) {
+ double promotedResolution = sensor.resolution;
+ double promotedMaxRange = sensor.maxRange;
+ if (fmod(promotedMaxRange, promotedResolution) != 0) {
+ ALOGW("%s's max range %f is not a multiple of the resolution %f",
+ sensor.name, sensor.maxRange, sensor.resolution);
+ SensorDeviceUtils::quantizeValue(
+ &sensor.maxRange, promotedResolution);
+ }
}
}
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 9b30dce..b4b5f98 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -272,11 +272,16 @@
}
}
-void SensorService::SensorEventConnection::incrementPendingFlushCount(int32_t handle) {
- Mutex::Autolock _l(mConnectionLock);
- if (mSensorInfo.count(handle) > 0) {
- FlushInfo& flushInfo = mSensorInfo[handle];
- flushInfo.mPendingFlushEventsToSend++;
+bool SensorService::SensorEventConnection::incrementPendingFlushCountIfHasAccess(int32_t handle) {
+ if (hasSensorAccess()) {
+ Mutex::Autolock _l(mConnectionLock);
+ if (mSensorInfo.count(handle) > 0) {
+ FlushInfo& flushInfo = mSensorInfo[handle];
+ flushInfo.mPendingFlushEventsToSend++;
+ }
+ return true;
+ } else {
+ return false;
}
}
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 8d5fcf7..8f2d5db 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -116,8 +116,9 @@
// for writing send the data from the cache.
virtual int handleEvent(int fd, int events, void* data);
- // Increment mPendingFlushEventsToSend for the given sensor handle.
- void incrementPendingFlushCount(int32_t handle);
+ // Increment mPendingFlushEventsToSend for the given handle if the connection has sensor access.
+ // Returns true if this connection does have sensor access.
+ bool incrementPendingFlushCountIfHasAccess(int32_t handle);
// Add or remove the file descriptor associated with the BitTube to the looper. If mDead is set
// to true or there are no more sensors for this connection, the file descriptor is removed if
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 3f88f77..aa0dc92 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1777,7 +1777,10 @@
if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0 || isVirtualSensor(handle)) {
// For older devices just increment pending flush count which will send a trivial
// flush complete event.
- connection->incrementPendingFlushCount(handle);
+ if (!connection->incrementPendingFlushCountIfHasAccess(handle)) {
+ ALOGE("flush called on an inaccessible sensor");
+ err = INVALID_OPERATION;
+ }
} else {
if (!canAccessSensor(sensor->getSensor(), "Tried flushing", opPackageName)) {
err = INVALID_OPERATION;
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index f0b0200..cf60b71 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -539,20 +539,6 @@
return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
}
-bool BufferLayer::latchUnsignaledBuffers() {
- static bool propertyLoaded = false;
- static bool latch = false;
- static std::mutex mutex;
- std::lock_guard<std::mutex> lock(mutex);
- if (!propertyLoaded) {
- char value[PROPERTY_VALUE_MAX] = {};
- property_get("debug.sf.latch_unsignaled", value, "0");
- latch = atoi(value);
- propertyLoaded = true;
- }
- return latch;
-}
-
// h/w composer set-up
bool BufferLayer::allTransactionsSignaled(nsecs_t expectedPresentTime) {
const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime);
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 26bfb49..2483abb 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -187,9 +187,6 @@
bool onPreComposition(nsecs_t) override;
void preparePerFrameCompositionState() override;
- // Loads the corresponding system property once per process
- static bool latchUnsignaledBuffers();
-
// Check all of the local sync points to ensure that all transactions
// which need to have been applied prior to the frame which is about to
// be latched have signaled
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 5f95182..89284f2 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -131,10 +131,6 @@
// -----------------------------------------------------------------------
bool BufferQueueLayer::fenceHasSignaled() const {
- if (latchUnsignaledBuffers()) {
- return true;
- }
-
if (!hasFrameUpdate()) {
return true;
}
@@ -328,9 +324,6 @@
}
uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
- mFlinger->mFrameTracer->traceFence(layerId, bufferID, currentFrameNumber,
- mQueueItems[0].mFenceTime,
- FrameTracer::FrameEvent::ACQUIRE_FENCE);
mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime,
FrameTracer::FrameEvent::LATCH);
@@ -397,8 +390,12 @@
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
const int32_t layerId = getSequence();
- mFlinger->mFrameTracer->traceTimestamp(layerId, item.mGraphicBuffer->getId(), item.mFrameNumber,
- systemTime(), FrameTracer::FrameEvent::QUEUE);
+ const uint64_t bufferId = item.mGraphicBuffer->getId();
+ mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
+ FrameTracer::FrameEvent::QUEUE);
+ mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
+ std::make_shared<FenceTime>(item.mFence),
+ FrameTracer::FrameEvent::ACQUIRE_FENCE);
ATRACE_CALL();
// Add this buffer from our internal queue tracker
@@ -464,8 +461,12 @@
}
const int32_t layerId = getSequence();
- mFlinger->mFrameTracer->traceTimestamp(layerId, item.mGraphicBuffer->getId(), item.mFrameNumber,
- systemTime(), FrameTracer::FrameEvent::QUEUE);
+ const uint64_t bufferId = item.mGraphicBuffer->getId();
+ mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
+ FrameTracer::FrameEvent::QUEUE);
+ mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
+ std::make_shared<FenceTime>(item.mFence),
+ FrameTracer::FrameEvent::ACQUIRE_FENCE);
mConsumer->onBufferAvailable(item);
}
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 790f2ec..884cc0c 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -422,10 +422,6 @@
// Interface implementation for BufferLayer
// -----------------------------------------------------------------------
bool BufferStateLayer::fenceHasSignaled() const {
- if (latchUnsignaledBuffers()) {
- return true;
- }
-
const bool fenceSignaled =
getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
if (!fenceSignaled) {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a34af17..70822bd 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -67,12 +67,14 @@
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
#include "TimeStats/TimeStats.h"
+#include "input/InputWindow.h"
#define DEBUG_RESIZE 0
namespace android {
using base::StringAppendF;
+using namespace android::flag_operators;
std::atomic<int32_t> Layer::sSequence{1};
@@ -80,7 +82,8 @@
: mFlinger(args.flinger),
mName(args.name),
mClientRef(args.client),
- mWindowType(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0)) {
+ mWindowType(static_cast<InputWindowInfo::Type>(
+ args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))) {
uint32_t layerFlags = 0;
if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
@@ -1820,7 +1823,7 @@
onRemovedFromCurrentState();
}
- if (callSetTransactionFlags || attachChildren()) {
+ if (attachChildren() || callSetTransactionFlags) {
setTransactionFlags(eTransactionNeeded);
}
return true;
@@ -1848,9 +1851,9 @@
if (client != nullptr && parentClient != client) {
if (child->mLayerDetached) {
child->mLayerDetached = false;
+ child->attachChildren();
changed = true;
}
- changed |= child->attachChildren();
}
}
@@ -2195,7 +2198,7 @@
}
LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags,
- const DisplayDevice* display) const {
+ const DisplayDevice* display) {
LayerProto* layerProto = layersProto.add_layers();
writeToProtoDrawingState(layerProto, traceFlags, display);
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
@@ -2216,7 +2219,7 @@
}
void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags,
- const DisplayDevice* display) const {
+ const DisplayDevice* display) {
ui::Transform transform = getTransform();
if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
@@ -2273,7 +2276,7 @@
}
void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
- uint32_t traceFlags) const {
+ uint32_t traceFlags) {
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
const State& state = useDrawing ? mDrawingState : mCurrentState;
@@ -2343,7 +2346,14 @@
}
if (traceFlags & SurfaceTracing::TRACE_INPUT) {
- LayerProtoHelper::writeToProto(state.inputInfo, state.touchableRegionCrop,
+ InputWindowInfo info;
+ if (useDrawing) {
+ info = fillInputInfo();
+ } else {
+ info = state.inputInfo;
+ }
+
+ LayerProtoHelper::writeToProto(info, state.touchableRegionCrop,
[&]() { return layerInfo->mutable_input_window_info(); });
}
@@ -2364,9 +2374,8 @@
mDrawingState.inputInfo.name = getName();
mDrawingState.inputInfo.ownerUid = mCallingUid;
mDrawingState.inputInfo.ownerPid = mCallingPid;
- mDrawingState.inputInfo.inputFeatures =
- InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL;
- mDrawingState.inputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
+ mDrawingState.inputInfo.inputFeatures = InputWindowInfo::Feature::NO_INPUT_CHANNEL;
+ mDrawingState.inputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL;
mDrawingState.inputInfo.displayId = getLayerStack();
}
@@ -2378,8 +2387,8 @@
}
ui::Transform t = getTransform();
- const float xScale = t.sx();
- const float yScale = t.sy();
+ 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) {
@@ -2568,7 +2577,7 @@
}
// Cloned layers shouldn't handle watch outside since their z order is not determined by
// WM or the client.
- mDrawingState.inputInfo.layoutParamsFlags &= ~InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH;
+ mDrawingState.inputInfo.flags &= ~InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH;
}
void Layer::updateClonedRelatives(const std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2c90c92..99b1bb1 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -286,7 +286,7 @@
void onFirstRef() override;
- int getWindowType() const { return mWindowType; }
+ InputWindowInfo::Type getWindowType() const { return mWindowType; }
void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; }
bool getPrimaryDisplayOnly() const { return mPrimaryDisplayOnly; }
@@ -528,19 +528,17 @@
bool isRemovedFromCurrentState() const;
- LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags,
- const DisplayDevice*) const;
+ LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags, const DisplayDevice*);
// Write states that are modified by the main thread. This includes drawing
// state as well as buffer data. This should be called in the main or tracing
// thread.
- void writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags,
- const DisplayDevice*) const;
+ void writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, const DisplayDevice*);
// Write drawing or current state. If writing current state, the caller should hold the
// external mStateLock. If writing drawing state, this function should be called on the
// main or tracing thread.
void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+ uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; }
virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; }
@@ -1040,7 +1038,7 @@
bool mChildrenChanged{false};
// Window types from WindowManager.LayoutParams
- const int mWindowType;
+ const InputWindowInfo::Type mWindowType;
private:
virtual void setTransformHint(ui::Transform::RotationFlags) {}
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index 0fe1421..dd65cf4 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -131,8 +131,12 @@
}
InputWindowInfoProto* proto = getInputWindowInfoProto();
- proto->set_layout_params_flags(inputInfo.layoutParamsFlags);
- proto->set_layout_params_type(inputInfo.layoutParamsType);
+ proto->set_layout_params_flags(inputInfo.flags.get());
+ using U = std::underlying_type_t<InputWindowInfo::Type>;
+ // TODO(b/129481165): This static assert can be safely removed once conversion warnings
+ // are re-enabled.
+ static_assert(std::is_same_v<U, int32_t>);
+ proto->set_layout_params_type(static_cast<U>(inputInfo.type));
LayerProtoHelper::writeToProto({inputInfo.frameLeft, inputInfo.frameTop, inputInfo.frameRight,
inputInfo.frameBottom},
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index f602412..d8477e7 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -106,41 +106,71 @@
drawSegment(Segment::Buttom, left, color, buffer, pixels);
}
-sp<GraphicBuffer> RefreshRateOverlay::SevenSegmentDrawer::drawNumber(int number,
- const half4& color) {
- if (number < 0 || number > 1000) return nullptr;
+std::vector<sp<GraphicBuffer>> RefreshRateOverlay::SevenSegmentDrawer::drawNumber(
+ int number, const half4& color, bool showSpinner) {
+ if (number < 0 || number > 1000) return {};
const auto hundreds = number / 100;
const auto tens = (number / 10) % 10;
const auto ones = number % 10;
- sp<GraphicBuffer> buffer =
- new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER |
- GRALLOC_USAGE_HW_TEXTURE,
- "RefreshRateOverlayBuffer");
- uint8_t* pixels;
- buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels));
- // Clear buffer content
- drawRect(Rect(BUFFER_WIDTH, BUFFER_HEIGHT), half4(0), buffer, pixels);
- int left = 0;
- if (hundreds != 0) {
- drawDigit(hundreds, left, color, buffer, pixels);
+ std::vector<sp<GraphicBuffer>> buffers;
+ const auto loopCount = showSpinner ? 6 : 1;
+ for (int i = 0; i < loopCount; i++) {
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1,
+ GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER |
+ GRALLOC_USAGE_HW_TEXTURE,
+ "RefreshRateOverlayBuffer");
+ uint8_t* pixels;
+ buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels));
+ // Clear buffer content
+ drawRect(Rect(BUFFER_WIDTH, BUFFER_HEIGHT), half4(0), buffer, pixels);
+ int left = 0;
+ if (hundreds != 0) {
+ drawDigit(hundreds, left, color, buffer, pixels);
+ }
left += DIGIT_WIDTH + DIGIT_SPACE;
- }
- if (tens != 0) {
- drawDigit(tens, left, color, buffer, pixels);
+ if (tens != 0) {
+ drawDigit(tens, left, color, buffer, pixels);
+ }
left += DIGIT_WIDTH + DIGIT_SPACE;
- }
- drawDigit(ones, left, color, buffer, pixels);
- buffer->unlock();
- return buffer;
+ drawDigit(ones, left, color, buffer, pixels);
+ left += DIGIT_WIDTH + DIGIT_SPACE;
+
+ if (showSpinner) {
+ switch (i) {
+ case 0:
+ drawSegment(Segment::Upper, left, color, buffer, pixels);
+ break;
+ case 1:
+ drawSegment(Segment::UpperRight, left, color, buffer, pixels);
+ break;
+ case 2:
+ drawSegment(Segment::LowerRight, left, color, buffer, pixels);
+ break;
+ case 3:
+ drawSegment(Segment::Buttom, left, color, buffer, pixels);
+ break;
+ case 4:
+ drawSegment(Segment::LowerLeft, left, color, buffer, pixels);
+ break;
+ case 5:
+ drawSegment(Segment::UpperLeft, left, color, buffer, pixels);
+ break;
+ }
+ }
+
+ buffer->unlock();
+ buffers.emplace_back(buffer);
+ }
+ return buffers;
}
-RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger)
- : mFlinger(flinger), mClient(new Client(&mFlinger)) {
+RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger, bool showSpinner)
+ : mFlinger(flinger), mClient(new Client(&mFlinger)), mShowSpinner(showSpinner) {
createLayer();
primeCache();
}
@@ -176,7 +206,7 @@
if (allRefreshRates.size() == 1) {
auto fps = allRefreshRates.begin()->second->getFps();
half4 color = {LOW_FPS_COLOR, ALPHA};
- mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
+ mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner));
return;
}
@@ -196,12 +226,12 @@
color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale);
color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale);
color.a = ALPHA;
- mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
+ mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner));
}
}
void RefreshRateOverlay::setViewport(ui::Size viewport) {
- Rect frame(viewport.width >> 3, viewport.height >> 5);
+ Rect frame((3 * viewport.width) >> 4, viewport.height >> 5);
frame.offsetBy(viewport.width >> 5, viewport.height >> 4);
mLayer->setFrame(frame);
@@ -209,7 +239,19 @@
}
void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
- auto buffer = mBufferCache[refreshRate.getFps()];
+ mCurrentFps = refreshRate.getFps();
+ auto buffer = mBufferCache[*mCurrentFps][mFrame];
+ mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {});
+
+ mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
+}
+
+void RefreshRateOverlay::onInvalidate() {
+ if (!mCurrentFps.has_value()) return;
+
+ const auto& buffers = mBufferCache[*mCurrentFps];
+ mFrame = (mFrame + 1) % buffers.size();
+ auto buffer = buffers[mFrame];
mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {});
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h
index 35c8020..1a8938f 100644
--- a/services/surfaceflinger/RefreshRateOverlay.h
+++ b/services/surfaceflinger/RefreshRateOverlay.h
@@ -38,15 +38,17 @@
class RefreshRateOverlay {
public:
- explicit RefreshRateOverlay(SurfaceFlinger&);
+ RefreshRateOverlay(SurfaceFlinger&, bool showSpinner);
void setViewport(ui::Size);
void changeRefreshRate(const RefreshRate&);
+ void onInvalidate();
private:
class SevenSegmentDrawer {
public:
- static sp<GraphicBuffer> drawNumber(int number, const half4& color);
+ static std::vector<sp<GraphicBuffer>> drawNumber(int number, const half4& color,
+ bool showSpinner);
static uint32_t getHeight() { return BUFFER_HEIGHT; }
static uint32_t getWidth() { return BUFFER_WIDTH; }
@@ -65,7 +67,7 @@
static constexpr uint32_t DIGIT_SPACE = 16;
static constexpr uint32_t BUFFER_HEIGHT = DIGIT_HEIGHT;
static constexpr uint32_t BUFFER_WIDTH =
- 3 * DIGIT_WIDTH + 2 * DIGIT_SPACE; // Digit|Space|Digit|Space|Digit
+ 4 * DIGIT_WIDTH + 3 * DIGIT_SPACE; // Digit|Space|Digit|Space|Digit|Space|Spinner
};
bool createLayer();
@@ -77,11 +79,14 @@
sp<IBinder> mIBinder;
sp<IGraphicBufferProducer> mGbp;
- std::unordered_map<int, sp<GraphicBuffer>> mBufferCache;
-
+ std::unordered_map<int, std::vector<sp<GraphicBuffer>>> mBufferCache;
+ std::optional<int> mCurrentFps;
+ int mFrame = 0;
static constexpr float ALPHA = 0.8f;
const half3 LOW_FPS_COLOR = half3(1.0f, 0.0f, 0.0f);
const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f);
+
+ const bool mShowSpinner;
};
} // namespace android
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index ecf2597..36433c2 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -20,6 +20,7 @@
#include "LayerHistory.h"
+#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/Timers.h>
@@ -183,4 +184,11 @@
mActiveLayersEnd = 0;
}
+
+std::string LayerHistory::dump() const {
+ std::lock_guard lock(mLock);
+ return base::StringPrintf("LayerHistory{size=%zu, active=%zu}", mLayerInfos.size(),
+ mActiveLayersEnd);
+}
+
} // namespace android::scheduler::impl
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 228b8a0..128699b 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -22,6 +22,7 @@
#include <memory>
#include <mutex>
+#include <string>
#include <utility>
#include <vector>
@@ -71,6 +72,7 @@
virtual Summary summarize(nsecs_t now) = 0;
virtual void clear() = 0;
+ virtual std::string dump() const = 0;
};
namespace impl {
@@ -97,6 +99,7 @@
android::scheduler::LayerHistory::Summary summarize(nsecs_t now) override;
void clear() override;
+ std::string dump() const override;
private:
friend class android::scheduler::LayerHistoryTest;
@@ -155,6 +158,7 @@
android::scheduler::LayerHistory::Summary summarize(nsecs_t /*now*/) override;
void clear() override;
+ std::string dump() const override;
private:
friend android::scheduler::LayerHistoryTestV2;
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index aa04bd7..37e67e1 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -20,6 +20,7 @@
#include "LayerHistory.h"
+#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/Timers.h>
@@ -31,9 +32,8 @@
#include <utility>
#include "../Layer.h"
-#include "SchedulerUtils.h"
-
#include "LayerInfoV2.h"
+#include "SchedulerUtils.h"
namespace android::scheduler::impl {
@@ -214,4 +214,10 @@
}
}
+std::string LayerHistoryV2::dump() const {
+ std::lock_guard lock(mLock);
+ return base::StringPrintf("LayerHistoryV2{size=%zu, active=%zu}", mLayerInfos.size(),
+ mActiveLayersEnd);
+}
+
} // namespace android::scheduler::impl
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 053d0a7..8661b6e 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -212,10 +212,8 @@
bool inPrimaryRange =
scores[i].first->inPolicy(policy->primaryRange.min, policy->primaryRange.max);
if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
- !(layer.focused &&
- (layer.vote == LayerVoteType::ExplicitDefault ||
- layer.vote == LayerVoteType::ExplicitExactOrMultiple))) {
- // Only focused layers with explicit frame rate settings are allowed to score
+ !(layer.focused && layer.vote == LayerVoteType::ExplicitDefault)) {
+ // Only focused layers with ExplicitDefault frame rate settings are allowed to score
// refresh rates outside the primary range.
continue;
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 27bf0ec..eed8486 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -280,6 +280,11 @@
RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
HwcConfigIndexType currentConfigId);
+ // Returns whether switching configs (refresh rate or resolution) is possible.
+ // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the configs only
+ // differ in resolution.
+ bool canSwitch() const { return mRefreshRates.size() > 1; }
+
// Class to enumerate options around toggling the kernel timer on and off. We have an option
// for no change to avoid extra calls to kernel.
enum class KernelIdleTimerAction {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 5c0ba01..8dd4b0a 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -61,6 +61,7 @@
} while (false)
namespace android {
+namespace {
std::unique_ptr<DispSync> createDispSync(bool supportKernelTimer) {
// TODO (140302863) remove this and use the vsync_reactor system.
@@ -97,25 +98,27 @@
}
}
+const char* toContentDetectionString(bool useContentDetection, bool useContentDetectionV2) {
+ if (!useContentDetection) return "off";
+ return useContentDetectionV2 ? "V2" : "V1";
+}
+
+} // namespace
+
Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
- const scheduler::RefreshRateConfigs& refreshRateConfig,
+ const scheduler::RefreshRateConfigs& refreshRateConfigs,
ISchedulerCallback& schedulerCallback, bool useContentDetectionV2,
bool useContentDetection)
: mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)),
mPrimaryDispSync(createDispSync(mSupportKernelTimer)),
mEventControlThread(new impl::EventControlThread(std::move(function))),
+ mLayerHistory(createLayerHistory(refreshRateConfigs, useContentDetectionV2)),
mSchedulerCallback(schedulerCallback),
- mRefreshRateConfigs(refreshRateConfig),
+ mRefreshRateConfigs(refreshRateConfigs),
mUseContentDetection(useContentDetection),
mUseContentDetectionV2(useContentDetectionV2) {
using namespace sysprop;
- if (mUseContentDetectionV2) {
- mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>(refreshRateConfig);
- } else {
- mLayerHistory = std::make_unique<scheduler::impl::LayerHistory>();
- }
-
const int setIdleTimerMs = property_get_int32("debug.sf.set_idle_timer_ms", 0);
if (const auto millis = setIdleTimerMs ? setIdleTimerMs : set_idle_timer_ms(0); millis > 0) {
@@ -149,11 +152,13 @@
Scheduler::Scheduler(std::unique_ptr<DispSync> primaryDispSync,
std::unique_ptr<EventControlThread> eventControlThread,
const scheduler::RefreshRateConfigs& configs,
- ISchedulerCallback& schedulerCallback, bool useContentDetectionV2,
+ ISchedulerCallback& schedulerCallback,
+ std::unique_ptr<LayerHistory> layerHistory, bool useContentDetectionV2,
bool useContentDetection)
: mSupportKernelTimer(false),
mPrimaryDispSync(std::move(primaryDispSync)),
mEventControlThread(std::move(eventControlThread)),
+ mLayerHistory(std::move(layerHistory)),
mSchedulerCallback(schedulerCallback),
mRefreshRateConfigs(configs),
mUseContentDetection(useContentDetection),
@@ -166,6 +171,17 @@
mIdleTimer.reset();
}
+std::unique_ptr<LayerHistory> Scheduler::createLayerHistory(
+ const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2) {
+ if (!configs.canSwitch()) return nullptr;
+
+ if (useContentDetectionV2) {
+ return std::make_unique<scheduler::impl::LayerHistoryV2>(configs);
+ }
+
+ return std::make_unique<scheduler::impl::LayerHistory>();
+}
+
DispSync& Scheduler::getPrimaryDispSync() {
return *mPrimaryDispSync;
}
@@ -416,7 +432,7 @@
const auto minFps = mRefreshRateConfigs.getMinRefreshRate().getFps();
const auto maxFps = mRefreshRateConfigs.getMaxRefreshRate().getFps();
- if (layer->getWindowType() == InputWindowInfo::TYPE_STATUS_BAR) {
+ if (layer->getWindowType() == InputWindowInfo::Type::STATUS_BAR) {
mLayerHistory->registerLayer(layer, minFps, maxFps,
scheduler::LayerHistory::LayerVoteType::NoVote);
} else if (!mUseContentDetection) {
@@ -429,12 +445,12 @@
// In V1 of content detection, all layers are registered as Heuristic (unless it's
// wallpaper).
const auto highFps =
- layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER ? minFps : maxFps;
+ layer->getWindowType() == InputWindowInfo::Type::WALLPAPER ? minFps : maxFps;
mLayerHistory->registerLayer(layer, minFps, highFps,
scheduler::LayerHistory::LayerVoteType::Heuristic);
} else {
- if (layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER) {
+ if (layer->getWindowType() == InputWindowInfo::Type::WALLPAPER) {
// Running Wallpaper at Min is considered as part of content detection.
mLayerHistory->registerLayer(layer, minFps, maxFps,
scheduler::LayerHistory::LayerVoteType::Min);
@@ -499,16 +515,7 @@
}
void Scheduler::notifyTouchEvent() {
- if (!mTouchTimer) return;
-
- // Touch event will boost the refresh rate to performance.
- // Clear Layer History to get fresh FPS detection.
- // NOTE: Instead of checking all the layers, we should be checking the layer
- // that is currently on top. b/142507166 will give us this capability.
- std::lock_guard<std::mutex> lock(mFeatureStateLock);
- if (mLayerHistory) {
- // Layer History will be cleared based on RefreshRateConfigs::getBestRefreshRate
-
+ if (mTouchTimer) {
mTouchTimer->reset();
if (mSupportKernelTimer && mIdleTimer) {
@@ -564,8 +571,14 @@
void Scheduler::touchTimerCallback(TimerState state) {
const TouchState touch = state == TimerState::Reset ? TouchState::Active : TouchState::Inactive;
+ // Touch event will boost the refresh rate to performance.
+ // Clear layer history to get fresh FPS detection.
+ // NOTE: Instead of checking all the layers, we should be checking the layer
+ // that is currently on top. b/142507166 will give us this capability.
if (handleTimerStateChanged(&mFeatures.touch, touch)) {
- mLayerHistory->clear();
+ if (mLayerHistory) {
+ mLayerHistory->clear();
+ }
}
ATRACE_INT("TouchState", static_cast<int>(touch));
}
@@ -577,14 +590,13 @@
void Scheduler::dump(std::string& result) const {
using base::StringAppendF;
- const char* const states[] = {"off", "on"};
- StringAppendF(&result, "+ Idle timer: %s\n",
- mIdleTimer ? mIdleTimer->dump().c_str() : states[0]);
+ StringAppendF(&result, "+ Idle timer: %s\n", mIdleTimer ? mIdleTimer->dump().c_str() : "off");
StringAppendF(&result, "+ Touch timer: %s\n",
- mTouchTimer ? mTouchTimer->dump().c_str() : states[0]);
- StringAppendF(&result, "+ Use content detection: %s\n\n",
- sysprop::use_content_detection_for_refresh_rate(false) ? "on" : "off");
+ mTouchTimer ? mTouchTimer->dump().c_str() : "off");
+ StringAppendF(&result, "+ Content detection: %s %s\n\n",
+ toContentDetectionString(mUseContentDetection, mUseContentDetectionV2),
+ mLayerHistory ? mLayerHistory->dump().c_str() : "(no layer history)");
}
template <class T>
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 730ea8f..5fee4b4 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -174,8 +174,11 @@
// Used by tests to inject mocks.
Scheduler(std::unique_ptr<DispSync>, std::unique_ptr<EventControlThread>,
- const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback,
- bool useContentDetectionV2, bool useContentDetection);
+ const scheduler::RefreshRateConfigs&, ISchedulerCallback&,
+ std::unique_ptr<LayerHistory>, bool useContentDetectionV2, bool useContentDetection);
+
+ static std::unique_ptr<LayerHistory> createLayerHistory(const scheduler::RefreshRateConfigs&,
+ bool useContentDetectionV2);
std::unique_ptr<VSyncSource> makePrimaryDispSyncSource(const char* name, nsecs_t phaseOffsetNs);
@@ -231,7 +234,7 @@
std::unique_ptr<EventControlThread> mEventControlThread;
// Used to choose refresh rate if content detection is enabled.
- std::unique_ptr<LayerHistory> mLayerHistory;
+ const std::unique_ptr<LayerHistory> mLayerHistory;
// Timer that records time between requests for next vsync.
std::optional<scheduler::OneShotTimer> mIdleTimer;
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
index a596bce..2a6fd05 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
@@ -243,7 +243,8 @@
std::vector<Invocation> invocations;
{
std::lock_guard<decltype(mMutex)> lk(mMutex);
- mLastTimerCallback = mTimeKeeper->now();
+ auto const now = mTimeKeeper->now();
+ mLastTimerCallback = now;
for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
auto& callback = it->second;
auto const wakeupTime = callback->wakeupTime();
@@ -251,7 +252,8 @@
continue;
}
- if (*wakeupTime < mIntendedWakeupTime + mTimerSlack) {
+ auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
+ if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
callback->executing();
invocations.emplace_back(
Invocation{callback, *callback->lastExecutedVsyncTarget(), *wakeupTime});
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index ab5773d..61f3fbb 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -255,21 +255,9 @@
}
}
-bool VSyncPredictor::needsMoreSamples(nsecs_t now) const {
- using namespace std::literals::chrono_literals;
+bool VSyncPredictor::needsMoreSamples() const {
std::lock_guard<std::mutex> lk(mMutex);
- bool needsMoreSamples = true;
- if (mTimestamps.size() >= kMinimumSamplesForPrediction) {
- nsecs_t constexpr aLongTime =
- std::chrono::duration_cast<std::chrono::nanoseconds>(500ms).count();
- if (!(mLastTimestampIndex < 0 || mTimestamps.empty())) {
- auto const lastTimestamp = mTimestamps[mLastTimestampIndex];
- needsMoreSamples = !((lastTimestamp + aLongTime) > now);
- }
- }
-
- ATRACE_INT("VSP-moreSamples", needsMoreSamples);
- return needsMoreSamples;
+ return mTimestamps.size() < kMinimumSamplesForPrediction;
}
void VSyncPredictor::resetModel() {
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index 3ca878d..5f3c418 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -52,11 +52,10 @@
*/
void setPeriod(nsecs_t period) final;
- /* Query if the model is in need of more samples to make a prediction at timePoint.
- * \param [in] timePoint The timePoint to inquire of.
+ /* Query if the model is in need of more samples to make a prediction.
* \return True, if model would benefit from more samples, False if not.
*/
- bool needsMoreSamples(nsecs_t timePoint) const;
+ bool needsMoreSamples() const final;
std::tuple<nsecs_t /* slope */, nsecs_t /* intercept */> getVSyncPredictionModel() const;
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index c743de0..efa8bab 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -233,6 +233,7 @@
}
void VSyncReactor::startPeriodTransition(nsecs_t newPeriod) {
+ ATRACE_CALL();
mPeriodConfirmationInProgress = true;
mPeriodTransitioningTo = newPeriod;
mMoreSamplesNeeded = true;
@@ -240,8 +241,7 @@
}
void VSyncReactor::endPeriodTransition() {
- setIgnorePresentFencesInternal(false);
- mMoreSamplesNeeded = false;
+ ATRACE_CALL();
mPeriodTransitioningTo.reset();
mPeriodConfirmationInProgress = false;
mLastHwVsync.reset();
@@ -254,6 +254,8 @@
if (!mSupportKernelIdleTimer && period == getPeriod()) {
endPeriodTransition();
+ setIgnorePresentFencesInternal(false);
+ mMoreSamplesNeeded = false;
} else {
startPeriodTransition(period);
}
@@ -303,6 +305,7 @@
std::lock_guard<std::mutex> lk(mMutex);
if (periodConfirmed(timestamp, hwcVsyncPeriod)) {
+ ATRACE_NAME("VSR: period confirmed");
if (mPeriodTransitioningTo) {
mTracker->setPeriod(*mPeriodTransitioningTo);
for (auto& entry : mCallbacks) {
@@ -310,17 +313,29 @@
}
*periodFlushed = true;
}
+
+ if (mLastHwVsync) {
+ mTracker->addVsyncTimestamp(*mLastHwVsync);
+ }
+ mTracker->addVsyncTimestamp(timestamp);
+
endPeriodTransition();
+ mMoreSamplesNeeded = mTracker->needsMoreSamples();
} else if (mPeriodConfirmationInProgress) {
+ ATRACE_NAME("VSR: still confirming period");
mLastHwVsync = timestamp;
mMoreSamplesNeeded = true;
*periodFlushed = false;
} else {
- mMoreSamplesNeeded = false;
+ ATRACE_NAME("VSR: adding sample");
*periodFlushed = false;
+ mTracker->addVsyncTimestamp(timestamp);
+ mMoreSamplesNeeded = mTracker->needsMoreSamples();
}
- mTracker->addVsyncTimestamp(timestamp);
+ if (!mMoreSamplesNeeded) {
+ setIgnorePresentFencesInternal(false);
+ }
return mMoreSamplesNeeded;
}
diff --git a/services/surfaceflinger/Scheduler/VSyncTracker.h b/services/surfaceflinger/Scheduler/VSyncTracker.h
index 05a6fc3..107c540 100644
--- a/services/surfaceflinger/Scheduler/VSyncTracker.h
+++ b/services/surfaceflinger/Scheduler/VSyncTracker.h
@@ -66,6 +66,8 @@
/* Inform the tracker that the samples it has are not accurate for prediction. */
virtual void resetModel() = 0;
+ virtual bool needsMoreSamples() const = 0;
+
virtual void dump(std::string& result) const = 0;
protected:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1c27759..7d5cb67 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -30,6 +30,8 @@
#include <android/hardware/configstore/1.1/types.h>
#include <android/hardware/power/Boost.h>
#include <android/native_window.h>
+#include <android/os/BnSetInputWindowsListener.h>
+#include <android/os/IInputFlinger.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
@@ -57,7 +59,7 @@
#include <gui/LayerMetadata.h>
#include <gui/LayerState.h>
#include <gui/Surface.h>
-#include <input/IInputFlinger.h>
+#include <hidl/ServiceManagement.h>
#include <layerproto/LayerProtoParser.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
@@ -88,6 +90,7 @@
#include <functional>
#include <mutex>
#include <optional>
+#include <type_traits>
#include <unordered_map>
#include "BufferLayer.h"
@@ -255,6 +258,21 @@
} // namespace anonymous
+struct SetInputWindowsListener : os::BnSetInputWindowsListener {
+ explicit SetInputWindowsListener(std::function<void()> listenerCb) : mListenerCb(listenerCb) {}
+
+ binder::Status onSetInputWindowsFinished() override;
+
+ std::function<void()> mListenerCb;
+};
+
+binder::Status SetInputWindowsListener::onSetInputWindowsFinished() {
+ if (mListenerCb != nullptr) {
+ mListenerCb();
+ }
+ return binder::Status::ok();
+}
+
// ---------------------------------------------------------------------------
const String16 sHardwareTest("android.permission.HARDWARE_TEST");
@@ -320,7 +338,9 @@
mEventQueue(mFactory.createMessageQueue()),
mCompositionEngine(mFactory.createCompositionEngine()),
mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
- mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) {}
+ mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) {
+ mSetInputWindowsListener = new SetInputWindowsListener([&]() { setInputWindowsFinished(); });
+}
SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) {
ALOGI("SurfaceFlinger is starting");
@@ -398,10 +418,6 @@
int debugDdms = atoi(value);
ALOGI_IF(debugDdms, "DDMS debugging not supported");
- property_get("debug.sf.disable_backpressure", value, "0");
- mPropagateBackpressure = !atoi(value);
- ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");
-
property_get("debug.sf.enable_gl_backpressure", value, "0");
mPropagateBackpressureClientComposition = atoi(value);
ALOGI_IF(mPropagateBackpressureClientComposition,
@@ -447,13 +463,15 @@
// deriving the setting from the set service name, but it
// would be brittle if the name that's not 'default' is used
// for production purposes later on.
- setenv("TREBLE_TESTING_OVERRIDE", "true", true);
+ android::hardware::details::setTrebleTestingOverride(true);
}
useFrameRateApi = use_frame_rate_api(true);
mKernelIdleTimerEnabled = mSupportKernelIdleTimer = sysprop::support_kernel_idle_timer(false);
base::SetProperty(KERNEL_IDLE_TIMER_PROP, mKernelIdleTimerEnabled ? "true" : "false");
+
+ mRefreshRateOverlaySpinner = property_get_bool("sf.debug.show_refresh_rate_overlay_spinner", 0);
}
SurfaceFlinger::~SurfaceFlinger() = default;
@@ -606,13 +624,6 @@
if (mWindowManager != 0) {
mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
}
- sp<IBinder> input(defaultServiceManager()->getService(
- String16("inputflinger")));
- if (input == nullptr) {
- ALOGE("Failed to link to input service");
- } else {
- mInputFlinger = interface_cast<IInputFlinger>(input);
- }
if (mVrFlinger) {
mVrFlinger->OnBootFinished();
@@ -627,7 +638,15 @@
LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
- static_cast<void>(schedule([this] {
+ sp<IBinder> input(defaultServiceManager()->getService(String16("inputflinger")));
+
+ static_cast<void>(schedule([=] {
+ if (input == nullptr) {
+ ALOGE("Failed to link to input service");
+ } else {
+ mInputFlinger = interface_cast<os::IInputFlinger>(input);
+ }
+
readPersistentProperties();
mPowerAdvisor.onBootFinished();
mBootStage = BootStage::FINISHED;
@@ -1841,10 +1860,7 @@
// for the present fence to fire instead of just giving up on this frame to handle cases
// where present fence is just about to get signaled.
const int graceTimeForPresentFenceMs =
- (mPropagateBackpressure &&
- (mPropagateBackpressureClientComposition || !mHadClientComposition))
- ? 1
- : 0;
+ (mPropagateBackpressureClientComposition || !mHadClientComposition) ? 1 : 0;
// Pending frames may trigger backpressure propagation.
const TracedOrdinal<bool> framePending = {"PrevFramePending",
@@ -1903,7 +1919,7 @@
ON_MAIN_THREAD(setActiveConfigInternal());
}
- if (framePending && mPropagateBackpressure) {
+ if (framePending) {
if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) {
signalLayerUpdate();
return;
@@ -1951,6 +1967,12 @@
mTracingEnabledChanged = false;
}
+ if (mRefreshRateOverlaySpinner) {
+ if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) {
+ mRefreshRateOverlay->onInvalidate();
+ }
+ }
+
bool refreshNeeded;
{
ConditionalLockGuard<std::mutex> lock(mTracingLock, mTracingEnabled);
@@ -2897,19 +2919,19 @@
}
void SurfaceFlinger::updateInputWindowInfo() {
- std::vector<InputWindowInfo> inputHandles;
+ std::vector<InputWindowInfo> inputInfos;
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (layer->needsInputInfo()) {
// When calculating the screen bounds we ignore the transparent region since it may
// result in an unwanted offset.
- inputHandles.push_back(layer->fillInputInfo());
+ inputInfos.push_back(layer->fillInputInfo());
}
});
- mInputFlinger->setInputWindows(inputHandles,
- mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
- : nullptr);
+ mInputFlinger->setInputWindows(inputInfos,
+ mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
+ : nullptr);
}
void SurfaceFlinger::commitInputWindowCommands() {
@@ -3812,7 +3834,7 @@
}
if (what & layer_state_t::eInputInfoChanged) {
if (privileged) {
- layer->setInputInfo(s.inputInfo);
+ layer->setInputInfo(*s.inputHandle->getInfo());
flags |= eTraversalNeeded;
} else {
ALOGE("Attempt to update InputWindowInfo without permission ACCESS_SURFACE_FLINGER");
@@ -3968,7 +3990,12 @@
if (metadata.has(METADATA_WINDOW_TYPE)) {
int32_t windowType = metadata.getInt32(METADATA_WINDOW_TYPE, 0);
if (windowType == 441731) {
- metadata.setInt32(METADATA_WINDOW_TYPE, InputWindowInfo::TYPE_NAVIGATION_BAR_PANEL);
+ using U = std::underlying_type_t<InputWindowInfo::Type>;
+ // TODO(b/129481165): This static assert can be safely removed once conversion warnings
+ // are re-enabled.
+ static_assert(std::is_same_v<U, int32_t>);
+ metadata.setInt32(METADATA_WINDOW_TYPE,
+ static_cast<U>(InputWindowInfo::Type::NAVIGATION_BAR_PANEL));
primaryDisplayOnly = true;
}
}
@@ -6064,10 +6091,6 @@
}
}
-void SurfaceFlinger::SetInputWindowsListener::onSetInputWindowsFinished() {
- mFlinger->setInputWindowsFinished();
-}
-
wp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
Mutex::Autolock _l(mStateLock);
return fromHandleLocked(handle);
@@ -6244,7 +6267,7 @@
static_cast<void>(schedule([=] {
std::unique_ptr<RefreshRateOverlay> overlay;
if (enable) {
- overlay = std::make_unique<RefreshRateOverlay>(*this);
+ overlay = std::make_unique<RefreshRateOverlay>(*this, mRefreshRateOverlaySpinner);
}
{
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e9a2905..d56321d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -33,7 +33,6 @@
#include <gui/ITransactionCompletedListener.h>
#include <gui/LayerState.h>
#include <gui/OccupancyTracker.h>
-#include <input/ISetInputWindowsListener.h>
#include <layerproto/LayerProtoHeader.h>
#include <math/mat4.h>
#include <renderengine/LayerSettings.h>
@@ -89,8 +88,8 @@
class Client;
class EventThread;
class HWComposer;
+struct SetInputWindowsListener;
class IGraphicBufferProducer;
-class IInputFlinger;
class Layer;
class MessageBase;
class RefreshRateOverlay;
@@ -99,6 +98,10 @@
class TimeStats;
class FrameTracer;
+namespace os {
+ class IInputFlinger;
+}
+
namespace compositionengine {
class DisplaySurface;
class OutputLayer;
@@ -336,6 +339,7 @@
// If set, disables reusing client composition buffers. This can be set by
// debug.sf.disable_client_composition_cache
bool mDisableClientCompositionCache = false;
+ void setInputWindowsFinished();
private:
friend class BufferLayer;
@@ -543,6 +547,8 @@
bool mKernelIdleTimerEnabled = false;
// Keeps track of whether the kernel timer is supported on the SF side.
bool mSupportKernelIdleTimer = false;
+ // Show spinner with refresh rate overlay
+ bool mRefreshRateOverlaySpinner = false;
/* ------------------------------------------------------------------------
* Message handling
*/
@@ -606,7 +612,6 @@
void updateInputFlinger();
void updateInputWindowInfo();
void commitInputWindowCommands() REQUIRES(mStateLock);
- void setInputWindowsFinished();
void updateCursorAsync();
void initScheduler(DisplayId primaryDisplayId);
@@ -1083,7 +1088,6 @@
bool mDebugDisableTransformHint = false;
volatile nsecs_t mDebugInTransaction = 0;
bool mForceFullDamage = false;
- bool mPropagateBackpressure = true;
bool mPropagateBackpressureClientComposition = false;
std::unique_ptr<SurfaceInterceptor> mInterceptor;
@@ -1255,21 +1259,12 @@
const float mInternalDisplayDensity;
const float mEmulatedDisplayDensity;
- sp<IInputFlinger> mInputFlinger;
+ sp<os::IInputFlinger> mInputFlinger;
InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock);
// Should only be accessed by the main thread.
InputWindowCommands mInputWindowCommands;
- struct SetInputWindowsListener : BnSetInputWindowsListener {
- explicit SetInputWindowsListener(sp<SurfaceFlinger> flinger)
- : mFlinger(std::move(flinger)) {}
-
- void onSetInputWindowsFinished() override;
-
- const sp<SurfaceFlinger> mFlinger;
- };
-
- const sp<SetInputWindowsListener> mSetInputWindowsListener = new SetInputWindowsListener(this);
+ sp<SetInputWindowsListener> mSetInputWindowsListener;
bool mPendingSyncInputWindows GUARDED_BY(mStateLock) = false;
Hwc2::impl::PowerAdvisor mPowerAdvisor;
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index fe2af80..c96dfc7 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -21,6 +21,7 @@
"CommonTypes_test.cpp",
"Credentials_test.cpp",
"DereferenceSurfaceControl_test.cpp",
+ "DetachChildren_test.cpp",
"DisplayConfigs_test.cpp",
"EffectLayer_test.cpp",
"InvalidHandles_test.cpp",
diff --git a/services/surfaceflinger/tests/DetachChildren_test.cpp b/services/surfaceflinger/tests/DetachChildren_test.cpp
new file mode 100644
index 0000000..b6c2fe2
--- /dev/null
+++ b/services/surfaceflinger/tests/DetachChildren_test.cpp
@@ -0,0 +1,322 @@
+/*
+ * 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.
+ */
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include "LayerTransactionTest.h"
+
+namespace android {
+
+class DetachChildren : public LayerTransactionTest {
+protected:
+ virtual void SetUp() {
+ LayerTransactionTest::SetUp();
+
+ mMainSurface = createLayer(String8("Main Test Surface"), mMainSurfaceBounds.width(),
+ mMainSurfaceBounds.height(), 0, mBlackBgSurface.get());
+
+ ASSERT_TRUE(mMainSurface != nullptr);
+ ASSERT_TRUE(mMainSurface->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(mMainSurface, mMainSurfaceColor);
+
+ asTransaction([&](Transaction& t) {
+ t.setLayer(mMainSurface, INT32_MAX - 1)
+ .setPosition(mMainSurface, mMainSurfaceBounds.left, mMainSurfaceBounds.top)
+ .show(mMainSurface);
+ });
+ }
+
+ virtual void TearDown() {
+ LayerTransactionTest::TearDown();
+ mMainSurface = 0;
+ }
+
+ sp<SurfaceControl> mMainSurface;
+ Color mMainSurfaceColor = {195, 63, 63, 255};
+ Rect mMainSurfaceBounds = Rect(64, 64, 128, 128);
+ std::unique_ptr<ScreenCapture> mCapture;
+};
+
+TEST_F(DetachChildren, RelativesAreNotDetached) {
+ Color relativeColor = {10, 10, 10, 255};
+ Rect relBounds = Rect(64, 64, 74, 74);
+
+ sp<SurfaceControl> relative =
+ createLayer(String8("relativeTestSurface"), relBounds.width(), relBounds.height(), 0);
+ TransactionUtils::fillSurfaceRGBA8(relative, relativeColor);
+
+ Transaction{}
+ .setRelativeLayer(relative, mMainSurface->getHandle(), 1)
+ .setPosition(relative, relBounds.left, relBounds.top)
+ .apply();
+
+ {
+ // The relative should be on top of the FG control.
+ mCapture = screenshot();
+ mCapture->expectColor(relBounds, relativeColor);
+ }
+ Transaction{}.detachChildren(mMainSurface).apply();
+
+ {
+ // Nothing should change at this point.
+ mCapture = screenshot();
+ mCapture->expectColor(relBounds, relativeColor);
+ }
+
+ Transaction{}.hide(relative).apply();
+
+ {
+ // Ensure that the relative was actually hidden, rather than
+ // being left in the detached but visible state.
+ mCapture = screenshot();
+ mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
+ }
+}
+
+TEST_F(DetachChildren, DetachChildrenSameClient) {
+ Color childColor = {200, 200, 200, 255};
+ Rect childBounds = Rect(74, 74, 84, 84);
+ sp<SurfaceControl> child = createLayer(String8("Child surface"), childBounds.width(),
+ childBounds.height(), 0, mMainSurface.get());
+ ASSERT_TRUE(child->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(child, childColor);
+
+ asTransaction([&](Transaction& t) {
+ t.show(child);
+ t.setPosition(child, childBounds.left - mMainSurfaceBounds.left,
+ childBounds.top - mMainSurfaceBounds.top);
+ });
+
+ {
+ mCapture = screenshot();
+ // Expect main color around the child surface
+ mCapture->expectBorder(childBounds, mMainSurfaceColor);
+ mCapture->expectColor(childBounds, childColor);
+ }
+
+ asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
+
+ asTransaction([&](Transaction& t) { t.hide(child); });
+
+ // Since the child has the same client as the parent, it will not get
+ // detached and will be hidden.
+ {
+ mCapture = screenshot();
+ mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
+ }
+}
+
+TEST_F(DetachChildren, DetachChildrenDifferentClient) {
+ Color childColor = {200, 200, 200, 255};
+ Rect childBounds = Rect(74, 74, 84, 84);
+
+ sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
+ sp<SurfaceControl> childNewClient =
+ createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
+ childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
+ ASSERT_TRUE(childNewClient->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
+
+ asTransaction([&](Transaction& t) {
+ t.show(childNewClient);
+ t.setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
+ childBounds.top - mMainSurfaceBounds.top);
+ });
+
+ {
+ mCapture = screenshot();
+ // Expect main color around the child surface
+ mCapture->expectBorder(childBounds, mMainSurfaceColor);
+ mCapture->expectColor(childBounds, childColor);
+ }
+
+ asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
+
+ asTransaction([&](Transaction& t) { t.hide(childNewClient); });
+
+ // Nothing should have changed.
+ {
+ mCapture = screenshot();
+ mCapture->expectBorder(childBounds, mMainSurfaceColor);
+ mCapture->expectColor(childBounds, childColor);
+ }
+}
+
+TEST_F(DetachChildren, DetachChildrenThenAttach) {
+ Color childColor = {200, 200, 200, 255};
+ Rect childBounds = Rect(74, 74, 84, 84);
+
+ sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
+ sp<SurfaceControl> childNewClient =
+ createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
+ childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
+ ASSERT_TRUE(childNewClient->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
+
+ Transaction()
+ .show(childNewClient)
+ .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
+ childBounds.top - mMainSurfaceBounds.top)
+ .apply();
+
+ {
+ mCapture = screenshot();
+ // Expect main color around the child surface
+ mCapture->expectBorder(childBounds, mMainSurfaceColor);
+ mCapture->expectColor(childBounds, childColor);
+ }
+
+ Transaction().detachChildren(mMainSurface).apply();
+ Transaction().hide(childNewClient).apply();
+
+ // Nothing should have changed.
+ {
+ mCapture = screenshot();
+ mCapture->expectBorder(childBounds, mMainSurfaceColor);
+ mCapture->expectColor(childBounds, childColor);
+ }
+
+ Color newParentColor = Color::RED;
+ Rect newParentBounds = Rect(20, 20, 52, 52);
+ sp<SurfaceControl> newParentSurface =
+ createLayer(String8("New Parent Surface"), newParentBounds.width(),
+ newParentBounds.height(), 0);
+ TransactionUtils::fillSurfaceRGBA8(newParentSurface, newParentColor);
+ Transaction()
+ .setLayer(newParentSurface, INT32_MAX - 1)
+ .show(newParentSurface)
+ .setPosition(newParentSurface, newParentBounds.left, newParentBounds.top)
+ .reparent(childNewClient, newParentSurface->getHandle())
+ .apply();
+ {
+ mCapture = screenshot();
+ // Child is now hidden.
+ mCapture->expectColor(newParentBounds, newParentColor);
+ }
+}
+
+TEST_F(DetachChildren, DetachChildrenWithDeferredTransaction) {
+ Color childColor = {200, 200, 200, 255};
+ Rect childBounds = Rect(74, 74, 84, 84);
+
+ sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
+ sp<SurfaceControl> childNewClient =
+ createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
+ childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
+ ASSERT_TRUE(childNewClient->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
+
+ Transaction()
+ .show(childNewClient)
+ .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
+ childBounds.top - mMainSurfaceBounds.top)
+ .apply();
+
+ {
+ mCapture = screenshot();
+ mCapture->expectBorder(childBounds, mMainSurfaceColor);
+ mCapture->expectColor(childBounds, childColor);
+ }
+
+ Transaction()
+ .deferTransactionUntil_legacy(childNewClient, mMainSurface->getHandle(),
+ mMainSurface->getSurface()->getNextFrameNumber())
+ .apply();
+ Transaction().detachChildren(mMainSurface).apply();
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED,
+ mMainSurfaceBounds.width(),
+ mMainSurfaceBounds.height()));
+
+ // BufferLayer can still dequeue buffers even though there's a detached layer with a
+ // deferred transaction.
+ {
+ SCOPED_TRACE("new buffer");
+ mCapture = screenshot();
+ mCapture->expectBorder(childBounds, Color::RED);
+ mCapture->expectColor(childBounds, childColor);
+ }
+}
+
+TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) {
+ Color childColor = {200, 200, 200, 255};
+ Rect childBounds = Rect(74, 74, 94, 94);
+ Color grandchildColor = Color::RED;
+ Rect grandchildBounds = Rect(80, 80, 90, 90);
+
+ sp<SurfaceComposerClient> newClient1 = new SurfaceComposerClient;
+ sp<SurfaceComposerClient> newClient2 = new SurfaceComposerClient;
+
+ sp<SurfaceControl> childSurface =
+ createSurface(newClient1, "Child surface", childBounds.width(), childBounds.height(),
+ PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
+ sp<SurfaceControl> grandchildSurface =
+ createSurface(newClient2, "Grandchild Surface", grandchildBounds.width(),
+ grandchildBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, childSurface.get());
+
+ TransactionUtils::fillSurfaceRGBA8(childSurface, childColor);
+ TransactionUtils::fillSurfaceRGBA8(grandchildSurface, grandchildColor);
+
+ Transaction()
+ .show(childSurface)
+ .show(grandchildSurface)
+ .setPosition(childSurface, childBounds.left - mMainSurfaceBounds.left,
+ childBounds.top - mMainSurfaceBounds.top)
+ .setPosition(grandchildSurface, grandchildBounds.left - childBounds.left,
+ grandchildBounds.top - childBounds.top)
+ .apply();
+
+ {
+ mCapture = screenshot();
+ mCapture->expectBorder(childBounds, mMainSurfaceColor);
+ mCapture->expectBorder(grandchildBounds, childColor);
+ mCapture->expectColor(grandchildBounds, grandchildColor);
+ }
+
+ Transaction().detachChildren(childSurface).apply();
+
+ // Remove main surface offscreen
+ Transaction().reparent(mMainSurface, nullptr).apply();
+ {
+ mCapture = screenshot();
+ mCapture->expectColor(mMainSurfaceBounds, Color::BLACK);
+ }
+
+ Transaction().reparent(mMainSurface, mBlackBgSurface->getHandle()).apply();
+ {
+ mCapture = screenshot();
+ mCapture->expectBorder(childBounds, mMainSurfaceColor);
+ mCapture->expectBorder(grandchildBounds, childColor);
+ mCapture->expectColor(grandchildBounds, grandchildColor);
+ }
+
+ Transaction().hide(grandchildSurface).apply();
+
+ // grandchild is still detached so it will not hide
+ {
+ mCapture = screenshot();
+ mCapture->expectBorder(childBounds, mMainSurfaceColor);
+ mCapture->expectBorder(grandchildBounds, childColor);
+ mCapture->expectColor(grandchildBounds, grandchildColor);
+ }
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp
index cdd9d92..84823f5 100644
--- a/services/surfaceflinger/tests/LayerUpdate_test.cpp
+++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp
@@ -103,41 +103,6 @@
sp<SurfaceControl> mSyncSurfaceControl;
};
-TEST_F(LayerUpdateTest, RelativesAreNotDetached) {
- std::unique_ptr<ScreenCapture> sc;
-
- sp<SurfaceControl> relative = createLayer(String8("relativeTestSurface"), 10, 10, 0);
- TransactionUtils::fillSurfaceRGBA8(relative, 10, 10, 10);
- waitForPostedBuffers();
-
- Transaction{}
- .setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1)
- .setPosition(relative, 64, 64)
- .apply();
-
- {
- // The relative should be on top of the FG control.
- ScreenCapture::captureScreen(&sc);
- sc->checkPixel(64, 64, 10, 10, 10);
- }
- Transaction{}.detachChildren(mFGSurfaceControl).apply();
-
- {
- // Nothing should change at this point.
- ScreenCapture::captureScreen(&sc);
- sc->checkPixel(64, 64, 10, 10, 10);
- }
-
- Transaction{}.hide(relative).apply();
-
- {
- // Ensure that the relative was actually hidden, rather than
- // being left in the detached but visible state.
- ScreenCapture::captureScreen(&sc);
- sc->expectFGColor(64, 64);
- }
-}
-
class GeometryLatchingTest : public LayerUpdateTest {
protected:
void EXPECT_INITIAL_STATE(const char* trace) {
@@ -588,174 +553,6 @@
}
}
-TEST_F(ChildLayerTest, DetachChildrenSameClient) {
- asTransaction([&](Transaction& t) {
- t.show(mChild);
- t.setPosition(mChild, 10, 10);
- t.setPosition(mFGSurfaceControl, 64, 64);
- });
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(74, 74);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(84, 84);
- }
-
- asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); });
-
- asTransaction([&](Transaction& t) { t.hide(mChild); });
-
- // Since the child has the same client as the parent, it will not get
- // detached and will be hidden.
- {
- mCapture = screenshot();
- mCapture->expectFGColor(64, 64);
- mCapture->expectFGColor(74, 74);
- mCapture->expectFGColor(84, 84);
- }
-}
-
-TEST_F(ChildLayerTest, DetachChildrenDifferentClient) {
- sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> mChildNewClient =
- createSurface(mNewComposerClient, "New Child Test Surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-
- ASSERT_TRUE(mChildNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(mChildNewClient, 200, 200, 200);
-
- asTransaction([&](Transaction& t) {
- t.hide(mChild);
- t.show(mChildNewClient);
- t.setPosition(mChildNewClient, 10, 10);
- t.setPosition(mFGSurfaceControl, 64, 64);
- });
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(74, 74);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(84, 84);
- }
-
- asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); });
-
- asTransaction([&](Transaction& t) { t.hide(mChildNewClient); });
-
- // Nothing should have changed.
- {
- mCapture = screenshot();
- mCapture->expectFGColor(64, 64);
- mCapture->expectChildColor(74, 74);
- mCapture->expectFGColor(84, 84);
- }
-}
-
-TEST_F(ChildLayerTest, DetachChildrenThenAttach) {
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-
- ASSERT_TRUE(childNewClient != nullptr);
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200);
-
- Transaction()
- .hide(mChild)
- .show(childNewClient)
- .setPosition(childNewClient, 10, 10)
- .setPosition(mFGSurfaceControl, 64, 64)
- .apply();
-
- {
- mCapture = screenshot();
- // Top left of foreground must now be visible
- mCapture->expectFGColor(64, 64);
- // But 10 pixels in we should see the child surface
- mCapture->expectChildColor(74, 74);
- // And 10 more pixels we should be back to the foreground surface
- mCapture->expectFGColor(84, 84);
- }
-
- Transaction().detachChildren(mFGSurfaceControl).apply();
- Transaction().hide(childNewClient).apply();
-
- // Nothing should have changed.
- {
- mCapture = screenshot();
- mCapture->expectFGColor(64, 64);
- mCapture->expectChildColor(74, 74);
- mCapture->expectFGColor(84, 84);
- }
-
- sp<SurfaceControl> newParentSurface = createLayer(String8("New Parent Surface"), 32, 32, 0);
- fillLayerColor(ISurfaceComposerClient::eFXSurfaceBufferQueue, newParentSurface, Color::RED, 32,
- 32);
- Transaction()
- .setLayer(newParentSurface, INT32_MAX - 1)
- .show(newParentSurface)
- .setPosition(newParentSurface, 20, 20)
- .reparent(childNewClient, newParentSurface->getHandle())
- .apply();
- {
- mCapture = screenshot();
- // Child is now hidden.
- mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED);
- }
-}
-TEST_F(ChildLayerTest, DetachChildrenWithDeferredTransaction) {
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-
- ASSERT_TRUE(childNewClient != nullptr);
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200);
-
- Transaction()
- .hide(mChild)
- .show(childNewClient)
- .setPosition(childNewClient, 10, 10)
- .setPosition(mFGSurfaceControl, 64, 64)
- .apply();
-
- {
- mCapture = screenshot();
- Rect rect = Rect(74, 74, 84, 84);
- mCapture->expectBorder(rect, Color{195, 63, 63, 255});
- mCapture->expectColor(rect, Color{200, 200, 200, 255});
- }
-
- Transaction()
- .deferTransactionUntil_legacy(childNewClient, mFGSurfaceControl->getHandle(),
- mFGSurfaceControl->getSurface()->getNextFrameNumber())
- .apply();
- Transaction().detachChildren(mFGSurfaceControl).apply();
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mFGSurfaceControl, Color::RED, 32, 32));
-
- // BufferLayer can still dequeue buffers even though there's a detached layer with a
- // deferred transaction.
- {
- SCOPED_TRACE("new buffer");
- mCapture = screenshot();
- Rect rect = Rect(74, 74, 84, 84);
- mCapture->expectBorder(rect, Color::RED);
- mCapture->expectColor(rect, Color{200, 200, 200, 255});
- }
-}
-
TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
asTransaction([&](Transaction& t) {
t.show(mChild);
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp
index 96a7541..1cea25a 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp
@@ -29,8 +29,8 @@
#include "SurfaceFlinger.h" // Get the name of the service...
#include <binder/IServiceManager.h>
-
#include <cutils/properties.h>
+#include <hidl/ServiceManagement.h>
#include <iomanip>
#include <thread>
@@ -173,7 +173,7 @@
property_set("debug.sf.hwc_service_name", "mock");
// This allows tests/SF to register/load a HIDL service not listed in manifest files.
- setenv("TREBLE_TESTING_OVERRIDE", "true", true);
+ android::hardware::details::setTrebleTestingOverride(true);
property_set("debug.sf.treble_testing_override", "true");
}
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 9355e61..9add6a5 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -150,9 +150,14 @@
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
EXPECT_CALL(*primaryDispSync, expectedPresentTime(_)).WillRepeatedly(Return(0));
+ constexpr bool kHasMultipleConfigs = true;
mFlinger.setupScheduler(std::move(primaryDispSync),
std::make_unique<mock::EventControlThread>(),
- std::move(eventThread), std::move(sfEventThread));
+ std::move(eventThread), std::move(sfEventThread),
+ kHasMultipleConfigs);
+
+ // Layer history should be created if there are multiple configs.
+ ASSERT_TRUE(mFlinger.scheduler()->hasLayerHistory());
}
void setupForceGeometryDirty() {
diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp
index 68cb52f..a119e27 100644
--- a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp
@@ -77,6 +77,22 @@
return tracingSession;
}
+ std::vector<perfetto::protos::TracePacket> readGraphicsFramePacketsBlocking(
+ perfetto::TracingSession* tracingSession) {
+ std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+ perfetto::protos::Trace trace;
+ EXPECT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+
+ std::vector<perfetto::protos::TracePacket> packets;
+ for (const auto& packet : trace.packet()) {
+ if (!packet.has_graphics_frame_event()) {
+ continue;
+ }
+ packets.emplace_back(packet);
+ }
+ return packets;
+ }
+
std::unique_ptr<FrameTracer> mFrameTracer;
FenceToFenceTimeMap fenceFactory;
};
@@ -142,40 +158,29 @@
auto tracingSession = getTracingSessionForTest();
tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
-
mFrameTracer->traceTimestamp(layerId, bufferID, frameNumber, timestamp, type, duration);
// Create second trace packet to finalize the previous one.
mFrameTracer->traceTimestamp(layerId, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
tracingSession->StopBlocking();
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- EXPECT_EQ(raw_trace.size(), 0);
+ auto packets = readGraphicsFramePacketsBlocking(tracingSession.get());
+ EXPECT_EQ(packets.size(), 0);
}
{
auto tracingSession = getTracingSessionForTest();
tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
-
mFrameTracer->traceNewLayer(layerId, layerName);
mFrameTracer->traceTimestamp(layerId, bufferID, frameNumber, timestamp, type, duration);
// Create second trace packet to finalize the previous one.
mFrameTracer->traceTimestamp(layerId, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
tracingSession->StopBlocking();
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- ASSERT_GT(raw_trace.size(), 0);
+ auto packets = readGraphicsFramePacketsBlocking(tracingSession.get());
+ EXPECT_EQ(packets.size(), 1);
- perfetto::protos::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
- ASSERT_FALSE(trace.packet().empty());
- EXPECT_EQ(trace.packet().size(), 1);
-
- const auto& packet = trace.packet().Get(0);
+ const auto& packet = packets[0];
ASSERT_TRUE(packet.has_timestamp());
EXPECT_EQ(packet.timestamp(), timestamp);
ASSERT_TRUE(packet.has_graphics_frame_event());
@@ -205,24 +210,21 @@
fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING);
auto tracingSession = getTracingSessionForTest();
tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
// Trace.
mFrameTracer->traceNewLayer(layerId, layerName);
mFrameTracer->traceFence(layerId, bufferID, frameNumber, fenceTime, type);
// Create extra trace packet to (hopefully not) trigger and finalize the fence packet.
mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
tracingSession->StopBlocking();
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- EXPECT_EQ(raw_trace.size(), 0);
+
+ auto packets = readGraphicsFramePacketsBlocking(tracingSession.get());
+ EXPECT_EQ(packets.size(), 0);
}
{
auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto tracingSession = getTracingSessionForTest();
tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
mFrameTracer->traceNewLayer(layerId, layerName);
mFrameTracer->traceFence(layerId, bufferID, frameNumber, fenceTime, type);
const nsecs_t timestamp = systemTime();
@@ -231,15 +233,10 @@
mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
tracingSession->StopBlocking();
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- ASSERT_GT(raw_trace.size(), 0);
+ auto packets = readGraphicsFramePacketsBlocking(tracingSession.get());
+ EXPECT_EQ(packets.size(), 2); // Two packets because of the extra trace made above.
- perfetto::protos::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
- ASSERT_FALSE(trace.packet().empty());
- EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above.
-
- const auto& packet = trace.packet().Get(1);
+ const auto& packet = packets[1];
ASSERT_TRUE(packet.has_timestamp());
EXPECT_EQ(packet.timestamp(), timestamp);
ASSERT_TRUE(packet.has_graphics_frame_event());
@@ -266,8 +263,6 @@
auto tracingSession = getTracingSessionForTest();
tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
mFrameTracer->traceNewLayer(layerId, layerName);
// traceFence called after fence signalled.
@@ -288,22 +283,17 @@
mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
tracingSession->StopBlocking();
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- ASSERT_GT(raw_trace.size(), 0);
+ auto packets = readGraphicsFramePacketsBlocking(tracingSession.get());
+ EXPECT_EQ(packets.size(), 2);
- perfetto::protos::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
- ASSERT_FALSE(trace.packet().empty());
- EXPECT_EQ(trace.packet().size(), 2);
-
- const auto& packet1 = trace.packet().Get(0);
+ const auto& packet1 = packets[0];
ASSERT_TRUE(packet1.has_timestamp());
EXPECT_EQ(packet1.timestamp(), signalTime1);
ASSERT_TRUE(packet1.has_graphics_frame_event());
ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
- const auto& packet2 = trace.packet().Get(1);
+ const auto& packet2 = packets[1];
ASSERT_TRUE(packet2.has_timestamp());
EXPECT_EQ(packet2.timestamp(), signalTime2);
ASSERT_TRUE(packet2.has_graphics_frame_event());
@@ -323,8 +313,6 @@
auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
mFrameTracer->traceNewLayer(layerId, layerName);
mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence, type);
fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime);
@@ -332,8 +320,8 @@
mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
tracingSession->StopBlocking();
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- EXPECT_EQ(raw_trace.size(), 0);
+ auto packets = readGraphicsFramePacketsBlocking(tracingSession.get());
+ EXPECT_EQ(packets.size(), 0);
}
TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) {
@@ -347,8 +335,6 @@
auto tracingSession = getTracingSessionForTest();
tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
mFrameTracer->traceNewLayer(layerId, layerName);
// traceFence called after fence signalled.
@@ -369,15 +355,10 @@
mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
tracingSession->StopBlocking();
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- ASSERT_GT(raw_trace.size(), 0);
+ auto packets = readGraphicsFramePacketsBlocking(tracingSession.get());
+ EXPECT_EQ(packets.size(), 2);
- perfetto::protos::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
- ASSERT_FALSE(trace.packet().empty());
- EXPECT_EQ(trace.packet().size(), 2);
-
- const auto& packet1 = trace.packet().Get(0);
+ const auto& packet1 = packets[0];
ASSERT_TRUE(packet1.has_timestamp());
EXPECT_EQ(packet1.timestamp(), startTime1);
ASSERT_TRUE(packet1.has_graphics_frame_event());
@@ -386,7 +367,7 @@
const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event();
EXPECT_EQ(buffer_event1.duration_ns(), duration);
- const auto& packet2 = trace.packet().Get(1);
+ const auto& packet2 = packets[1];
ASSERT_TRUE(packet2.has_timestamp());
EXPECT_EQ(packet2.timestamp(), startTime2);
ASSERT_TRUE(packet2.has_graphics_frame_event());
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index cae317b..3ab22d3 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -49,6 +49,8 @@
LayerHistoryTest() { mFlinger.resetScheduler(mScheduler); }
+ void SetUp() override { ASSERT_TRUE(mScheduler->hasLayerHistory()); }
+
impl::LayerHistory& history() { return *mScheduler->mutableLayerHistory(); }
const impl::LayerHistory& history() const { return *mScheduler->mutableLayerHistory(); }
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index afd2b71..1705835 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -50,6 +50,8 @@
LayerHistoryTestV2() { mFlinger.resetScheduler(mScheduler); }
+ void SetUp() override { ASSERT_TRUE(mScheduler->hasLayerHistory()); }
+
impl::LayerHistoryV2& history() { return *mScheduler->mutableLayerHistoryV2(); }
const impl::LayerHistoryV2& history() const { return *mScheduler->mutableLayerHistoryV2(); }
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 03d4460..1f6f166 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -1130,15 +1130,6 @@
auto& lr = layers[0];
RefreshRateConfigs::GlobalSignals consideredSignals;
- lr.vote = LayerVoteType::ExplicitExactOrMultiple;
- lr.desiredRefreshRate = 60.0f;
- lr.name = "60Hz ExplicitExactOrMultiple";
- lr.focused = true;
- EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = true},
- &consideredSignals));
- EXPECT_EQ(false, consideredSignals.touch);
-
lr.vote = LayerVoteType::ExplicitDefault;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz ExplicitDefault";
@@ -1162,13 +1153,6 @@
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
- lr.vote = LayerVoteType::ExplicitExactOrMultiple;
- lr.desiredRefreshRate = 90.0f;
- lr.name = "90Hz ExplicitExactOrMultiple";
- lr.focused = true;
- EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = true}));
-
lr.vote = LayerVoteType::ExplicitDefault;
lr.desiredRefreshRate = 90.0f;
lr.name = "90Hz ExplicitDefault";
@@ -1204,7 +1188,7 @@
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.focused = true;
- EXPECT_EQ(mExpected60Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::ExplicitDefault;
@@ -1306,7 +1290,7 @@
EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f));
EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, 90.f));
EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f));
- EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f));
// Layers not focused are not allowed to override primary config
EXPECT_EQ(HWC_CONFIG_ID_60,
@@ -1321,7 +1305,7 @@
// When we're higher than the primary range max due to a layer frame rate setting, touch boost
// shouldn't drag us back down to the primary range max.
EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f, /*touch=*/true));
- EXPECT_EQ(HWC_CONFIG_ID_90,
+ EXPECT_EQ(HWC_CONFIG_ID_60,
getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f, /*touch=*/true));
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 1aa7320..382199d 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -31,8 +31,10 @@
#include "Scheduler/EventThread.h"
#include "Scheduler/RefreshRateConfigs.h"
#include "TestableScheduler.h"
+#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockDisplay.h"
#include "mock/MockEventThread.h"
+#include "mock/MockLayer.h"
using testing::_;
using testing::Return;
@@ -58,13 +60,18 @@
SchedulerTest();
~SchedulerTest() override;
- std::unique_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
- std::unique_ptr<TestableScheduler> mScheduler;
+ Hwc2::mock::Display mDisplay;
+ const scheduler::RefreshRateConfigs mConfigs{{HWC2::Display::Config::Builder(mDisplay, 0)
+ .setVsyncPeriod(16'666'667)
+ .setConfigGroup(0)
+ .build()},
+ HwcConfigIndexType(0)};
+
+ TestableScheduler mScheduler{mConfigs, false};
Scheduler::ConnectionHandle mConnectionHandle;
mock::EventThread* mEventThread;
sp<MockEventThreadConnection> mEventThreadConnection;
- Hwc2::mock::Display mDisplay;
};
SchedulerTest::SchedulerTest() {
@@ -72,16 +79,6 @@
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
- std::vector<std::shared_ptr<const HWC2::Display::Config>> configs{
- HWC2::Display::Config::Builder(mDisplay, 0)
- .setVsyncPeriod(int32_t(16666667))
- .setConfigGroup(0)
- .build()};
- mRefreshRateConfigs = std::make_unique<
- scheduler::RefreshRateConfigs>(configs, /*currentConfig=*/HwcConfigIndexType(0));
-
- mScheduler = std::make_unique<TestableScheduler>(*mRefreshRateConfigs, false);
-
auto eventThread = std::make_unique<mock::EventThread>();
mEventThread = eventThread.get();
EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
@@ -93,7 +90,7 @@
EXPECT_CALL(*mEventThread, createEventConnection(_, _))
.WillRepeatedly(Return(mEventThreadConnection));
- mConnectionHandle = mScheduler->createConnection(std::move(eventThread));
+ mConnectionHandle = mScheduler.createConnection(std::move(eventThread));
EXPECT_TRUE(mConnectionHandle);
}
@@ -103,7 +100,6 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-namespace {
/* ------------------------------------------------------------------------
* Test cases
*/
@@ -111,67 +107,84 @@
TEST_F(SchedulerTest, invalidConnectionHandle) {
Scheduler::ConnectionHandle handle;
- sp<IDisplayEventConnection> connection;
- ASSERT_NO_FATAL_FAILURE(
- connection = mScheduler->createDisplayEventConnection(handle,
- ISurfaceComposer::
- eConfigChangedSuppress));
+ const sp<IDisplayEventConnection> connection =
+ mScheduler.createDisplayEventConnection(handle,
+ ISurfaceComposer::eConfigChangedSuppress);
+
EXPECT_FALSE(connection);
- EXPECT_FALSE(mScheduler->getEventConnection(handle));
+ EXPECT_FALSE(mScheduler.getEventConnection(handle));
// The EXPECT_CALLS make sure we don't call the functions on the subsequent event threads.
EXPECT_CALL(*mEventThread, onHotplugReceived(_, _)).Times(0);
- ASSERT_NO_FATAL_FAILURE(mScheduler->onHotplugReceived(handle, PHYSICAL_DISPLAY_ID, false));
+ mScheduler.onHotplugReceived(handle, PHYSICAL_DISPLAY_ID, false);
EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(0);
- ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(handle));
+ mScheduler.onScreenAcquired(handle);
EXPECT_CALL(*mEventThread, onScreenReleased()).Times(0);
- ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(handle));
+ mScheduler.onScreenReleased(handle);
std::string output;
EXPECT_CALL(*mEventThread, dump(_)).Times(0);
- ASSERT_NO_FATAL_FAILURE(mScheduler->dump(handle, output));
+ mScheduler.dump(handle, output);
EXPECT_TRUE(output.empty());
EXPECT_CALL(*mEventThread, setPhaseOffset(_)).Times(0);
- ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(handle, 10));
+ mScheduler.setPhaseOffset(handle, 10);
}
TEST_F(SchedulerTest, validConnectionHandle) {
- sp<IDisplayEventConnection> connection;
- ASSERT_NO_FATAL_FAILURE(
- connection = mScheduler->createDisplayEventConnection(mConnectionHandle,
- ISurfaceComposer::
- eConfigChangedSuppress));
+ const sp<IDisplayEventConnection> connection =
+ mScheduler.createDisplayEventConnection(mConnectionHandle,
+ ISurfaceComposer::eConfigChangedSuppress);
+
ASSERT_EQ(mEventThreadConnection, connection);
- EXPECT_TRUE(mScheduler->getEventConnection(mConnectionHandle));
+ EXPECT_TRUE(mScheduler.getEventConnection(mConnectionHandle));
EXPECT_CALL(*mEventThread, onHotplugReceived(PHYSICAL_DISPLAY_ID, false)).Times(1);
- ASSERT_NO_FATAL_FAILURE(
- mScheduler->onHotplugReceived(mConnectionHandle, PHYSICAL_DISPLAY_ID, false));
+ mScheduler.onHotplugReceived(mConnectionHandle, PHYSICAL_DISPLAY_ID, false);
EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(1);
- ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(mConnectionHandle));
+ mScheduler.onScreenAcquired(mConnectionHandle);
EXPECT_CALL(*mEventThread, onScreenReleased()).Times(1);
- ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(mConnectionHandle));
+ mScheduler.onScreenReleased(mConnectionHandle);
std::string output("dump");
EXPECT_CALL(*mEventThread, dump(output)).Times(1);
- ASSERT_NO_FATAL_FAILURE(mScheduler->dump(mConnectionHandle, output));
+ mScheduler.dump(mConnectionHandle, output);
EXPECT_FALSE(output.empty());
EXPECT_CALL(*mEventThread, setPhaseOffset(10)).Times(1);
- ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(mConnectionHandle, 10));
+ mScheduler.setPhaseOffset(mConnectionHandle, 10);
static constexpr size_t kEventConnections = 5;
ON_CALL(*mEventThread, getEventThreadConnectionCount())
.WillByDefault(Return(kEventConnections));
- EXPECT_EQ(kEventConnections, mScheduler->getEventThreadConnectionCount(mConnectionHandle));
+ EXPECT_EQ(kEventConnections, mScheduler.getEventThreadConnectionCount(mConnectionHandle));
}
-} // namespace
+TEST_F(SchedulerTest, noLayerHistory) {
+ // Layer history should not be created if there is a single config.
+ ASSERT_FALSE(mScheduler.hasLayerHistory());
+
+ TestableSurfaceFlinger flinger;
+ mock::MockLayer layer(flinger.flinger());
+
+ // Content detection should be no-op.
+ mScheduler.registerLayer(&layer);
+ mScheduler.recordLayerHistory(&layer, 0, LayerHistory::LayerUpdateType::Buffer);
+
+ constexpr bool kPowerStateNormal = true;
+ mScheduler.setDisplayPowerState(kPowerStateNormal);
+
+ constexpr uint32_t kDisplayArea = 999'999;
+ mScheduler.onPrimaryDisplayAreaChanged(kDisplayArea);
+
+ mScheduler.chooseRefreshRateForContent();
+ EXPECT_EQ(0, mScheduler.refreshRateChangeCount());
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index b7067a6..c463294 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -29,41 +29,20 @@
class TestableScheduler : public Scheduler, private ISchedulerCallback {
public:
TestableScheduler(const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2)
- : Scheduler([](bool) {}, configs, *this, useContentDetectionV2, true) {
- if (mUseContentDetectionV2) {
- mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>(configs);
- } else {
- mLayerHistory = std::make_unique<scheduler::impl::LayerHistory>();
- }
- }
+ : Scheduler([](bool) {}, configs, *this, useContentDetectionV2, true) {}
TestableScheduler(std::unique_ptr<DispSync> primaryDispSync,
std::unique_ptr<EventControlThread> eventControlThread,
const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2)
: Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs, *this,
- useContentDetectionV2, true) {
- if (mUseContentDetectionV2) {
- mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>(configs);
- } else {
- mLayerHistory = std::make_unique<scheduler::impl::LayerHistory>();
- }
- }
+ createLayerHistory(configs, useContentDetectionV2), useContentDetectionV2,
+ true) {}
// Used to inject mock event thread.
ConnectionHandle createConnection(std::unique_ptr<EventThread> eventThread) {
return Scheduler::createConnection(std::move(eventThread));
}
- size_t layerHistorySize() const NO_THREAD_SAFETY_ANALYSIS {
- if (mUseContentDetectionV2) {
- return static_cast<scheduler::impl::LayerHistoryV2*>(mLayerHistory.get())
- ->mLayerInfos.size();
- } else {
- return static_cast<scheduler::impl::LayerHistory*>(mLayerHistory.get())
- ->mLayerInfos.size();
- }
- }
-
/* ------------------------------------------------------------------------
* Read-write access to private data to set up preconditions and assert
* post-conditions.
@@ -73,14 +52,26 @@
auto& mutablePrimaryDispSync() { return mPrimaryDispSync; }
auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; }
- auto mutableLayerHistory() {
+ size_t refreshRateChangeCount() const { return mRefreshRateChangeCount; }
+
+ bool hasLayerHistory() const { return static_cast<bool>(mLayerHistory); }
+
+ auto* mutableLayerHistory() {
+ LOG_ALWAYS_FATAL_IF(mUseContentDetectionV2);
return static_cast<scheduler::impl::LayerHistory*>(mLayerHistory.get());
}
- auto mutableLayerHistoryV2() {
+ auto* mutableLayerHistoryV2() {
+ LOG_ALWAYS_FATAL_IF(!mUseContentDetectionV2);
return static_cast<scheduler::impl::LayerHistoryV2*>(mLayerHistory.get());
}
+ size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS {
+ if (!mLayerHistory) return 0;
+ return mUseContentDetectionV2 ? mutableLayerHistoryV2()->mLayerInfos.size()
+ : mutableLayerHistory()->mLayerInfos.size();
+ }
+
void replaceTouchTimer(int64_t millis) {
if (mTouchTimer) {
mTouchTimer.reset();
@@ -108,9 +99,12 @@
}
private:
- void changeRefreshRate(const RefreshRate&, ConfigEvent) override {}
+ void changeRefreshRate(const RefreshRate&, ConfigEvent) override { mRefreshRateChangeCount++; }
+
void repaintEverythingForHWC() override {}
void kernelTimerChanged(bool /*expired*/) override {}
+
+ size_t mRefreshRateChangeCount = 0;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index f630103..256e048 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -202,13 +202,20 @@
std::unique_ptr<EventControlThread> eventControlThread,
std::unique_ptr<EventThread> appEventThread,
std::unique_ptr<EventThread> sfEventThread,
- bool useContentDetectionV2 = false) {
+ bool hasMultipleConfigs = false) {
std::vector<std::shared_ptr<const HWC2::Display::Config>> configs{
HWC2::Display::Config::Builder(mDisplay, 0)
- .setVsyncPeriod(int32_t(16666667))
+ .setVsyncPeriod(16'666'667)
.setConfigGroup(0)
.build()};
+ if (hasMultipleConfigs) {
+ configs.emplace_back(HWC2::Display::Config::Builder(mDisplay, 1)
+ .setVsyncPeriod(11'111'111)
+ .setConfigGroup(0)
+ .build());
+ }
+
mFlinger->mRefreshRateConfigs = std::make_unique<
scheduler::RefreshRateConfigs>(configs, /*currentConfig=*/HwcConfigIndexType(0));
mFlinger->mRefreshRateStats = std::make_unique<
@@ -218,9 +225,10 @@
mFlinger->mPhaseConfiguration =
mFactory.createPhaseConfiguration(*mFlinger->mRefreshRateConfigs);
+ constexpr bool kUseContentDetectionV2 = false;
mScheduler =
new TestableScheduler(std::move(primaryDispSync), std::move(eventControlThread),
- *mFlinger->mRefreshRateConfigs, useContentDetectionV2);
+ *mFlinger->mRefreshRateConfigs, kUseContentDetectionV2);
mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread));
mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
index be49ef3..c2a7752 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
@@ -51,6 +51,7 @@
void setPeriod(nsecs_t) final {}
void resetModel() final {}
+ bool needsMoreSamples() const final { return false; }
void dump(std::string&) const final {}
private:
@@ -86,6 +87,7 @@
void setPeriod(nsecs_t) final {}
void resetModel() final {}
+ bool needsMoreSamples() const final { return false; }
void dump(std::string&) const final {}
private:
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
index d940dc5..373f6a5 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
@@ -47,6 +47,7 @@
MOCK_CONST_METHOD0(currentPeriod, nsecs_t());
MOCK_METHOD1(setPeriod, void(nsecs_t));
MOCK_METHOD0(resetModel, void());
+ MOCK_CONST_METHOD0(needsMoreSamples, bool());
MOCK_CONST_METHOD1(dump, void(std::string&));
nsecs_t nextVSyncTime(nsecs_t timePoint) const {
@@ -115,11 +116,15 @@
operator VSyncDispatch::CallbackToken() const { return mToken; }
- void counter(nsecs_t time, nsecs_t) { mCalls.push_back(time); }
+ void counter(nsecs_t time, nsecs_t wakeup_time) {
+ mCalls.push_back(time);
+ mWakeupTime.push_back(wakeup_time);
+ }
VSyncDispatch& mDispatch;
VSyncDispatch::CallbackToken mToken;
std::vector<nsecs_t> mCalls;
+ std::vector<nsecs_t> mWakeupTime;
};
class PausingCallback {
@@ -747,6 +752,31 @@
EXPECT_THAT(cb2.mCalls.size(), Eq(1));
}
+TEST_F(VSyncDispatchTimerQueueTest, laggedTimerGroupsCallbacksWithinLag) {
+ CountingCallback cb1(mDispatch);
+ CountingCallback cb2(mDispatch);
+
+ Sequence seq;
+ EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
+ .InSequence(seq)
+ .WillOnce(Return(1000));
+ EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
+ EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
+ .InSequence(seq)
+ .WillOnce(Return(1000));
+
+ EXPECT_EQ(mDispatch.schedule(cb1, 400, 1000), ScheduleResult::Scheduled);
+ EXPECT_EQ(mDispatch.schedule(cb2, 390, 1000), ScheduleResult::Scheduled);
+
+ mMockClock.setLag(100);
+ mMockClock.advanceBy(700);
+
+ ASSERT_THAT(cb1.mWakeupTime.size(), Eq(1));
+ EXPECT_THAT(cb1.mWakeupTime[0], Eq(600));
+ ASSERT_THAT(cb2.mWakeupTime.size(), Eq(1));
+ EXPECT_THAT(cb2.mWakeupTime[0], Eq(610));
+}
+
class VSyncDispatchTimerQueueEntryTest : public testing::Test {
protected:
nsecs_t const mPeriod = 1000;
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index fc39235..d4cd11d 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -73,27 +73,27 @@
TEST_F(VSyncPredictorTest, reportsSamplesNeededWhenHasNoDataPoints) {
for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
- EXPECT_TRUE(tracker.needsMoreSamples(mNow += mPeriod));
- tracker.addVsyncTimestamp(mNow);
+ EXPECT_TRUE(tracker.needsMoreSamples());
+ tracker.addVsyncTimestamp(mNow += mPeriod);
}
- EXPECT_FALSE(tracker.needsMoreSamples(mNow));
+ EXPECT_FALSE(tracker.needsMoreSamples());
}
TEST_F(VSyncPredictorTest, reportsSamplesNeededAfterExplicitRateChange) {
for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
tracker.addVsyncTimestamp(mNow += mPeriod);
}
- EXPECT_FALSE(tracker.needsMoreSamples(mNow));
+ EXPECT_FALSE(tracker.needsMoreSamples());
auto const changedPeriod = mPeriod * 2;
tracker.setPeriod(changedPeriod);
- EXPECT_TRUE(tracker.needsMoreSamples(mNow));
+ EXPECT_TRUE(tracker.needsMoreSamples());
for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
- EXPECT_TRUE(tracker.needsMoreSamples(mNow += changedPeriod));
- tracker.addVsyncTimestamp(mNow);
+ EXPECT_TRUE(tracker.needsMoreSamples());
+ tracker.addVsyncTimestamp(mNow += changedPeriod);
}
- EXPECT_FALSE(tracker.needsMoreSamples(mNow));
+ EXPECT_FALSE(tracker.needsMoreSamples());
}
TEST_F(VSyncPredictorTest, transitionsToModelledPointsAfterSynthetic) {
@@ -320,20 +320,6 @@
EXPECT_THAT(intercept, Eq(0));
}
-TEST_F(VSyncPredictorTest, willBecomeInaccurateAfterA_longTimeWithNoSamples) {
- auto const simulatedVsyncs = generateVsyncTimestamps(kMinimumSamplesForPrediction, mPeriod, 0);
-
- for (auto const& timestamp : simulatedVsyncs) {
- tracker.addVsyncTimestamp(timestamp);
- }
- auto const mNow = *simulatedVsyncs.rbegin();
- EXPECT_FALSE(tracker.needsMoreSamples(mNow));
-
- // TODO: would be better to decay this as a result of the variance of the samples
- static auto constexpr aLongTimeOut = 1000000000;
- EXPECT_TRUE(tracker.needsMoreSamples(mNow + aLongTimeOut));
-}
-
TEST_F(VSyncPredictorTest, idealModelPredictionsBeforeRegressionModelIsBuilt) {
auto const simulatedVsyncs =
generateVsyncTimestamps(kMinimumSamplesForPrediction + 1, mPeriod, 0);
@@ -443,7 +429,7 @@
// When VsyncPredictor returns the period it means that it doesn't know how to predict and
// it needs to get more samples
if (slope == mPeriod && intercept == 0) {
- EXPECT_TRUE(tracker.needsMoreSamples(now));
+ EXPECT_TRUE(tracker.needsMoreSamples());
}
}
}
diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
index a972562..6856612 100644
--- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
@@ -41,6 +41,7 @@
MOCK_CONST_METHOD0(currentPeriod, nsecs_t());
MOCK_METHOD1(setPeriod, void(nsecs_t));
MOCK_METHOD0(resetModel, void());
+ MOCK_CONST_METHOD0(needsMoreSamples, bool());
MOCK_CONST_METHOD1(dump, void(std::string&));
};
@@ -57,6 +58,7 @@
nsecs_t currentPeriod() const final { return mTracker->currentPeriod(); }
void setPeriod(nsecs_t period) final { mTracker->setPeriod(period); }
void resetModel() final { mTracker->resetModel(); }
+ bool needsMoreSamples() const final { return mTracker->needsMoreSamples(); }
void dump(std::string& result) const final { mTracker->dump(result); }
private:
@@ -455,6 +457,83 @@
EXPECT_FALSE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
}
+TEST_F(VSyncReactorTest, hwVsyncIsRequestedForTracker) {
+ auto time = 0;
+ bool periodFlushed = false;
+ nsecs_t const newPeriod = 4000;
+ mReactor.setPeriod(newPeriod);
+
+ static auto constexpr numSamplesWithNewPeriod = 4;
+ Sequence seq;
+ EXPECT_CALL(*mMockTracker, needsMoreSamples())
+ .Times(numSamplesWithNewPeriod - 2)
+ .InSequence(seq)
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(*mMockTracker, needsMoreSamples())
+ .Times(1)
+ .InSequence(seq)
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(numSamplesWithNewPeriod);
+
+ EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+
+ EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+ // confirmed period, but predictor wants numRequest samples. This one and prior are valid.
+ EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod, std::nullopt, &periodFlushed));
+ EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod, std::nullopt, &periodFlushed));
+ EXPECT_FALSE(mReactor.addResyncSample(time += newPeriod, std::nullopt, &periodFlushed));
+}
+
+TEST_F(VSyncReactorTest, hwVsyncturnsOffOnConfirmationWhenTrackerDoesntRequest) {
+ auto time = 0;
+ bool periodFlushed = false;
+ nsecs_t const newPeriod = 4000;
+ mReactor.setPeriod(newPeriod);
+
+ Sequence seq;
+ EXPECT_CALL(*mMockTracker, needsMoreSamples())
+ .Times(1)
+ .InSequence(seq)
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(2);
+
+ EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+ EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+ EXPECT_FALSE(mReactor.addResyncSample(time += newPeriod, std::nullopt, &periodFlushed));
+}
+
+TEST_F(VSyncReactorTest, hwVsyncIsRequestedForTrackerMultiplePeriodChanges) {
+ auto time = 0;
+ bool periodFlushed = false;
+ nsecs_t const newPeriod1 = 4000;
+ nsecs_t const newPeriod2 = 7000;
+
+ mReactor.setPeriod(newPeriod1);
+
+ Sequence seq;
+ EXPECT_CALL(*mMockTracker, needsMoreSamples())
+ .Times(4)
+ .InSequence(seq)
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(*mMockTracker, needsMoreSamples())
+ .Times(1)
+ .InSequence(seq)
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(7);
+
+ EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+ EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+ // confirmed period, but predictor wants numRequest samples. This one and prior are valid.
+ EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod1, std::nullopt, &periodFlushed));
+ EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod1, std::nullopt, &periodFlushed));
+
+ mReactor.setPeriod(newPeriod2);
+ EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod1, std::nullopt, &periodFlushed));
+ EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod2, std::nullopt, &periodFlushed));
+ EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod2, std::nullopt, &periodFlushed));
+ EXPECT_FALSE(mReactor.addResyncSample(time += newPeriod2, std::nullopt, &periodFlushed));
+}
+
static nsecs_t computeWorkload(nsecs_t period, nsecs_t phase) {
return period - phase;
}
@@ -648,7 +727,7 @@
TEST_F(VSyncReactorTest, periodChangeWithGivenVsyncPeriod) {
bool periodFlushed = true;
- EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(3);
+ EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(2);
mReactor.setIgnorePresentFences(true);
nsecs_t const newPeriod = 5000;
@@ -672,7 +751,7 @@
kPendingLimit, true /* supportKernelIdleTimer */);
bool periodFlushed = true;
- EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(5);
+ EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(4);
idleReactor.setIgnorePresentFences(true);
// First, set the same period, which should only be confirmed when we receive two
diff --git a/services/vibratorservice/VibratorHalController.cpp b/services/vibratorservice/VibratorHalController.cpp
index 896c162..03e51ae 100644
--- a/services/vibratorservice/VibratorHalController.cpp
+++ b/services/vibratorservice/VibratorHalController.cpp
@@ -47,105 +47,77 @@
static constexpr int MAX_RETRIES = 1;
-template <typename T>
-using hal_connect_fn = std::function<sp<T>()>;
-
-template <typename T>
-sp<T> connectToHal(bool* halExists, const hal_connect_fn<T>& connectFn, const char* halName) {
- if (!*halExists) {
+std::shared_ptr<HalWrapper> HalConnector::connect(std::shared_ptr<CallbackScheduler> scheduler) {
+ static bool gHalExists = true;
+ if (!gHalExists) {
+ // We already tried to connect to all of the vibrator HAL versions and none was available.
return nullptr;
}
- sp<T> hal = connectFn();
- if (hal) {
- ALOGV("Successfully connected to Vibrator HAL %s service.", halName);
- } else {
- ALOGV("Vibrator HAL %s service not available.", halName);
- *halExists = false;
- }
- return hal;
-}
-sp<Aidl::IVibrator> connectToAidl() {
- static bool gHalExists = true;
- static hal_connect_fn<Aidl::IVibrator> connectFn = []() {
- return waitForVintfService<Aidl::IVibrator>();
- };
- return connectToHal(&gHalExists, connectFn, "AIDL");
-}
-
-sp<V1_0::IVibrator> connectToHidl() {
- static bool gHalExists = true;
- static hal_connect_fn<V1_0::IVibrator> connectFn = []() {
- return V1_0::IVibrator::getService();
- };
- return connectToHal(&gHalExists, connectFn, "v1.0");
-}
-
-// -------------------------------------------------------------------------------------------------
-
-std::shared_ptr<HalWrapper> HalConnector::connect(std::shared_ptr<CallbackScheduler> scheduler) {
- sp<Aidl::IVibrator> aidlHal = connectToAidl();
+ sp<Aidl::IVibrator> aidlHal = waitForVintfService<Aidl::IVibrator>();
if (aidlHal) {
+ ALOGV("Successfully connected to Vibrator HAL AIDL service.");
return std::make_shared<AidlHalWrapper>(std::move(scheduler), aidlHal);
}
- sp<V1_0::IVibrator> halV1_0 = connectToHidl();
+
+ sp<V1_0::IVibrator> halV1_0 = V1_0::IVibrator::getService();
if (halV1_0 == nullptr) {
- // No Vibrator HAL service available.
+ ALOGV("Vibrator HAL service not available.");
+ gHalExists = false;
return nullptr;
}
+
sp<V1_3::IVibrator> halV1_3 = V1_3::IVibrator::castFrom(halV1_0);
if (halV1_3) {
- ALOGV("Successfully converted to Vibrator HAL v1.3 service.");
+ ALOGV("Successfully connected to Vibrator HAL v1.3 service.");
return std::make_shared<HidlHalWrapperV1_3>(std::move(scheduler), halV1_3);
}
sp<V1_2::IVibrator> halV1_2 = V1_2::IVibrator::castFrom(halV1_0);
if (halV1_2) {
- ALOGV("Successfully converted to Vibrator HAL v1.2 service.");
+ ALOGV("Successfully connected to Vibrator HAL v1.2 service.");
return std::make_shared<HidlHalWrapperV1_2>(std::move(scheduler), halV1_2);
}
sp<V1_1::IVibrator> halV1_1 = V1_1::IVibrator::castFrom(halV1_0);
if (halV1_1) {
- ALOGV("Successfully converted to Vibrator HAL v1.1 service.");
+ ALOGV("Successfully connected to Vibrator HAL v1.1 service.");
return std::make_shared<HidlHalWrapperV1_1>(std::move(scheduler), halV1_1);
}
+ ALOGV("Successfully connected to Vibrator HAL v1.0 service.");
return std::make_shared<HidlHalWrapperV1_0>(std::move(scheduler), halV1_0);
}
// -------------------------------------------------------------------------------------------------
-std::shared_ptr<HalWrapper> HalController::initHal() {
- std::lock_guard<std::mutex> lock(mConnectedHalMutex);
- if (mConnectedHal == nullptr) {
- mConnectedHal = mHalConnector->connect(mCallbackScheduler);
- }
- return mConnectedHal;
-}
-
template <typename T>
HalResult<T> HalController::processHalResult(HalResult<T> result, const char* functionName) {
if (result.isFailed()) {
ALOGE("%s failed: Vibrator HAL not available", functionName);
std::lock_guard<std::mutex> lock(mConnectedHalMutex);
- // Drop HAL handle. This will force future api calls to reconnect.
- mConnectedHal = nullptr;
+ mConnectedHal->tryReconnect();
}
return result;
}
template <typename T>
HalResult<T> HalController::apply(HalController::hal_fn<T>& halFn, const char* functionName) {
- std::shared_ptr<HalWrapper> hal = initHal();
- if (hal == nullptr) {
- ALOGV("Skipped %s because Vibrator HAL is not available", functionName);
- return HalResult<T>::unsupported();
+ std::shared_ptr<HalWrapper> hal = nullptr;
+ {
+ std::lock_guard<std::mutex> lock(mConnectedHalMutex);
+ if (mConnectedHal == nullptr) {
+ // Init was never called, so connect to HAL for the first time during this call.
+ mConnectedHal = mHalConnector->connect(mCallbackScheduler);
+
+ if (mConnectedHal == nullptr) {
+ ALOGV("Skipped %s because Vibrator HAL is not available", functionName);
+ return HalResult<T>::unsupported();
+ }
+ }
+ hal = mConnectedHal;
}
HalResult<T> ret = processHalResult(halFn(hal), functionName);
for (int i = 0; i < MAX_RETRIES && ret.isFailed(); i++) {
- hal = initHal();
- if (hal) {
- ret = processHalResult(halFn(hal), functionName);
- }
+ ret = processHalResult(halFn(hal), functionName);
}
return ret;
@@ -153,11 +125,27 @@
// -------------------------------------------------------------------------------------------------
+void HalController::init() {
+ std::lock_guard<std::mutex> lock(mConnectedHalMutex);
+ if (mConnectedHal == nullptr) {
+ mConnectedHal = mHalConnector->connect(mCallbackScheduler);
+ }
+}
+
HalResult<void> HalController::ping() {
hal_fn<void> pingFn = [](std::shared_ptr<HalWrapper> hal) { return hal->ping(); };
return apply(pingFn, "ping");
}
+void HalController::tryReconnect() {
+ std::lock_guard<std::mutex> lock(mConnectedHalMutex);
+ if (mConnectedHal == nullptr) {
+ mConnectedHal = mHalConnector->connect(mCallbackScheduler);
+ } else {
+ mConnectedHal->tryReconnect();
+ }
+}
+
HalResult<void> HalController::on(milliseconds timeout,
const std::function<void()>& completionCallback) {
hal_fn<void> onFn = [&](std::shared_ptr<HalWrapper> hal) {
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index 94db538..9d219ff 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -149,8 +149,16 @@
// -------------------------------------------------------------------------------------------------
HalResult<void> AidlHalWrapper::ping() {
- return IInterface::asBinder(mHandle)->pingBinder() ? HalResult<void>::ok()
- : HalResult<void>::failed();
+ return IInterface::asBinder(getHal())->pingBinder() ? HalResult<void>::ok()
+ : HalResult<void>::failed();
+}
+
+void AidlHalWrapper::tryReconnect() {
+ sp<Aidl::IVibrator> newHandle = checkVintfService<Aidl::IVibrator>();
+ if (newHandle) {
+ std::lock_guard<std::mutex> lock(mHandleMutex);
+ mHandle = std::move(newHandle);
+ }
}
HalResult<void> AidlHalWrapper::on(milliseconds timeout,
@@ -160,7 +168,7 @@
static_cast<int32_t>(capabilities.value() & Capabilities::ON_CALLBACK);
auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr;
- auto ret = HalResult<void>::fromStatus(mHandle->on(timeout.count(), cb));
+ auto ret = HalResult<void>::fromStatus(getHal()->on(timeout.count(), cb));
if (!supportsCallback && ret.isOk()) {
mCallbackScheduler->schedule(completionCallback, timeout);
}
@@ -169,24 +177,24 @@
}
HalResult<void> AidlHalWrapper::off() {
- return HalResult<void>::fromStatus(mHandle->off());
+ return HalResult<void>::fromStatus(getHal()->off());
}
HalResult<void> AidlHalWrapper::setAmplitude(int32_t amplitude) {
float convertedAmplitude = static_cast<float>(amplitude) / std::numeric_limits<uint8_t>::max();
- return HalResult<void>::fromStatus(mHandle->setAmplitude(convertedAmplitude));
+ return HalResult<void>::fromStatus(getHal()->setAmplitude(convertedAmplitude));
}
HalResult<void> AidlHalWrapper::setExternalControl(bool enabled) {
- return HalResult<void>::fromStatus(mHandle->setExternalControl(enabled));
+ return HalResult<void>::fromStatus(getHal()->setExternalControl(enabled));
}
HalResult<void> AidlHalWrapper::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) {
- return HalResult<void>::fromStatus(mHandle->alwaysOnEnable(id, effect, strength));
+ return HalResult<void>::fromStatus(getHal()->alwaysOnEnable(id, effect, strength));
}
HalResult<void> AidlHalWrapper::alwaysOnDisable(int32_t id) {
- return HalResult<void>::fromStatus(mHandle->alwaysOnDisable(id));
+ return HalResult<void>::fromStatus(getHal()->alwaysOnDisable(id));
}
HalResult<Capabilities> AidlHalWrapper::getCapabilities() {
@@ -210,7 +218,7 @@
auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr;
int32_t lengthMs;
- auto result = mHandle->perform(effect, strength, cb, &lengthMs);
+ auto result = getHal()->perform(effect, strength, cb, &lengthMs);
milliseconds length = milliseconds(lengthMs);
auto ret = HalResult<milliseconds>::fromStatus(result, length);
@@ -226,31 +234,47 @@
const std::function<void()>& completionCallback) {
// This method should always support callbacks, so no need to double check.
auto cb = new HalCallbackWrapper(completionCallback);
- return HalResult<void>::fromStatus(mHandle->compose(primitiveEffects, cb));
+ return HalResult<void>::fromStatus(getHal()->compose(primitiveEffects, cb));
}
HalResult<Capabilities> AidlHalWrapper::getCapabilitiesInternal() {
int32_t capabilities = 0;
- auto result = mHandle->getCapabilities(&capabilities);
+ auto result = getHal()->getCapabilities(&capabilities);
return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities));
}
HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffectsInternal() {
std::vector<Effect> supportedEffects;
- auto result = mHandle->getSupportedEffects(&supportedEffects);
+ auto result = getHal()->getSupportedEffects(&supportedEffects);
return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects);
}
+sp<Aidl::IVibrator> AidlHalWrapper::getHal() {
+ std::lock_guard<std::mutex> lock(mHandleMutex);
+ return mHandle;
+}
+
// -------------------------------------------------------------------------------------------------
-HalResult<void> HidlHalWrapperV1_0::ping() {
- auto result = mHandleV1_0->ping();
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::ping() {
+ auto result = getHal()->ping();
return HalResult<void>::fromReturn(result);
}
-HalResult<void> HidlHalWrapperV1_0::on(milliseconds timeout,
- const std::function<void()>& completionCallback) {
- auto result = mHandleV1_0->on(timeout.count());
+template <typename I>
+void HidlHalWrapper<I>::tryReconnect() {
+ sp<I> newHandle = I::tryGetService();
+ if (newHandle) {
+ std::lock_guard<std::mutex> lock(mHandleMutex);
+ mHandle = std::move(newHandle);
+ }
+}
+
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::on(milliseconds timeout,
+ const std::function<void()>& completionCallback) {
+ auto result = getHal()->on(timeout.count());
auto ret = HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
if (ret.isOk()) {
mCallbackScheduler->schedule(completionCallback, timeout);
@@ -258,69 +282,68 @@
return ret;
}
-HalResult<void> HidlHalWrapperV1_0::off() {
- auto result = mHandleV1_0->off();
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::off() {
+ auto result = getHal()->off();
return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
}
-HalResult<void> HidlHalWrapperV1_0::setAmplitude(int32_t amplitude) {
- auto result = mHandleV1_0->setAmplitude(static_cast<uint8_t>(amplitude));
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::setAmplitude(int32_t amplitude) {
+ auto result = getHal()->setAmplitude(static_cast<uint8_t>(amplitude));
return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
}
-HalResult<void> HidlHalWrapperV1_0::setExternalControl(bool) {
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::setExternalControl(bool) {
ALOGV("Skipped setExternalControl because Vibrator HAL does not support it");
return HalResult<void>::unsupported();
}
-HalResult<void> HidlHalWrapperV1_0::alwaysOnEnable(int32_t, Effect, EffectStrength) {
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::alwaysOnEnable(int32_t, Effect, EffectStrength) {
ALOGV("Skipped alwaysOnEnable because Vibrator HAL AIDL is not available");
return HalResult<void>::unsupported();
}
-HalResult<void> HidlHalWrapperV1_0::alwaysOnDisable(int32_t) {
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::alwaysOnDisable(int32_t) {
ALOGV("Skipped alwaysOnDisable because Vibrator HAL AIDL is not available");
return HalResult<void>::unsupported();
}
-HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilities() {
+template <typename I>
+HalResult<Capabilities> HidlHalWrapper<I>::getCapabilities() {
std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
- return loadCached<Capabilities>(std::bind(&HidlHalWrapperV1_0::getCapabilitiesInternal, this),
+ return loadCached<Capabilities>(std::bind(&HidlHalWrapper<I>::getCapabilitiesInternal, this),
mCapabilities);
}
-HalResult<std::vector<Effect>> HidlHalWrapperV1_0::getSupportedEffects() {
+template <typename I>
+HalResult<std::vector<Effect>> HidlHalWrapper<I>::getSupportedEffects() {
ALOGV("Skipped getSupportedEffects because Vibrator HAL AIDL is not available");
return HalResult<std::vector<Effect>>::unsupported();
}
-HalResult<milliseconds> HidlHalWrapperV1_0::performEffect(
- Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
- if (isStaticCastValid<V1_0::Effect>(effect)) {
- return performInternalV1_0(effect, strength, completionCallback);
- }
-
- ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
- Aidl::toString(effect).c_str());
- return HalResult<milliseconds>::unsupported();
-}
-
-HalResult<void> HidlHalWrapperV1_0::performComposedEffect(const std::vector<CompositeEffect>&,
- const std::function<void()>&) {
+template <typename I>
+HalResult<void> HidlHalWrapper<I>::performComposedEffect(const std::vector<CompositeEffect>&,
+ const std::function<void()>&) {
ALOGV("Skipped composed effect because Vibrator HAL AIDL is not available");
return HalResult<void>::unsupported();
}
-HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilitiesInternal() {
- hardware::Return<bool> result = mHandleV1_0->supportsAmplitudeControl();
+template <typename I>
+HalResult<Capabilities> HidlHalWrapper<I>::getCapabilitiesInternal() {
+ hardware::Return<bool> result = getHal()->supportsAmplitudeControl();
Capabilities capabilities =
result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE;
return HalResult<Capabilities>::fromReturn(result, capabilities);
}
-template <class I, class T>
-HalResult<milliseconds> HidlHalWrapperV1_0::performInternal(
- perform_fn<I, T> performFn, sp<I> handle, T effect, EffectStrength strength,
+template <typename I>
+template <typename T>
+HalResult<milliseconds> HidlHalWrapper<I>::performInternal(
+ perform_fn<T> performFn, sp<I> handle, T effect, EffectStrength strength,
const std::function<void()>& completionCallback) {
V1_0::Status status;
int32_t lengthMs;
@@ -341,10 +364,24 @@
return ret;
}
-HalResult<milliseconds> HidlHalWrapperV1_0::performInternalV1_0(
+template <typename I>
+sp<I> HidlHalWrapper<I>::getHal() {
+ std::lock_guard<std::mutex> lock(mHandleMutex);
+ return mHandle;
+}
+
+// -------------------------------------------------------------------------------------------------
+
+HalResult<milliseconds> HidlHalWrapperV1_0::performEffect(
Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
- V1_0::Effect e = static_cast<V1_0::Effect>(effect);
- return performInternal(&V1_0::IVibrator::perform, mHandleV1_0, e, strength, completionCallback);
+ if (isStaticCastValid<V1_0::Effect>(effect)) {
+ return performInternal(&V1_0::IVibrator::perform, getHal(),
+ static_cast<V1_0::Effect>(effect), strength, completionCallback);
+ }
+
+ ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
+ Aidl::toString(effect).c_str());
+ return HalResult<milliseconds>::unsupported();
}
// -------------------------------------------------------------------------------------------------
@@ -352,10 +389,12 @@
HalResult<milliseconds> HidlHalWrapperV1_1::performEffect(
Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
if (isStaticCastValid<V1_0::Effect>(effect)) {
- return performInternalV1_0(effect, strength, completionCallback);
+ return performInternal(&V1_1::IVibrator::perform, getHal(),
+ static_cast<V1_0::Effect>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
- return performInternalV1_1(effect, strength, completionCallback);
+ return performInternal(&V1_1::IVibrator::perform_1_1, getHal(),
+ static_cast<V1_1::Effect_1_1>(effect), strength, completionCallback);
}
ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
@@ -363,25 +402,21 @@
return HalResult<milliseconds>::unsupported();
}
-HalResult<milliseconds> HidlHalWrapperV1_1::performInternalV1_1(
- Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
- V1_1::Effect_1_1 e = static_cast<V1_1::Effect_1_1>(effect);
- return performInternal(&V1_1::IVibrator::perform_1_1, mHandleV1_1, e, strength,
- completionCallback);
-}
-
// -------------------------------------------------------------------------------------------------
HalResult<milliseconds> HidlHalWrapperV1_2::performEffect(
Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
if (isStaticCastValid<V1_0::Effect>(effect)) {
- return performInternalV1_0(effect, strength, completionCallback);
+ return performInternal(&V1_2::IVibrator::perform, getHal(),
+ static_cast<V1_0::Effect>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
- return performInternalV1_1(effect, strength, completionCallback);
+ return performInternal(&V1_2::IVibrator::perform_1_1, getHal(),
+ static_cast<V1_1::Effect_1_1>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_2::Effect>(effect)) {
- return performInternalV1_2(effect, strength, completionCallback);
+ return performInternal(&V1_2::IVibrator::perform_1_2, getHal(),
+ static_cast<V1_2::Effect>(effect), strength, completionCallback);
}
ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
@@ -389,33 +424,30 @@
return HalResult<milliseconds>::unsupported();
}
-HalResult<milliseconds> HidlHalWrapperV1_2::performInternalV1_2(
- Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
- V1_2::Effect e = static_cast<V1_2::Effect>(effect);
- return performInternal(&V1_2::IVibrator::perform_1_2, mHandleV1_2, e, strength,
- completionCallback);
-}
-
// -------------------------------------------------------------------------------------------------
HalResult<void> HidlHalWrapperV1_3::setExternalControl(bool enabled) {
- auto result = mHandleV1_3->setExternalControl(static_cast<uint32_t>(enabled));
+ auto result = getHal()->setExternalControl(static_cast<uint32_t>(enabled));
return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
}
HalResult<milliseconds> HidlHalWrapperV1_3::performEffect(
Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
if (isStaticCastValid<V1_0::Effect>(effect)) {
- return performInternalV1_0(effect, strength, completionCallback);
+ return performInternal(&V1_3::IVibrator::perform, getHal(),
+ static_cast<V1_0::Effect>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_1::Effect_1_1>(effect)) {
- return performInternalV1_1(effect, strength, completionCallback);
+ return performInternal(&V1_3::IVibrator::perform_1_1, getHal(),
+ static_cast<V1_1::Effect_1_1>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_2::Effect>(effect)) {
- return performInternalV1_2(effect, strength, completionCallback);
+ return performInternal(&V1_3::IVibrator::perform_1_2, getHal(),
+ static_cast<V1_2::Effect>(effect), strength, completionCallback);
}
if (isStaticCastValid<V1_3::Effect>(effect)) {
- return performInternalV1_3(effect, strength, completionCallback);
+ return performInternal(&V1_3::IVibrator::perform_1_3, getHal(),
+ static_cast<V1_3::Effect>(effect), strength, completionCallback);
}
ALOGV("Skipped performEffect because Vibrator HAL does not support effect %s",
@@ -424,23 +456,23 @@
}
HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() {
- HalResult<Capabilities> parentResult = HidlHalWrapperV1_2::getCapabilitiesInternal();
- if (!parentResult.isOk()) {
- // Loading for previous HAL versions already failed, so propagate failure.
- return parentResult;
+ sp<V1_3::IVibrator> hal = getHal();
+ auto amplitudeResult = hal->supportsAmplitudeControl();
+ if (!amplitudeResult.isOk()) {
+ return HalResult<Capabilities>::failed();
}
- Capabilities capabilities = parentResult.value();
- auto result = mHandleV1_3->supportsExternalControl();
- capabilities |= result.withDefault(false) ? Capabilities::EXTERNAL_CONTROL : Capabilities::NONE;
- return HalResult<Capabilities>::fromReturn(result, capabilities);
-}
+ auto externalControlResult = hal->supportsExternalControl();
+ Capabilities capabilities = Capabilities::NONE;
-HalResult<milliseconds> HidlHalWrapperV1_3::performInternalV1_3(
- Effect effect, EffectStrength strength, const std::function<void()>& completionCallback) {
- V1_3::Effect e = static_cast<V1_3::Effect>(effect);
- return performInternal(&V1_3::IVibrator::perform_1_3, mHandleV1_3, e, strength,
- completionCallback);
+ if (amplitudeResult.withDefault(false)) {
+ capabilities |= Capabilities::AMPLITUDE_CONTROL;
+ }
+ if (externalControlResult.withDefault(false)) {
+ capabilities |= Capabilities::EXTERNAL_CONTROL;
+ }
+
+ return HalResult<Capabilities>::fromReturn(externalControlResult, capabilities);
}
// -------------------------------------------------------------------------------------------------
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalController.h b/services/vibratorservice/include/vibratorservice/VibratorHalController.h
index 1fb7d05..daf2c8c 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalController.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalController.h
@@ -51,7 +51,10 @@
mConnectedHal(nullptr) {}
virtual ~HalController() = default;
+ void init();
+
HalResult<void> ping() final override;
+ void tryReconnect() final override;
HalResult<void> on(std::chrono::milliseconds timeout,
const std::function<void()>& completionCallback) final override;
@@ -81,8 +84,6 @@
// Shared pointer to allow local copies to be used by different threads.
std::shared_ptr<HalWrapper> mConnectedHal GUARDED_BY(mConnectedHalMutex);
- std::shared_ptr<HalWrapper> initHal();
-
template <typename T>
HalResult<T> processHalResult(HalResult<T> result, const char* functionName);
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index 5e3c275..a4fa869 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -20,6 +20,7 @@
#include <android-base/thread_annotations.h>
#include <android/hardware/vibrator/1.3/IVibrator.h>
#include <android/hardware/vibrator/IVibrator.h>
+#include <binder/IServiceManager.h>
#include <vibratorservice/VibratorCallbackScheduler.h>
@@ -131,6 +132,7 @@
virtual ~HalWrapper() = default;
virtual HalResult<void> ping() = 0;
+ virtual void tryReconnect() = 0;
virtual HalResult<void> on(std::chrono::milliseconds timeout,
const std::function<void()>& completionCallback) = 0;
@@ -167,34 +169,36 @@
: HalWrapper(std::move(scheduler)), mHandle(std::move(handle)) {}
virtual ~AidlHalWrapper() = default;
- virtual HalResult<void> ping() override;
+ HalResult<void> ping() override final;
+ void tryReconnect() override final;
- virtual HalResult<void> on(std::chrono::milliseconds timeout,
- const std::function<void()>& completionCallback) override;
- virtual HalResult<void> off() override;
+ HalResult<void> on(std::chrono::milliseconds timeout,
+ const std::function<void()>& completionCallback) override final;
+ HalResult<void> off() override final;
- virtual HalResult<void> setAmplitude(int32_t amplitude) override;
- virtual HalResult<void> setExternalControl(bool enabled) override;
+ HalResult<void> setAmplitude(int32_t amplitude) override final;
+ HalResult<void> setExternalControl(bool enabled) override final;
- virtual HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
- hardware::vibrator::EffectStrength strength) override;
- virtual HalResult<void> alwaysOnDisable(int32_t id) override;
+ HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
+ hardware::vibrator::EffectStrength strength) override final;
+ HalResult<void> alwaysOnDisable(int32_t id) override final;
- virtual HalResult<Capabilities> getCapabilities() override;
- virtual HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffects() override;
+ HalResult<Capabilities> getCapabilities() override final;
+ HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffects() override final;
- virtual HalResult<std::chrono::milliseconds> performEffect(
+ HalResult<std::chrono::milliseconds> performEffect(
hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback) override;
+ const std::function<void()>& completionCallback) override final;
- virtual HalResult<void> performComposedEffect(
+ HalResult<void> performComposedEffect(
const std::vector<hardware::vibrator::CompositeEffect>& primitiveEffects,
- const std::function<void()>& completionCallback) override;
+ const std::function<void()>& completionCallback) override final;
private:
- const sp<hardware::vibrator::IVibrator> mHandle;
+ std::mutex mHandleMutex;
std::mutex mCapabilitiesMutex;
std::mutex mSupportedEffectsMutex;
+ sp<hardware::vibrator::IVibrator> mHandle GUARDED_BY(mHandleMutex);
std::optional<Capabilities> mCapabilities GUARDED_BY(mCapabilitiesMutex);
std::optional<std::vector<hardware::vibrator::Effect>> mSupportedEffects
GUARDED_BY(mSupportedEffectsMutex);
@@ -202,125 +206,120 @@
// Loads directly from IVibrator handle, skipping caches.
HalResult<Capabilities> getCapabilitiesInternal();
HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffectsInternal();
+ sp<hardware::vibrator::IVibrator> getHal();
};
-// Wrapper for the HDIL Vibrator HAL v1.0.
-class HidlHalWrapperV1_0 : public HalWrapper {
+// Wrapper for the HDIL Vibrator HALs.
+template <typename I>
+class HidlHalWrapper : public HalWrapper {
public:
- HidlHalWrapperV1_0(std::shared_ptr<CallbackScheduler> scheduler,
- sp<hardware::vibrator::V1_0::IVibrator> handle)
- : HalWrapper(std::move(scheduler)), mHandleV1_0(std::move(handle)) {}
- virtual ~HidlHalWrapperV1_0() = default;
+ HidlHalWrapper(std::shared_ptr<CallbackScheduler> scheduler, sp<I> handle)
+ : HalWrapper(std::move(scheduler)), mHandle(std::move(handle)) {}
+ virtual ~HidlHalWrapper() = default;
- virtual HalResult<void> ping() override;
+ HalResult<void> ping() override final;
+ void tryReconnect() override final;
- virtual HalResult<void> on(std::chrono::milliseconds timeout,
- const std::function<void()>& completionCallback) override;
- virtual HalResult<void> off() override;
+ HalResult<void> on(std::chrono::milliseconds timeout,
+ const std::function<void()>& completionCallback) override final;
+ HalResult<void> off() override final;
- virtual HalResult<void> setAmplitude(int32_t amplitude) override;
+ HalResult<void> setAmplitude(int32_t amplitude) override final;
virtual HalResult<void> setExternalControl(bool enabled) override;
- virtual HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
- hardware::vibrator::EffectStrength strength) override;
- virtual HalResult<void> alwaysOnDisable(int32_t id) override;
+ HalResult<void> alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect,
+ hardware::vibrator::EffectStrength strength) override final;
+ HalResult<void> alwaysOnDisable(int32_t id) override final;
- virtual HalResult<Capabilities> getCapabilities() override;
- virtual HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffects() override;
+ HalResult<Capabilities> getCapabilities() override final;
+ HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffects() override final;
- virtual HalResult<std::chrono::milliseconds> performEffect(
- hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback) override;
-
- virtual HalResult<void> performComposedEffect(
+ HalResult<void> performComposedEffect(
const std::vector<hardware::vibrator::CompositeEffect>& primitiveEffects,
- const std::function<void()>& completionCallback) override;
+ const std::function<void()>& completionCallback) override final;
protected:
- const sp<hardware::vibrator::V1_0::IVibrator> mHandleV1_0;
+ std::mutex mHandleMutex;
std::mutex mCapabilitiesMutex;
+ sp<I> mHandle GUARDED_BY(mHandleMutex);
std::optional<Capabilities> mCapabilities GUARDED_BY(mCapabilitiesMutex);
// Loads directly from IVibrator handle, skipping the mCapabilities cache.
virtual HalResult<Capabilities> getCapabilitiesInternal();
- template <class I, class T>
+ template <class T>
using perform_fn =
hardware::Return<void> (I::*)(T, hardware::vibrator::V1_0::EffectStrength,
hardware::vibrator::V1_0::IVibrator::perform_cb);
- template <class I, class T>
+ template <class T>
HalResult<std::chrono::milliseconds> performInternal(
- perform_fn<I, T> performFn, sp<I> handle, T effect,
+ perform_fn<T> performFn, sp<I> handle, T effect,
hardware::vibrator::EffectStrength strength,
const std::function<void()>& completionCallback);
- HalResult<std::chrono::milliseconds> performInternalV1_0(
+ sp<I> getHal();
+};
+
+// Wrapper for the HDIL Vibrator HAL v1.0.
+class HidlHalWrapperV1_0 : public HidlHalWrapper<hardware::vibrator::V1_0::IVibrator> {
+public:
+ HidlHalWrapperV1_0(std::shared_ptr<CallbackScheduler> scheduler,
+ sp<hardware::vibrator::V1_0::IVibrator> handle)
+ : HidlHalWrapper<hardware::vibrator::V1_0::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
+ virtual ~HidlHalWrapperV1_0() = default;
+
+ HalResult<std::chrono::milliseconds> performEffect(
hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback);
+ const std::function<void()>& completionCallback) override final;
};
// Wrapper for the HDIL Vibrator HAL v1.1.
-class HidlHalWrapperV1_1 : public HidlHalWrapperV1_0 {
+class HidlHalWrapperV1_1 : public HidlHalWrapper<hardware::vibrator::V1_1::IVibrator> {
public:
HidlHalWrapperV1_1(std::shared_ptr<CallbackScheduler> scheduler,
sp<hardware::vibrator::V1_1::IVibrator> handle)
- : HidlHalWrapperV1_0(std::move(scheduler), handle), mHandleV1_1(handle) {}
+ : HidlHalWrapper<hardware::vibrator::V1_1::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
virtual ~HidlHalWrapperV1_1() = default;
- virtual HalResult<std::chrono::milliseconds> performEffect(
+ HalResult<std::chrono::milliseconds> performEffect(
hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback) override;
-
-protected:
- const sp<hardware::vibrator::V1_1::IVibrator> mHandleV1_1;
-
- HalResult<std::chrono::milliseconds> performInternalV1_1(
- hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback);
+ const std::function<void()>& completionCallback) override final;
};
// Wrapper for the HDIL Vibrator HAL v1.2.
-class HidlHalWrapperV1_2 : public HidlHalWrapperV1_1 {
+class HidlHalWrapperV1_2 : public HidlHalWrapper<hardware::vibrator::V1_2::IVibrator> {
public:
HidlHalWrapperV1_2(std::shared_ptr<CallbackScheduler> scheduler,
sp<hardware::vibrator::V1_2::IVibrator> handle)
- : HidlHalWrapperV1_1(std::move(scheduler), handle), mHandleV1_2(handle) {}
+ : HidlHalWrapper<hardware::vibrator::V1_2::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
virtual ~HidlHalWrapperV1_2() = default;
- virtual HalResult<std::chrono::milliseconds> performEffect(
+ HalResult<std::chrono::milliseconds> performEffect(
hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback) override;
-
-protected:
- const sp<hardware::vibrator::V1_2::IVibrator> mHandleV1_2;
-
- HalResult<std::chrono::milliseconds> performInternalV1_2(
- hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback);
+ const std::function<void()>& completionCallback) override final;
};
// Wrapper for the HDIL Vibrator HAL v1.3.
-class HidlHalWrapperV1_3 : public HidlHalWrapperV1_2 {
+class HidlHalWrapperV1_3 : public HidlHalWrapper<hardware::vibrator::V1_3::IVibrator> {
public:
HidlHalWrapperV1_3(std::shared_ptr<CallbackScheduler> scheduler,
sp<hardware::vibrator::V1_3::IVibrator> handle)
- : HidlHalWrapperV1_2(std::move(scheduler), handle), mHandleV1_3(handle) {}
+ : HidlHalWrapper<hardware::vibrator::V1_3::IVibrator>(std::move(scheduler),
+ std::move(handle)) {}
virtual ~HidlHalWrapperV1_3() = default;
- virtual HalResult<void> setExternalControl(bool enabled) override;
+ HalResult<void> setExternalControl(bool enabled) override final;
- virtual HalResult<std::chrono::milliseconds> performEffect(
+ HalResult<std::chrono::milliseconds> performEffect(
hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback) override;
+ const std::function<void()>& completionCallback) override final;
protected:
- const sp<hardware::vibrator::V1_3::IVibrator> mHandleV1_3;
-
- virtual HalResult<Capabilities> getCapabilitiesInternal() override;
- HalResult<std::chrono::milliseconds> performInternalV1_3(
- hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
- const std::function<void()>& completionCallback);
+ HalResult<Capabilities> getCapabilitiesInternal() override final;
};
// -------------------------------------------------------------------------------------------------
diff --git a/services/vibratorservice/test/VibratorHalControllerTest.cpp b/services/vibratorservice/test/VibratorHalControllerTest.cpp
index 24e6a1e..2d55549 100644
--- a/services/vibratorservice/test/VibratorHalControllerTest.cpp
+++ b/services/vibratorservice/test/VibratorHalControllerTest.cpp
@@ -53,6 +53,7 @@
virtual ~MockHalWrapper() = default;
MOCK_METHOD(vibrator::HalResult<void>, ping, (), (override));
+ MOCK_METHOD(void, tryReconnect, (), (override));
MOCK_METHOD(vibrator::HalResult<void>, on,
(milliseconds timeout, const std::function<void()>& completionCallback),
(override));
@@ -132,7 +133,6 @@
vibrator::HalResult<vibrator::Capabilities> capabilitiesResult,
vibrator::HalResult<std::vector<Effect>> effectsResult,
vibrator::HalResult<milliseconds> durationResult) {
- InSequence seq;
EXPECT_CALL(*mMockHal.get(), ping())
.Times(Exactly(cardinality))
.WillRepeatedly(Return(voidResult));
@@ -167,11 +167,25 @@
EXPECT_CALL(*mMockHal.get(), performComposedEffect(Eq(compositeEffects), _))
.Times(Exactly(cardinality))
.WillRepeatedly(Return(voidResult));
+
+ if (cardinality > 1) {
+ // One reconnection call after each failure.
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(11 * cardinality));
+ }
}
};
// -------------------------------------------------------------------------------------------------
+TEST_F(VibratorHalControllerTest, TestInit) {
+ mController->init();
+ ASSERT_EQ(1, mConnectCounter);
+
+ // Noop when wrapper was already initialized.
+ mController->init();
+ ASSERT_EQ(1, mConnectCounter);
+}
+
TEST_F(VibratorHalControllerTest, TestApiCallsAreForwardedToHal) {
std::vector<Effect> supportedEffects;
supportedEffects.push_back(Effect::CLICK);
@@ -211,7 +225,6 @@
ASSERT_TRUE(mController->performComposedEffect(compositeEffects, []() {}).isOk());
- // No reconnection attempt was made after the first one.
ASSERT_EQ(1, mConnectCounter);
}
@@ -239,7 +252,6 @@
ASSERT_TRUE(mController->performComposedEffect(std::vector<CompositeEffect>(), []() {})
.isUnsupported());
- // No reconnection attempt was made after the first one.
ASSERT_EQ(1, mConnectCounter);
}
@@ -266,23 +278,24 @@
ASSERT_TRUE(
mController->performComposedEffect(std::vector<CompositeEffect>(), []() {}).isFailed());
- // One reconnection attempt + retry attempts per api call.
- ASSERT_EQ(11 * MAX_ATTEMPTS, mConnectCounter);
+ ASSERT_EQ(1, mConnectCounter);
}
TEST_F(VibratorHalControllerTest, TestFailedApiResultReturnsSuccessAfterRetries) {
{
InSequence seq;
EXPECT_CALL(*mMockHal.get(), ping())
- .Times(Exactly(2))
- .WillOnce(Return(vibrator::HalResult<void>::failed()))
+ .Times(Exactly(1))
+ .WillRepeatedly(Return(vibrator::HalResult<void>::failed()));
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
+ EXPECT_CALL(*mMockHal.get(), ping())
+ .Times(Exactly(1))
.WillRepeatedly(Return(vibrator::HalResult<void>::ok()));
}
ASSERT_EQ(0, mConnectCounter);
ASSERT_TRUE(mController->ping().isOk());
- // One connect + one retry.
- ASSERT_EQ(2, mConnectCounter);
+ ASSERT_EQ(1, mConnectCounter);
}
TEST_F(VibratorHalControllerTest, TestMultiThreadConnectsOnlyOnce) {
@@ -323,7 +336,7 @@
ASSERT_TRUE(mController->performComposedEffect(std::vector<CompositeEffect>(), []() {})
.isUnsupported());
- // One reconnection attempt per api call, no retry.
+ // One connection attempt per api call.
ASSERT_EQ(11, mConnectCounter);
}
@@ -337,19 +350,24 @@
return vibrator::HalResult<void>::ok();
});
EXPECT_CALL(*mMockHal.get(), ping())
- .Times(Exactly(MAX_ATTEMPTS))
+ .Times(Exactly(1))
.WillRepeatedly(Return(vibrator::HalResult<void>::failed()));
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
+ EXPECT_CALL(*mMockHal.get(), ping())
+ .Times(Exactly(1))
+ .WillRepeatedly(Return(vibrator::HalResult<void>::failed()));
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(1));
}
std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
ASSERT_TRUE(mController->on(10ms, callback).isOk());
- ASSERT_TRUE(mController->ping().isFailed()); // Delete connected HAL pointer from controller.
- mMockHal.reset(); // Delete mock HAL pointer from test class.
+ ASSERT_TRUE(mController->ping().isFailed());
+ mMockHal.reset();
ASSERT_EQ(0, *callbackCounter.get());
- // Callback triggered even after HalWrapper was completely destroyed.
+ // Callback triggered even after HalWrapper was reconnected.
std::this_thread::sleep_for(15ms);
ASSERT_EQ(1, *callbackCounter.get());
}
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 5b9affd..80166c8 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -1256,7 +1256,7 @@
ATRACE_CALL();
if (!EnsureInitialized())
- return VK_ERROR_INITIALIZATION_FAILED;
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
uint32_t count = GetLayerCount();
@@ -1280,7 +1280,7 @@
ATRACE_CALL();
if (!EnsureInitialized())
- return VK_ERROR_INITIALIZATION_FAILED;
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
if (pLayerName) {
const Layer* layer = FindLayer(pLayerName);
@@ -1456,6 +1456,11 @@
VkResult EnumerateInstanceVersion(uint32_t* pApiVersion) {
ATRACE_CALL();
+ // Load the driver here if not done yet. This api will be used in Zygote
+ // for Vulkan driver pre-loading because of the minimum overhead.
+ if (!EnsureInitialized())
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
*pApiVersion = VK_API_VERSION_1_1;
return VK_SUCCESS;
}
diff --git a/vulkan/libvulkan/api.h b/vulkan/libvulkan/api.h
index 416cba0..2a215d7 100644
--- a/vulkan/libvulkan/api.h
+++ b/vulkan/libvulkan/api.h
@@ -24,17 +24,34 @@
namespace vulkan {
namespace api {
-// clang-format off
-VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
-VKAPI_ATTR void DestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
-VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR VkResult EnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties);
-VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
-VKAPI_ATTR VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties);
-VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkInstance* pInstance);
+VKAPI_ATTR void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice);
+VKAPI_ATTR void DestroyDevice(VkDevice device,
+ const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult
+EnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
+ VkLayerProperties* pProperties);
+VKAPI_ATTR VkResult
+EnumerateInstanceExtensionProperties(const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult
+EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkLayerProperties* pProperties);
+VKAPI_ATTR VkResult
+EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
VKAPI_ATTR VkResult EnumerateInstanceVersion(uint32_t* pApiVersion);
-// clang-format on
inline InstanceData& GetData(VkInstance instance) {
return driver::GetData(instance).opaque_api_data;
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 74ef0e7..e3fc67e 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -95,15 +95,15 @@
class CreateInfoWrapper {
public:
CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
+ uint32_t icd_api_version,
const VkAllocationCallbacks& allocator);
CreateInfoWrapper(VkPhysicalDevice physical_dev,
const VkDeviceCreateInfo& create_info,
+ uint32_t icd_api_version,
const VkAllocationCallbacks& allocator);
~CreateInfoWrapper();
VkResult Validate();
- void DowngradeApiVersion();
- void UpgradeDeviceCoreApiVersion(uint32_t api_version);
const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
@@ -120,8 +120,8 @@
uint32_t name_count;
};
+ VkResult SanitizeApiVersion();
VkResult SanitizePNext();
-
VkResult SanitizeLayers();
VkResult SanitizeExtensions();
@@ -133,6 +133,8 @@
const bool is_instance_;
const VkAllocationCallbacks& allocator_;
+ const uint32_t loader_api_version_;
+ const uint32_t icd_api_version_;
VkPhysicalDevice physical_dev_;
@@ -324,32 +326,27 @@
}
CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
+ uint32_t icd_api_version,
const VkAllocationCallbacks& allocator)
: is_instance_(true),
allocator_(allocator),
+ loader_api_version_(VK_API_VERSION_1_1),
+ icd_api_version_(icd_api_version),
physical_dev_(VK_NULL_HANDLE),
instance_info_(create_info),
- extension_filter_() {
- // instance core versions need to match the loader api version
- for (uint32_t i = ProcHook::EXTENSION_CORE_1_0;
- i != ProcHook::EXTENSION_COUNT; ++i) {
- hook_extensions_.set(i);
- hal_extensions_.set(i);
- }
-}
+ extension_filter_() {}
CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
const VkDeviceCreateInfo& create_info,
+ uint32_t icd_api_version,
const VkAllocationCallbacks& allocator)
: is_instance_(false),
allocator_(allocator),
+ loader_api_version_(VK_API_VERSION_1_1),
+ icd_api_version_(icd_api_version),
physical_dev_(physical_dev),
dev_info_(create_info),
- extension_filter_() {
- // initialize with baseline core API version
- hook_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
- hal_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
-}
+ extension_filter_() {}
CreateInfoWrapper::~CreateInfoWrapper() {
allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
@@ -357,7 +354,9 @@
}
VkResult CreateInfoWrapper::Validate() {
- VkResult result = SanitizePNext();
+ VkResult result = SanitizeApiVersion();
+ if (result == VK_SUCCESS)
+ result = SanitizePNext();
if (result == VK_SUCCESS)
result = SanitizeLayers();
if (result == VK_SUCCESS)
@@ -384,6 +383,22 @@
return &dev_info_;
}
+VkResult CreateInfoWrapper::SanitizeApiVersion() {
+ if (!is_instance_ || !instance_info_.pApplicationInfo)
+ return VK_SUCCESS;
+
+ if (icd_api_version_ > VK_API_VERSION_1_0 ||
+ instance_info_.pApplicationInfo->apiVersion < VK_API_VERSION_1_1)
+ return VK_SUCCESS;
+
+ // override apiVersion to avoid error return from 1.0 icd
+ application_info_ = *instance_info_.pApplicationInfo;
+ application_info_.apiVersion = VK_API_VERSION_1_0;
+ instance_info_.pApplicationInfo = &application_info_;
+
+ return VK_SUCCESS;
+}
+
VkResult CreateInfoWrapper::SanitizePNext() {
const struct StructHeader {
VkStructureType type;
@@ -431,15 +446,33 @@
: dev_info_.ppEnabledExtensionNames;
auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
: dev_info_.enabledExtensionCount;
- if (!ext_count)
- return VK_SUCCESS;
VkResult result = InitExtensionFilter();
if (result != VK_SUCCESS)
return result;
- for (uint32_t i = 0; i < ext_count; i++)
- FilterExtension(ext_names[i]);
+ if (is_instance_ && icd_api_version_ < loader_api_version_) {
+ for (uint32_t i = 0; i < ext_count; i++) {
+ // Upon api downgrade, skip the promoted instance extensions in the
+ // first pass to avoid duplicate extensions.
+ const std::optional<uint32_t> version =
+ GetInstanceExtensionPromotedVersion(ext_names[i]);
+ if (version && *version > icd_api_version_ &&
+ *version <= loader_api_version_)
+ continue;
+
+ FilterExtension(ext_names[i]);
+ }
+
+ // Enable the required extensions to support core functionalities.
+ const auto promoted_extensions = GetPromotedInstanceExtensions(
+ icd_api_version_, loader_api_version_);
+ for (const auto& promoted_extension : promoted_extensions)
+ FilterExtension(promoted_extension);
+ } else {
+ for (uint32_t i = 0; i < ext_count; i++)
+ FilterExtension(ext_names[i]);
+ }
// Enable device extensions that contain physical-device commands, so that
// vkGetInstanceProcAddr will return those physical-device commands.
@@ -447,6 +480,23 @@
hook_extensions_.set(ProcHook::KHR_swapchain);
}
+ const uint32_t api_version =
+ is_instance_ ? loader_api_version_
+ : std::min(icd_api_version_, loader_api_version_);
+ switch (api_version) {
+ case VK_API_VERSION_1_1:
+ hook_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
+ [[clang::fallthrough]];
+ case VK_API_VERSION_1_0:
+ hook_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
+ break;
+ default:
+ ALOGE("Unknown API version[%u]", api_version);
+ break;
+ }
+
ext_names = extension_filter_.names;
ext_count = extension_filter_.name_count;
@@ -504,10 +554,20 @@
filter.ext_count = count;
// allocate name array
- uint32_t enabled_ext_count = (is_instance_)
- ? instance_info_.enabledExtensionCount
- : dev_info_.enabledExtensionCount;
- count = std::min(filter.ext_count, enabled_ext_count);
+ if (is_instance_) {
+ uint32_t enabled_ext_count = instance_info_.enabledExtensionCount;
+
+ // It requires enabling additional promoted extensions to downgrade api,
+ // so we reserve enough space here.
+ if (icd_api_version_ < loader_api_version_) {
+ enabled_ext_count += CountPromotedInstanceExtensions(
+ icd_api_version_, loader_api_version_);
+ }
+
+ count = std::min(filter.ext_count, enabled_ext_count);
+ } else {
+ count = std::min(filter.ext_count, dev_info_.enabledExtensionCount);
+ }
filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
@@ -535,6 +595,10 @@
hook_extensions_.set(ext_bit);
break;
case ProcHook::KHR_get_physical_device_properties2:
+ case ProcHook::KHR_device_group_creation:
+ case ProcHook::KHR_external_memory_capabilities:
+ case ProcHook::KHR_external_semaphore_capabilities:
+ case ProcHook::KHR_external_fence_capabilities:
case ProcHook::EXTENSION_UNKNOWN:
// Extensions we don't need to do anything about at this level
break;
@@ -591,6 +655,10 @@
case ProcHook::KHR_android_surface:
case ProcHook::KHR_get_physical_device_properties2:
+ case ProcHook::KHR_device_group_creation:
+ case ProcHook::KHR_external_memory_capabilities:
+ case ProcHook::KHR_external_semaphore_capabilities:
+ case ProcHook::KHR_external_fence_capabilities:
case ProcHook::KHR_get_surface_capabilities2:
case ProcHook::KHR_surface:
case ProcHook::EXT_debug_report:
@@ -636,40 +704,6 @@
}
}
-void CreateInfoWrapper::DowngradeApiVersion() {
- // If pApplicationInfo is NULL, apiVersion is assumed to be 1.0:
- if (instance_info_.pApplicationInfo) {
- application_info_ = *instance_info_.pApplicationInfo;
- instance_info_.pApplicationInfo = &application_info_;
- application_info_.apiVersion = VK_API_VERSION_1_0;
- }
-}
-
-void CreateInfoWrapper::UpgradeDeviceCoreApiVersion(uint32_t api_version) {
- ALOG_ASSERT(!is_instance_, "Device only API called by instance wrapper.");
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wold-style-cast"
- api_version ^= VK_VERSION_PATCH(api_version);
-#pragma clang diagnostic pop
-
- // cap the API version to the loader supported highest version
- if (api_version > VK_API_VERSION_1_1)
- api_version = VK_API_VERSION_1_1;
-
- switch (api_version) {
- case VK_API_VERSION_1_1:
- hook_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
- hal_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
- [[clang::fallthrough]];
- case VK_API_VERSION_1_0:
- break;
- default:
- ALOGD("Unknown upgrade API version[%u]", api_version);
- break;
- }
-}
-
VKAPI_ATTR void* DefaultAllocate(void*,
size_t size,
size_t alignment,
@@ -901,21 +935,14 @@
return result;
}
-bool QueryPresentationProperties(
+void QueryPresentationProperties(
VkPhysicalDevice physicalDevice,
- VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties) {
- const InstanceData& data = GetData(physicalDevice);
-
- // GPDP2 must be present and enabled on the instance.
- if (!data.driver.GetPhysicalDeviceProperties2KHR &&
- !data.driver.GetPhysicalDeviceProperties2)
- return false;
-
+ VkPhysicalDevicePresentationPropertiesANDROID* presentation_properties) {
// Request the android-specific presentation properties via GPDP2
- VkPhysicalDeviceProperties2KHR properties = {
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
+ VkPhysicalDeviceProperties2 properties = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
presentation_properties,
- {}
+ {},
};
#pragma clang diagnostic push
@@ -926,14 +953,7 @@
presentation_properties->pNext = nullptr;
presentation_properties->sharedImage = VK_FALSE;
- if (data.driver.GetPhysicalDeviceProperties2KHR) {
- data.driver.GetPhysicalDeviceProperties2KHR(physicalDevice,
- &properties);
- } else {
- data.driver.GetPhysicalDeviceProperties2(physicalDevice, &properties);
- }
-
- return true;
+ GetPhysicalDeviceProperties2(physicalDevice, &properties);
}
VkResult EnumerateDeviceExtensionProperties(
@@ -955,8 +975,8 @@
}
VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
- if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
- presentation_properties.sharedImage) {
+ QueryPresentationProperties(physicalDevice, &presentation_properties);
+ if (presentation_properties.sharedImage) {
loader_extensions.push_back({
VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
@@ -1027,49 +1047,32 @@
const VkAllocationCallbacks& data_allocator =
(pAllocator) ? *pAllocator : GetDefaultAllocator();
- CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
- VkResult result = wrapper.Validate();
- if (result != VK_SUCCESS)
- return result;
-
- ATRACE_BEGIN("AllocateInstanceData");
- InstanceData* data = AllocateInstanceData(data_allocator);
- ATRACE_END();
- if (!data)
- return VK_ERROR_OUT_OF_HOST_MEMORY;
-
- data->hook_extensions |= wrapper.GetHookExtensions();
-
- ATRACE_BEGIN("autoDowngradeApiVersion");
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wold-style-cast"
- uint32_t api_version = ((pCreateInfo->pApplicationInfo)
- ? pCreateInfo->pApplicationInfo->apiVersion
- : VK_API_VERSION_1_0);
- uint32_t api_major_version = VK_VERSION_MAJOR(api_version);
- uint32_t api_minor_version = VK_VERSION_MINOR(api_version);
- uint32_t icd_api_version;
+ VkResult result = VK_SUCCESS;
+ uint32_t icd_api_version = VK_API_VERSION_1_0;
PFN_vkEnumerateInstanceVersion pfn_enumerate_instance_version =
reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
Hal::Device().GetInstanceProcAddr(nullptr,
"vkEnumerateInstanceVersion"));
- if (!pfn_enumerate_instance_version) {
- icd_api_version = VK_API_VERSION_1_0;
- } else {
+ if (pfn_enumerate_instance_version) {
ATRACE_BEGIN("pfn_enumerate_instance_version");
result = (*pfn_enumerate_instance_version)(&icd_api_version);
ATRACE_END();
- }
- uint32_t icd_api_major_version = VK_VERSION_MAJOR(icd_api_version);
- uint32_t icd_api_minor_version = VK_VERSION_MINOR(icd_api_version);
+ if (result != VK_SUCCESS)
+ return result;
- if ((icd_api_major_version == 1) && (icd_api_minor_version == 0) &&
- ((api_major_version > 1) || (api_minor_version > 0))) {
- api_version = VK_API_VERSION_1_0;
- wrapper.DowngradeApiVersion();
+ icd_api_version ^= VK_VERSION_PATCH(icd_api_version);
}
-#pragma clang diagnostic pop
- ATRACE_END();
+
+ CreateInfoWrapper wrapper(*pCreateInfo, icd_api_version, data_allocator);
+ result = wrapper.Validate();
+ if (result != VK_SUCCESS)
+ return result;
+
+ InstanceData* data = AllocateInstanceData(data_allocator);
+ if (!data)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ data->hook_extensions |= wrapper.GetHookExtensions();
// call into the driver
VkInstance instance;
@@ -1133,7 +1136,16 @@
const VkAllocationCallbacks& data_allocator =
(pAllocator) ? *pAllocator : instance_data.allocator;
- CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
+ VkPhysicalDeviceProperties properties;
+ ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
+ instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
+ &properties);
+ ATRACE_END();
+
+ CreateInfoWrapper wrapper(
+ physicalDevice, *pCreateInfo,
+ properties.apiVersion ^ VK_VERSION_PATCH(properties.apiVersion),
+ data_allocator);
VkResult result = wrapper.Validate();
if (result != VK_SUCCESS)
return result;
@@ -1145,13 +1157,6 @@
if (!data)
return VK_ERROR_OUT_OF_HOST_MEMORY;
- VkPhysicalDeviceProperties properties;
- ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
- instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
- &properties);
- ATRACE_END();
-
- wrapper.UpgradeDeviceCoreApiVersion(properties.apiVersion);
data->hook_extensions |= wrapper.GetHookExtensions();
// call into the driver
@@ -1248,7 +1253,8 @@
VkResult result = VK_SUCCESS;
const auto& data = GetData(instance);
- if (!data.driver.EnumeratePhysicalDeviceGroups) {
+ if (!data.driver.EnumeratePhysicalDeviceGroups &&
+ !data.driver.EnumeratePhysicalDeviceGroupsKHR) {
uint32_t device_count = 0;
result = EnumeratePhysicalDevices(instance, &device_count, nullptr);
if (result < 0)
@@ -1280,9 +1286,15 @@
pPhysicalDeviceGroupProperties[i].subsetAllocation = 0;
}
} else {
- result = data.driver.EnumeratePhysicalDeviceGroups(
- instance, pPhysicalDeviceGroupCount,
- pPhysicalDeviceGroupProperties);
+ if (data.driver.EnumeratePhysicalDeviceGroups) {
+ result = data.driver.EnumeratePhysicalDeviceGroups(
+ instance, pPhysicalDeviceGroupCount,
+ pPhysicalDeviceGroupProperties);
+ } else {
+ result = data.driver.EnumeratePhysicalDeviceGroupsKHR(
+ instance, pPhysicalDeviceGroupCount,
+ pPhysicalDeviceGroupProperties);
+ }
if ((result == VK_SUCCESS || result == VK_INCOMPLETE) &&
*pPhysicalDeviceGroupCount && pPhysicalDeviceGroupProperties) {
for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) {
@@ -1323,10 +1335,10 @@
if (*pQueue != VK_NULL_HANDLE) SetData(*pQueue, data);
}
-VKAPI_ATTR VkResult
-AllocateCommandBuffers(VkDevice device,
- const VkCommandBufferAllocateInfo* pAllocateInfo,
- VkCommandBuffer* pCommandBuffers) {
+VkResult AllocateCommandBuffers(
+ VkDevice device,
+ const VkCommandBufferAllocateInfo* pAllocateInfo,
+ VkCommandBuffer* pCommandBuffers) {
ATRACE_CALL();
const auto& data = GetData(device);
@@ -1341,10 +1353,10 @@
return result;
}
-VKAPI_ATTR VkResult QueueSubmit(VkQueue queue,
- uint32_t submitCount,
- const VkSubmitInfo* pSubmits,
- VkFence fence) {
+VkResult QueueSubmit(VkQueue queue,
+ uint32_t submitCount,
+ const VkSubmitInfo* pSubmits,
+ VkFence fence) {
ATRACE_CALL();
const auto& data = GetData(queue);
@@ -1352,5 +1364,198 @@
return data.driver.QueueSubmit(queue, submitCount, pSubmits, fence);
}
+void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures2* pFeatures) {
+ ATRACE_CALL();
+
+ const auto& driver = GetData(physicalDevice).driver;
+
+ if (driver.GetPhysicalDeviceFeatures2) {
+ driver.GetPhysicalDeviceFeatures2(physicalDevice, pFeatures);
+ return;
+ }
+
+ driver.GetPhysicalDeviceFeatures2KHR(physicalDevice, pFeatures);
+}
+
+void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2* pProperties) {
+ ATRACE_CALL();
+
+ const auto& driver = GetData(physicalDevice).driver;
+
+ if (driver.GetPhysicalDeviceProperties2) {
+ driver.GetPhysicalDeviceProperties2(physicalDevice, pProperties);
+ return;
+ }
+
+ driver.GetPhysicalDeviceProperties2KHR(physicalDevice, pProperties);
+}
+
+void GetPhysicalDeviceFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties2* pFormatProperties) {
+ ATRACE_CALL();
+
+ const auto& driver = GetData(physicalDevice).driver;
+
+ if (driver.GetPhysicalDeviceFormatProperties2) {
+ driver.GetPhysicalDeviceFormatProperties2(physicalDevice, format,
+ pFormatProperties);
+ return;
+ }
+
+ driver.GetPhysicalDeviceFormatProperties2KHR(physicalDevice, format,
+ pFormatProperties);
+}
+
+VkResult GetPhysicalDeviceImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
+ VkImageFormatProperties2* pImageFormatProperties) {
+ ATRACE_CALL();
+
+ const auto& driver = GetData(physicalDevice).driver;
+
+ if (driver.GetPhysicalDeviceImageFormatProperties2) {
+ return driver.GetPhysicalDeviceImageFormatProperties2(
+ physicalDevice, pImageFormatInfo, pImageFormatProperties);
+ }
+
+ return driver.GetPhysicalDeviceImageFormatProperties2KHR(
+ physicalDevice, pImageFormatInfo, pImageFormatProperties);
+}
+
+void GetPhysicalDeviceQueueFamilyProperties2(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2* pQueueFamilyProperties) {
+ ATRACE_CALL();
+
+ const auto& driver = GetData(physicalDevice).driver;
+
+ if (driver.GetPhysicalDeviceQueueFamilyProperties2) {
+ driver.GetPhysicalDeviceQueueFamilyProperties2(
+ physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+ return;
+ }
+
+ driver.GetPhysicalDeviceQueueFamilyProperties2KHR(
+ physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+void GetPhysicalDeviceMemoryProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+ ATRACE_CALL();
+
+ const auto& driver = GetData(physicalDevice).driver;
+
+ if (driver.GetPhysicalDeviceMemoryProperties2) {
+ driver.GetPhysicalDeviceMemoryProperties2(physicalDevice,
+ pMemoryProperties);
+ return;
+ }
+
+ driver.GetPhysicalDeviceMemoryProperties2KHR(physicalDevice,
+ pMemoryProperties);
+}
+
+void GetPhysicalDeviceSparseImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
+ uint32_t* pPropertyCount,
+ VkSparseImageFormatProperties2* pProperties) {
+ ATRACE_CALL();
+
+ const auto& driver = GetData(physicalDevice).driver;
+
+ if (driver.GetPhysicalDeviceSparseImageFormatProperties2) {
+ driver.GetPhysicalDeviceSparseImageFormatProperties2(
+ physicalDevice, pFormatInfo, pPropertyCount, pProperties);
+ return;
+ }
+
+ driver.GetPhysicalDeviceSparseImageFormatProperties2KHR(
+ physicalDevice, pFormatInfo, pPropertyCount, pProperties);
+}
+
+void GetPhysicalDeviceExternalBufferProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties) {
+ ATRACE_CALL();
+
+ const auto& driver = GetData(physicalDevice).driver;
+
+ if (driver.GetPhysicalDeviceExternalBufferProperties) {
+ driver.GetPhysicalDeviceExternalBufferProperties(
+ physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+ return;
+ }
+
+ if (driver.GetPhysicalDeviceExternalBufferPropertiesKHR) {
+ driver.GetPhysicalDeviceExternalBufferPropertiesKHR(
+ physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+ return;
+ }
+
+ memset(&pExternalBufferProperties->externalMemoryProperties, 0,
+ sizeof(VkExternalMemoryProperties));
+}
+
+void GetPhysicalDeviceExternalSemaphoreProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+ VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+ ATRACE_CALL();
+
+ const auto& driver = GetData(physicalDevice).driver;
+
+ if (driver.GetPhysicalDeviceExternalSemaphoreProperties) {
+ driver.GetPhysicalDeviceExternalSemaphoreProperties(
+ physicalDevice, pExternalSemaphoreInfo,
+ pExternalSemaphoreProperties);
+ return;
+ }
+
+ if (driver.GetPhysicalDeviceExternalSemaphorePropertiesKHR) {
+ driver.GetPhysicalDeviceExternalSemaphorePropertiesKHR(
+ physicalDevice, pExternalSemaphoreInfo,
+ pExternalSemaphoreProperties);
+ return;
+ }
+
+ pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
+ pExternalSemaphoreProperties->compatibleHandleTypes = 0;
+ pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
+}
+
+void GetPhysicalDeviceExternalFenceProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
+ VkExternalFenceProperties* pExternalFenceProperties) {
+ ATRACE_CALL();
+
+ const auto& driver = GetData(physicalDevice).driver;
+
+ if (driver.GetPhysicalDeviceExternalFenceProperties) {
+ driver.GetPhysicalDeviceExternalFenceProperties(
+ physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+ return;
+ }
+
+ if (driver.GetPhysicalDeviceExternalFencePropertiesKHR) {
+ driver.GetPhysicalDeviceExternalFencePropertiesKHR(
+ physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+ return;
+ }
+
+ pExternalFenceProperties->exportFromImportedHandleTypes = 0;
+ pExternalFenceProperties->compatibleHandleTypes = 0;
+ pExternalFenceProperties->externalFenceFeatures = 0;
+}
+
} // namespace driver
} // namespace vulkan
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index 23c717c..14c516b 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -103,30 +103,95 @@
bool OpenHAL();
const VkAllocationCallbacks& GetDefaultAllocator();
-bool QueryPresentationProperties(
+void QueryPresentationProperties(
VkPhysicalDevice physicalDevice,
- VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties);
+ VkPhysicalDevicePresentationPropertiesANDROID* presentation_properties);
-// clang-format off
-VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName);
-VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName);
-VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
-
-VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
-
-VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
-VKAPI_ATTR void DestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
-VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
-
-VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
-VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
-
-VKAPI_ATTR void GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
-VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
-VKAPI_ATTR VkResult AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
-VKAPI_ATTR VkResult QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence);
-// clang-format on
+VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
+ const char* pName);
+VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device,
+ const char* pName);
+VKAPI_ATTR VkResult
+EnumerateInstanceExtensionProperties(const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult
+EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkInstance* pInstance);
+VKAPI_ATTR void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice);
+VKAPI_ATTR void DestroyDevice(VkDevice device,
+ const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult
+EnumeratePhysicalDevices(VkInstance instance,
+ uint32_t* pPhysicalDeviceCount,
+ VkPhysicalDevice* pPhysicalDevices);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+VKAPI_ATTR void GetDeviceQueue(VkDevice device,
+ uint32_t queueFamilyIndex,
+ uint32_t queueIndex,
+ VkQueue* pQueue);
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device,
+ const VkDeviceQueueInfo2* pQueueInfo,
+ VkQueue* pQueue);
+VKAPI_ATTR VkResult
+AllocateCommandBuffers(VkDevice device,
+ const VkCommandBufferAllocateInfo* pAllocateInfo,
+ VkCommandBuffer* pCommandBuffers);
+VKAPI_ATTR VkResult QueueSubmit(VkQueue queue,
+ uint32_t submitCount,
+ const VkSubmitInfo* pSubmits,
+ VkFence fence);
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
+ VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
+ uint32_t* pPropertyCount,
+ VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+ VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
+ VkExternalFenceProperties* pExternalFenceProperties);
template <typename DispatchableType>
void StaticAssertDispatchable(DispatchableType) {
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 52205e9..5f37a50 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -363,6 +363,55 @@
reinterpret_cast<PFN_vkVoidFunction>(checkedGetPastPresentationTimingGOOGLE),
},
{
+ "vkGetPhysicalDeviceExternalBufferProperties",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE_1_1,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceExternalBufferProperties),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceExternalFenceProperties",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE_1_1,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceExternalFenceProperties),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceExternalSemaphoreProperties",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE_1_1,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceExternalSemaphoreProperties),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceFeatures2",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE_1_1,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceFeatures2),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceFormatProperties2",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE_1_1,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceFormatProperties2),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceImageFormatProperties2",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE_1_1,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceImageFormatProperties2),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceMemoryProperties2",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE_1_1,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMemoryProperties2),
+ nullptr,
+ },
+ {
"vkGetPhysicalDevicePresentRectanglesKHR",
ProcHook::INSTANCE,
ProcHook::KHR_swapchain,
@@ -370,6 +419,27 @@
nullptr,
},
{
+ "vkGetPhysicalDeviceProperties2",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE_1_1,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProperties2),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceQueueFamilyProperties2",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE_1_1,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties2),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceSparseImageFormatProperties2",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE_1_1,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSparseImageFormatProperties2),
+ nullptr,
+ },
+ {
"vkGetPhysicalDeviceSurfaceCapabilities2KHR",
ProcHook::INSTANCE,
ProcHook::KHR_get_surface_capabilities2,
@@ -480,10 +550,9 @@
} // namespace
const ProcHook* GetProcHook(const char* name) {
- const auto& begin = g_proc_hooks;
- const auto& end =
- g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
- const auto hook = std::lower_bound(
+ auto begin = std::cbegin(g_proc_hooks);
+ auto end = std::cend(g_proc_hooks);
+ auto hook = std::lower_bound(
begin, end, name,
[](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
@@ -505,6 +574,10 @@
if (strcmp(name, "VK_ANDROID_external_memory_android_hardware_buffer") == 0) return ProcHook::ANDROID_external_memory_android_hardware_buffer;
if (strcmp(name, "VK_KHR_bind_memory2") == 0) return ProcHook::KHR_bind_memory2;
if (strcmp(name, "VK_KHR_get_physical_device_properties2") == 0) return ProcHook::KHR_get_physical_device_properties2;
+ if (strcmp(name, "VK_KHR_device_group_creation") == 0) return ProcHook::KHR_device_group_creation;
+ if (strcmp(name, "VK_KHR_external_memory_capabilities") == 0) return ProcHook::KHR_external_memory_capabilities;
+ if (strcmp(name, "VK_KHR_external_semaphore_capabilities") == 0) return ProcHook::KHR_external_semaphore_capabilities;
+ if (strcmp(name, "VK_KHR_external_fence_capabilities") == 0) return ProcHook::KHR_external_fence_capabilities;
// clang-format on
return ProcHook::EXTENSION_UNKNOWN;
}
@@ -543,9 +616,28 @@
INIT_PROC_EXT(EXT_debug_report, true, instance, CreateDebugReportCallbackEXT);
INIT_PROC_EXT(EXT_debug_report, true, instance, DestroyDebugReportCallbackEXT);
INIT_PROC_EXT(EXT_debug_report, true, instance, DebugReportMessageEXT);
+ INIT_PROC(false, instance, GetPhysicalDeviceFeatures2);
+ INIT_PROC_EXT(KHR_get_physical_device_properties2, true, instance, GetPhysicalDeviceFeatures2KHR);
INIT_PROC(false, instance, GetPhysicalDeviceProperties2);
INIT_PROC_EXT(KHR_get_physical_device_properties2, true, instance, GetPhysicalDeviceProperties2KHR);
+ INIT_PROC(false, instance, GetPhysicalDeviceFormatProperties2);
+ INIT_PROC_EXT(KHR_get_physical_device_properties2, true, instance, GetPhysicalDeviceFormatProperties2KHR);
+ INIT_PROC(false, instance, GetPhysicalDeviceImageFormatProperties2);
+ INIT_PROC_EXT(KHR_get_physical_device_properties2, true, instance, GetPhysicalDeviceImageFormatProperties2KHR);
+ INIT_PROC(false, instance, GetPhysicalDeviceQueueFamilyProperties2);
+ INIT_PROC_EXT(KHR_get_physical_device_properties2, true, instance, GetPhysicalDeviceQueueFamilyProperties2KHR);
+ INIT_PROC(false, instance, GetPhysicalDeviceMemoryProperties2);
+ INIT_PROC_EXT(KHR_get_physical_device_properties2, true, instance, GetPhysicalDeviceMemoryProperties2KHR);
+ INIT_PROC(false, instance, GetPhysicalDeviceSparseImageFormatProperties2);
+ INIT_PROC_EXT(KHR_get_physical_device_properties2, true, instance, GetPhysicalDeviceSparseImageFormatProperties2KHR);
+ INIT_PROC(false, instance, GetPhysicalDeviceExternalBufferProperties);
+ INIT_PROC_EXT(KHR_external_memory_capabilities, true, instance, GetPhysicalDeviceExternalBufferPropertiesKHR);
+ INIT_PROC(false, instance, GetPhysicalDeviceExternalSemaphoreProperties);
+ INIT_PROC_EXT(KHR_external_semaphore_capabilities, true, instance, GetPhysicalDeviceExternalSemaphorePropertiesKHR);
+ INIT_PROC(false, instance, GetPhysicalDeviceExternalFenceProperties);
+ INIT_PROC_EXT(KHR_external_fence_capabilities, true, instance, GetPhysicalDeviceExternalFencePropertiesKHR);
INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
+ INIT_PROC_EXT(KHR_device_group_creation, true, instance, EnumeratePhysicalDeviceGroupsKHR);
// clang-format on
return success;
@@ -577,5 +669,53 @@
return success;
}
+const std::pair<const char*, uint32_t> g_promoted_instance_extensions[] = {
+ // clang-format off
+ std::make_pair("VK_KHR_device_group_creation", VK_API_VERSION_1_1),
+ std::make_pair("VK_KHR_external_fence_capabilities", VK_API_VERSION_1_1),
+ std::make_pair("VK_KHR_external_memory_capabilities", VK_API_VERSION_1_1),
+ std::make_pair("VK_KHR_external_semaphore_capabilities", VK_API_VERSION_1_1),
+ std::make_pair("VK_KHR_get_physical_device_properties2", VK_API_VERSION_1_1),
+ // clang-format on
+};
+
+std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name) {
+ auto begin = std::cbegin(g_promoted_instance_extensions);
+ auto end = std::cend(g_promoted_instance_extensions);
+ auto iter =
+ std::lower_bound(begin, end, name,
+ [](const std::pair<const char*, uint32_t>& e,
+ const char* n) { return strcmp(e.first, n) < 0; });
+ return (iter < end && strcmp(iter->first, name) == 0)
+ ? std::optional<uint32_t>(iter->second)
+ : std::nullopt;
+}
+
+uint32_t CountPromotedInstanceExtensions(uint32_t begin_version,
+ uint32_t end_version) {
+ auto begin = std::cbegin(g_promoted_instance_extensions);
+ auto end = std::cend(g_promoted_instance_extensions);
+ uint32_t count = 0;
+
+ for (auto iter = begin; iter != end; iter++)
+ if (iter->second > begin_version && iter->second <= end_version)
+ count++;
+
+ return count;
+}
+
+std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version,
+ uint32_t end_version) {
+ auto begin = std::cbegin(g_promoted_instance_extensions);
+ auto end = std::cend(g_promoted_instance_extensions);
+ std::vector<const char*> extensions;
+
+ for (auto iter = begin; iter != end; iter++)
+ if (iter->second > begin_version && iter->second <= end_version)
+ extensions.emplace_back(iter->first);
+
+ return extensions;
+}
+
} // namespace driver
} // namespace vulkan
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 43c4d14..1aba674 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -23,6 +23,8 @@
#include <vulkan/vulkan.h>
#include <bitset>
+#include <optional>
+#include <vector>
namespace vulkan {
namespace driver {
@@ -48,6 +50,10 @@
ANDROID_external_memory_android_hardware_buffer,
KHR_bind_memory2,
KHR_get_physical_device_properties2,
+ KHR_device_group_creation,
+ KHR_external_memory_capabilities,
+ KHR_external_semaphore_capabilities,
+ KHR_external_fence_capabilities,
EXTENSION_CORE_1_0,
EXTENSION_CORE_1_1,
@@ -74,9 +80,28 @@
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+ PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
+ PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysicalDeviceFeatures2KHR;
PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
PFN_vkGetPhysicalDeviceProperties2KHR GetPhysicalDeviceProperties2KHR;
+ PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2;
+ PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysicalDeviceFormatProperties2KHR;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysicalDeviceImageFormatProperties2;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysicalDeviceImageFormatProperties2KHR;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysicalDeviceQueueFamilyProperties2;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysicalDeviceQueueFamilyProperties2KHR;
+ PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysicalDeviceMemoryProperties2;
+ PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysicalDeviceMemoryProperties2KHR;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysicalDeviceSparseImageFormatProperties2;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysicalDeviceSparseImageFormatProperties2KHR;
+ PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties;
+ PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR;
+ PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties;
+ PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR GetPhysicalDeviceExternalSemaphorePropertiesKHR;
+ PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties;
+ PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR GetPhysicalDeviceExternalFencePropertiesKHR;
PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
+ PFN_vkEnumeratePhysicalDeviceGroupsKHR EnumeratePhysicalDeviceGroupsKHR;
// clang-format on
};
@@ -109,6 +134,12 @@
PFN_vkGetDeviceProcAddr get_proc,
const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
+std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name);
+uint32_t CountPromotedInstanceExtensions(uint32_t begin_version,
+ uint32_t end_version);
+std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version,
+ uint32_t end_version);
+
} // namespace driver
} // namespace vulkan
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index c7ff640..0f791c9 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -881,11 +881,10 @@
present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
VkPhysicalDevicePresentationPropertiesANDROID present_properties;
- if (QueryPresentationProperties(pdev, &present_properties)) {
- if (present_properties.sharedImage) {
- present_modes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR);
- present_modes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
- }
+ QueryPresentationProperties(pdev, &present_properties);
+ if (present_properties.sharedImage) {
+ present_modes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR);
+ present_modes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
}
uint32_t num_modes = uint32_t(present_modes.size());
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
index a64a702..6a73023 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -40,6 +40,10 @@
'VK_ANDROID_external_memory_android_hardware_buffer',
'VK_KHR_bind_memory2',
'VK_KHR_get_physical_device_properties2',
+ 'VK_KHR_device_group_creation',
+ 'VK_KHR_external_memory_capabilities',
+ 'VK_KHR_external_semaphore_capabilities',
+ 'VK_KHR_external_fence_capabilities',
]
# Functions needed at vulkan::driver level.
@@ -71,12 +75,41 @@
'vkDestroyImage',
'vkGetPhysicalDeviceProperties',
- 'vkGetPhysicalDeviceProperties2',
- 'vkGetPhysicalDeviceProperties2KHR',
# VK_KHR_swapchain v69 requirement
'vkBindImageMemory2',
'vkBindImageMemory2KHR',
+
+ # For promoted VK_KHR_device_group_creation
+ 'vkEnumeratePhysicalDeviceGroupsKHR',
+
+ # For promoted VK_KHR_get_physical_device_properties2
+ 'vkGetPhysicalDeviceFeatures2',
+ 'vkGetPhysicalDeviceFeatures2KHR',
+ 'vkGetPhysicalDeviceProperties2',
+ 'vkGetPhysicalDeviceProperties2KHR',
+ 'vkGetPhysicalDeviceFormatProperties2',
+ 'vkGetPhysicalDeviceFormatProperties2KHR',
+ 'vkGetPhysicalDeviceImageFormatProperties2',
+ 'vkGetPhysicalDeviceImageFormatProperties2KHR',
+ 'vkGetPhysicalDeviceQueueFamilyProperties2',
+ 'vkGetPhysicalDeviceQueueFamilyProperties2KHR',
+ 'vkGetPhysicalDeviceMemoryProperties2',
+ 'vkGetPhysicalDeviceMemoryProperties2KHR',
+ 'vkGetPhysicalDeviceSparseImageFormatProperties2',
+ 'vkGetPhysicalDeviceSparseImageFormatProperties2KHR',
+
+ # For promoted VK_KHR_external_memory_capabilities
+ 'vkGetPhysicalDeviceExternalBufferProperties',
+ 'vkGetPhysicalDeviceExternalBufferPropertiesKHR',
+
+ # For promoted VK_KHR_external_semaphore_capabilities
+ 'vkGetPhysicalDeviceExternalSemaphoreProperties',
+ 'vkGetPhysicalDeviceExternalSemaphorePropertiesKHR',
+
+ # For promoted VK_KHR_external_fence_capabilities
+ 'vkGetPhysicalDeviceExternalFenceProperties',
+ 'vkGetPhysicalDeviceExternalFencePropertiesKHR',
]
# Functions intercepted at vulkan::driver level.
@@ -106,6 +139,24 @@
# VK_KHR_swapchain v69 requirement
'vkBindImageMemory2',
'vkBindImageMemory2KHR',
+
+ # For promoted VK_KHR_get_physical_device_properties2
+ 'vkGetPhysicalDeviceFeatures2',
+ 'vkGetPhysicalDeviceProperties2',
+ 'vkGetPhysicalDeviceFormatProperties2',
+ 'vkGetPhysicalDeviceImageFormatProperties2',
+ 'vkGetPhysicalDeviceQueueFamilyProperties2',
+ 'vkGetPhysicalDeviceMemoryProperties2',
+ 'vkGetPhysicalDeviceSparseImageFormatProperties2',
+
+ # For promoted VK_KHR_external_memory_capabilities
+ 'vkGetPhysicalDeviceExternalBufferProperties',
+
+ # For promoted VK_KHR_external_semaphore_capabilities
+ 'vkGetPhysicalDeviceExternalSemaphoreProperties',
+
+ # For promoted VK_KHR_external_fence_capabilities
+ 'vkGetPhysicalDeviceExternalFenceProperties',
]
@@ -162,6 +213,8 @@
#include <vulkan/vulkan.h>
#include <bitset>
+#include <optional>
+#include <vector>
namespace vulkan {
namespace driver {
@@ -229,6 +282,12 @@
PFN_vkGetDeviceProcAddr get_proc,
const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
+std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name);
+uint32_t CountPromotedInstanceExtensions(uint32_t begin_version,
+ uint32_t end_version);
+std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version,
+ uint32_t end_version);
+
} // namespace driver
} // namespace vulkan
@@ -464,10 +523,9 @@
} // namespace
const ProcHook* GetProcHook(const char* name) {
- const auto& begin = g_proc_hooks;
- const auto& end =
- g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
- const auto hook = std::lower_bound(
+ auto begin = std::cbegin(g_proc_hooks);
+ auto end = std::cend(g_proc_hooks);
+ auto hook = std::lower_bound(
begin, end, name,
[](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
@@ -539,6 +597,54 @@
return success;
}
+const std::pair<const char*, uint32_t> g_promoted_instance_extensions[] = {
+ // clang-format off\n""")
+
+ for key, value in sorted(gencom.promoted_inst_ext_dict.items()):
+ f.write(gencom.indent(1) + 'std::make_pair("' + key + '", ' + value + '),\n')
+
+ f.write("""\
+ // clang-format on
+};
+
+std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name) {
+ auto begin = std::cbegin(g_promoted_instance_extensions);
+ auto end = std::cend(g_promoted_instance_extensions);
+ auto iter =
+ std::lower_bound(begin, end, name,
+ [](const std::pair<const char*, uint32_t>& e,
+ const char* n) { return strcmp(e.first, n) < 0; });
+ return (iter < end && strcmp(iter->first, name) == 0)
+ ? std::optional<uint32_t>(iter->second)
+ : std::nullopt;
+}
+
+uint32_t CountPromotedInstanceExtensions(uint32_t begin_version,
+ uint32_t end_version) {
+ auto begin = std::cbegin(g_promoted_instance_extensions);
+ auto end = std::cend(g_promoted_instance_extensions);
+ uint32_t count = 0;
+
+ for (auto iter = begin; iter != end; iter++)
+ if (iter->second > begin_version && iter->second <= end_version)
+ count++;
+
+ return count;
+}
+
+std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version,
+ uint32_t end_version) {
+ auto begin = std::cbegin(g_promoted_instance_extensions);
+ auto end = std::cend(g_promoted_instance_extensions);
+ std::vector<const char*> extensions;
+
+ for (auto iter = begin; iter != end; iter++)
+ if (iter->second > begin_version && iter->second <= end_version)
+ extensions.emplace_back(iter->first);
+
+ return extensions;
+}
+
} // namespace driver
} // namespace vulkan\n""")
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
index ef0719d..ef021f2 100644
--- a/vulkan/scripts/generator_common.py
+++ b/vulkan/scripts/generator_common.py
@@ -97,6 +97,9 @@
# Dict for mapping a function to the core Vulkan API version.
version_dict = {}
+# Dict for mapping a promoted instance extension to the core Vulkan API version.
+promoted_inst_ext_dict = {}
+
def indent(num):
"""Returns the requested indents.
@@ -183,6 +186,15 @@
return version[11:]
+def version_2_api_version(version):
+ """Returns the api version from a version string.
+
+ Args:
+ version: Vulkan version string.
+ """
+ return 'VK_API' + version[2:]
+
+
def is_function_supported(cmd):
"""Returns true if a function is core or from a supportable extension.
@@ -327,6 +339,7 @@
return_type_dict
version_code_list
version_dict
+ promoted_inst_ext_dict
"""
registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
'external', 'vulkan-headers', 'registry', 'vk.xml')
@@ -379,6 +392,10 @@
apiversion = ''
if extension.tag == 'extension':
extname = extension.get('name')
+ if (extension.get('type') == 'instance' and
+ extension.get('promotedto') is not None):
+ promoted_inst_ext_dict[extname] = \
+ version_2_api_version(extension.get('promotedto'))
for req in extension:
if req.get('feature') is not None:
apiversion = req.get('feature')
diff --git a/vulkan/vkjson/vkjson.h b/vulkan/vkjson/vkjson.h
index a283b83..52e7bee 100644
--- a/vulkan/vkjson/vkjson.h
+++ b/vulkan/vkjson/vkjson.h
@@ -158,10 +158,7 @@
VkJsonInstance* instance,
std::string* errors);
-VkJsonDevice VkJsonGetDevice(VkInstance instance,
- VkPhysicalDevice device,
- uint32_t instanceExtensionCount,
- const char* const* instanceExtensions);
+VkJsonDevice VkJsonGetDevice(VkPhysicalDevice device);
std::string VkJsonDeviceToJson(const VkJsonDevice& device);
bool VkJsonDeviceFromJson(const std::string& json,
VkJsonDevice* device,
@@ -177,7 +174,7 @@
typedef VkJsonDevice VkJsonAllProperties;
inline VkJsonAllProperties VkJsonGetAllProperties(
VkPhysicalDevice physicalDevice) {
- return VkJsonGetDevice(VK_NULL_HANDLE, physicalDevice, 0, nullptr);
+ return VkJsonGetDevice(physicalDevice);
}
inline std::string VkJsonAllPropertiesToJson(
const VkJsonAllProperties& properties) {
diff --git a/vulkan/vkjson/vkjson_instance.cc b/vulkan/vkjson/vkjson_instance.cc
index 84cfe5e..ace713b 100644
--- a/vulkan/vkjson/vkjson_instance.cc
+++ b/vulkan/vkjson/vkjson_instance.cc
@@ -28,8 +28,6 @@
#include <utility>
namespace {
-const char* kSupportedInstanceExtensions[] = {
- "VK_KHR_get_physical_device_properties2"};
bool EnumerateExtensions(const char* layer_name,
std::vector<VkExtensionProperties>* extensions) {
@@ -47,15 +45,6 @@
}
bool HasExtension(const char* extension_name,
- uint32_t count,
- const char* const* extensions) {
- return std::find_if(extensions, extensions + count,
- [extension_name](const char* extension) {
- return strcmp(extension, extension_name) == 0;
- }) != extensions + count;
-}
-
-bool HasExtension(const char* extension_name,
const std::vector<VkExtensionProperties>& extensions) {
return std::find_if(extensions.cbegin(), extensions.cend(),
[extension_name](const VkExtensionProperties& extension) {
@@ -65,27 +54,9 @@
}
} // anonymous namespace
-VkJsonDevice VkJsonGetDevice(VkInstance instance,
- VkPhysicalDevice physical_device,
- uint32_t instance_extension_count,
- const char* const* instance_extensions) {
+VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) {
VkJsonDevice device;
- PFN_vkGetPhysicalDeviceProperties2KHR vkpGetPhysicalDeviceProperties2KHR =
- nullptr;
- PFN_vkGetPhysicalDeviceFeatures2KHR vkpGetPhysicalDeviceFeatures2KHR =
- nullptr;
- if (instance != VK_NULL_HANDLE &&
- HasExtension("VK_KHR_get_physical_device_properties2",
- instance_extension_count, instance_extensions)) {
- vkpGetPhysicalDeviceProperties2KHR =
- reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2KHR>(
- vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR"));
- vkpGetPhysicalDeviceFeatures2KHR =
- reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>(
- vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR"));
- }
-
uint32_t extension_count = 0;
vkEnumerateDeviceExtensionProperties(physical_device, nullptr,
&extension_count, nullptr);
@@ -103,55 +74,48 @@
device.layers.data());
}
- if (HasExtension("VK_KHR_get_physical_device_properties2",
- instance_extension_count, instance_extensions)) {
- VkPhysicalDeviceProperties2KHR properties = {
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
- nullptr,
- {} // properties
- };
- if (HasExtension("VK_KHR_driver_properties", device.extensions)) {
- device.ext_driver_properties.reported = true;
- device.ext_driver_properties.driver_properties_khr.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
- device.ext_driver_properties.driver_properties_khr.pNext =
- properties.pNext;
- properties.pNext =
- &device.ext_driver_properties.driver_properties_khr;
- }
- vkpGetPhysicalDeviceProperties2KHR(physical_device, &properties);
- device.properties = properties.properties;
-
- VkPhysicalDeviceFeatures2KHR features = {
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR,
- nullptr,
- {} // features
- };
- if (HasExtension("VK_KHR_variable_pointers", device.extensions)) {
- device.ext_variable_pointer_features.reported = true;
- device.ext_variable_pointer_features.variable_pointer_features_khr.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR;
- device.ext_variable_pointer_features.variable_pointer_features_khr.pNext =
- features.pNext;
- features.pNext =
- &device.ext_variable_pointer_features.variable_pointer_features_khr;
- }
- if (HasExtension("VK_KHR_shader_float16_int8", device.extensions)) {
- device.ext_shader_float16_int8_features.reported = true;
- device.ext_shader_float16_int8_features.shader_float16_int8_features_khr
- .sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;
- device.ext_shader_float16_int8_features.shader_float16_int8_features_khr
- .pNext = features.pNext;
- features.pNext = &device.ext_shader_float16_int8_features
- .shader_float16_int8_features_khr;
- }
- vkpGetPhysicalDeviceFeatures2KHR(physical_device, &features);
- device.features = features.features;
- } else {
- vkGetPhysicalDeviceProperties(physical_device, &device.properties);
- vkGetPhysicalDeviceFeatures(physical_device, &device.features);
+ VkPhysicalDeviceProperties2 properties = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
+ nullptr,
+ {},
+ };
+ if (HasExtension("VK_KHR_driver_properties", device.extensions)) {
+ device.ext_driver_properties.reported = true;
+ device.ext_driver_properties.driver_properties_khr.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
+ device.ext_driver_properties.driver_properties_khr.pNext = properties.pNext;
+ properties.pNext = &device.ext_driver_properties.driver_properties_khr;
}
+ vkGetPhysicalDeviceProperties2(physical_device, &properties);
+ device.properties = properties.properties;
+
+ VkPhysicalDeviceFeatures2 features = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
+ nullptr,
+ {},
+ };
+ if (HasExtension("VK_KHR_variable_pointers", device.extensions)) {
+ device.ext_variable_pointer_features.reported = true;
+ device.ext_variable_pointer_features.variable_pointer_features_khr.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR;
+ device.ext_variable_pointer_features.variable_pointer_features_khr.pNext =
+ features.pNext;
+ features.pNext =
+ &device.ext_variable_pointer_features.variable_pointer_features_khr;
+ }
+ if (HasExtension("VK_KHR_shader_float16_int8", device.extensions)) {
+ device.ext_shader_float16_int8_features.reported = true;
+ device.ext_shader_float16_int8_features.shader_float16_int8_features_khr
+ .sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;
+ device.ext_shader_float16_int8_features.shader_float16_int8_features_khr
+ .pNext = features.pNext;
+ features.pNext = &device.ext_shader_float16_int8_features
+ .shader_float16_int8_features_khr;
+ }
+ vkGetPhysicalDeviceFeatures2(physical_device, &features);
+ device.features = features.features;
+
vkGetPhysicalDeviceMemoryProperties(physical_device, &device.memory);
uint32_t queue_family_count = 0;
@@ -189,135 +153,117 @@
}
}
- PFN_vkGetPhysicalDeviceProperties2 vkpGetPhysicalDeviceProperties2 =
- reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2>(
- vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2"));
- if (vkpGetPhysicalDeviceProperties2) {
- VkPhysicalDeviceProperties2 properties2 = {
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, nullptr, {}};
+ VkPhysicalDeviceProperties2 properties2 = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
+ nullptr,
+ {},
+ };
- device.subgroup_properties.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
- device.subgroup_properties.pNext = properties2.pNext;
- properties2.pNext = &device.subgroup_properties;
+ device.subgroup_properties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
+ device.subgroup_properties.pNext = properties2.pNext;
+ properties2.pNext = &device.subgroup_properties;
- device.point_clipping_properties.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES;
- device.point_clipping_properties.pNext = properties2.pNext;
- properties2.pNext = &device.point_clipping_properties;
+ device.point_clipping_properties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES;
+ device.point_clipping_properties.pNext = properties2.pNext;
+ properties2.pNext = &device.point_clipping_properties;
- device.multiview_properties.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
- device.multiview_properties.pNext = properties2.pNext;
- properties2.pNext = &device.multiview_properties;
+ device.multiview_properties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
+ device.multiview_properties.pNext = properties2.pNext;
+ properties2.pNext = &device.multiview_properties;
- device.id_properties.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
- device.id_properties.pNext = properties2.pNext;
- properties2.pNext = &device.id_properties;
+ device.id_properties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
+ device.id_properties.pNext = properties2.pNext;
+ properties2.pNext = &device.id_properties;
- device.maintenance3_properties.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES;
- device.maintenance3_properties.pNext = properties2.pNext;
- properties2.pNext = &device.maintenance3_properties;
+ device.maintenance3_properties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES;
+ device.maintenance3_properties.pNext = properties2.pNext;
+ properties2.pNext = &device.maintenance3_properties;
- (*vkpGetPhysicalDeviceProperties2)(physical_device, &properties2);
- }
+ vkGetPhysicalDeviceProperties2(physical_device, &properties2);
- PFN_vkGetPhysicalDeviceFeatures2 vkpGetPhysicalDeviceFeatures2 =
- reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2>(
- vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2"));
- if (vkpGetPhysicalDeviceFeatures2) {
- VkPhysicalDeviceFeatures2 features2 = {
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, nullptr, {}};
+ VkPhysicalDeviceFeatures2 features2 = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
+ nullptr,
+ {},
+ };
- device.bit16_storage_features.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES;
- device.bit16_storage_features.pNext = features2.pNext;
- features2.pNext = &device.bit16_storage_features;
+ device.bit16_storage_features.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES;
+ device.bit16_storage_features.pNext = features2.pNext;
+ features2.pNext = &device.bit16_storage_features;
- device.multiview_features.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
- device.multiview_features.pNext = features2.pNext;
- features2.pNext = &device.multiview_features;
+ device.multiview_features.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
+ device.multiview_features.pNext = features2.pNext;
+ features2.pNext = &device.multiview_features;
- device.variable_pointer_features.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES;
- device.variable_pointer_features.pNext = features2.pNext;
- features2.pNext = &device.variable_pointer_features;
+ device.variable_pointer_features.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES;
+ device.variable_pointer_features.pNext = features2.pNext;
+ features2.pNext = &device.variable_pointer_features;
- device.protected_memory_features.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
- device.protected_memory_features.pNext = features2.pNext;
- features2.pNext = &device.protected_memory_features;
+ device.protected_memory_features.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
+ device.protected_memory_features.pNext = features2.pNext;
+ features2.pNext = &device.protected_memory_features;
- device.sampler_ycbcr_conversion_features.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
- device.sampler_ycbcr_conversion_features.pNext = features2.pNext;
- features2.pNext = &device.sampler_ycbcr_conversion_features;
+ device.sampler_ycbcr_conversion_features.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
+ device.sampler_ycbcr_conversion_features.pNext = features2.pNext;
+ features2.pNext = &device.sampler_ycbcr_conversion_features;
- device.shader_draw_parameter_features.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES;
- device.shader_draw_parameter_features.pNext = features2.pNext;
- features2.pNext = &device.shader_draw_parameter_features;
+ device.shader_draw_parameter_features.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES;
+ device.shader_draw_parameter_features.pNext = features2.pNext;
+ features2.pNext = &device.shader_draw_parameter_features;
- (*vkpGetPhysicalDeviceFeatures2)(physical_device, &features2);
- }
+ vkGetPhysicalDeviceFeatures2(physical_device, &features2);
- PFN_vkGetPhysicalDeviceExternalFenceProperties
- vkpGetPhysicalDeviceExternalFenceProperties =
- reinterpret_cast<PFN_vkGetPhysicalDeviceExternalFenceProperties>(
- vkGetInstanceProcAddr(
- instance, "vkGetPhysicalDeviceExternalFenceProperties"));
- if (vkpGetPhysicalDeviceExternalFenceProperties) {
- VkPhysicalDeviceExternalFenceInfo external_fence_info = {
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, nullptr,
- VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT};
- VkExternalFenceProperties external_fence_properties = {};
+ VkPhysicalDeviceExternalFenceInfo external_fence_info = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, nullptr,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT};
+ VkExternalFenceProperties external_fence_properties = {};
- for (VkExternalFenceHandleTypeFlagBits handle_type =
- VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
- handle_type <= VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
- handle_type = static_cast<VkExternalFenceHandleTypeFlagBits>(
- handle_type << 1)) {
- external_fence_info.handleType = handle_type;
- (*vkpGetPhysicalDeviceExternalFenceProperties)(
- physical_device, &external_fence_info, &external_fence_properties);
- if (external_fence_properties.exportFromImportedHandleTypes ||
- external_fence_properties.compatibleHandleTypes ||
- external_fence_properties.externalFenceFeatures) {
- device.external_fence_properties.insert(
- std::make_pair(handle_type, external_fence_properties));
- }
+ for (VkExternalFenceHandleTypeFlagBits handle_type =
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
+ handle_type <= VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
+ handle_type =
+ static_cast<VkExternalFenceHandleTypeFlagBits>(handle_type << 1)) {
+ external_fence_info.handleType = handle_type;
+ vkGetPhysicalDeviceExternalFenceProperties(
+ physical_device, &external_fence_info, &external_fence_properties);
+ if (external_fence_properties.exportFromImportedHandleTypes ||
+ external_fence_properties.compatibleHandleTypes ||
+ external_fence_properties.externalFenceFeatures) {
+ device.external_fence_properties.insert(
+ std::make_pair(handle_type, external_fence_properties));
}
}
- PFN_vkGetPhysicalDeviceExternalSemaphoreProperties
- vkpGetPhysicalDeviceExternalSemaphoreProperties = reinterpret_cast<
- PFN_vkGetPhysicalDeviceExternalSemaphoreProperties>(
- vkGetInstanceProcAddr(
- instance, "vkGetPhysicalDeviceExternalSemaphoreProperties"));
- if (vkpGetPhysicalDeviceExternalSemaphoreProperties) {
- VkPhysicalDeviceExternalSemaphoreInfo external_semaphore_info = {
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, nullptr,
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT};
- VkExternalSemaphoreProperties external_semaphore_properties = {};
+ VkPhysicalDeviceExternalSemaphoreInfo external_semaphore_info = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, nullptr,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT};
+ VkExternalSemaphoreProperties external_semaphore_properties = {};
- for (VkExternalSemaphoreHandleTypeFlagBits handle_type =
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
- handle_type <= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- handle_type = static_cast<VkExternalSemaphoreHandleTypeFlagBits>(
- handle_type << 1)) {
- external_semaphore_info.handleType = handle_type;
- (*vkpGetPhysicalDeviceExternalSemaphoreProperties)(
- physical_device, &external_semaphore_info,
- &external_semaphore_properties);
- if (external_semaphore_properties.exportFromImportedHandleTypes ||
- external_semaphore_properties.compatibleHandleTypes ||
- external_semaphore_properties.externalSemaphoreFeatures) {
- device.external_semaphore_properties.insert(
- std::make_pair(handle_type, external_semaphore_properties));
- }
+ for (VkExternalSemaphoreHandleTypeFlagBits handle_type =
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
+ handle_type <= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+ handle_type = static_cast<VkExternalSemaphoreHandleTypeFlagBits>(
+ handle_type << 1)) {
+ external_semaphore_info.handleType = handle_type;
+ vkGetPhysicalDeviceExternalSemaphoreProperties(
+ physical_device, &external_semaphore_info,
+ &external_semaphore_properties);
+ if (external_semaphore_properties.exportFromImportedHandleTypes ||
+ external_semaphore_properties.compatibleHandleTypes ||
+ external_semaphore_properties.externalSemaphoreFeatures) {
+ device.external_semaphore_properties.insert(
+ std::make_pair(handle_type, external_semaphore_properties));
}
}
}
@@ -351,19 +297,15 @@
if (!EnumerateExtensions(nullptr, &instance.extensions))
return VkJsonInstance();
- std::vector<const char*> instance_extensions;
- for (const auto extension : kSupportedInstanceExtensions) {
- if (HasExtension(extension, instance.extensions))
- instance_extensions.push_back(extension);
- }
-
- const VkApplicationInfo app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO,
- nullptr,
- "vkjson_info",
- 1,
- "",
- 0,
- VK_API_VERSION_1_1};
+ const VkApplicationInfo app_info = {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ nullptr,
+ "vkjson_info",
+ 1,
+ "",
+ 0,
+ VK_API_VERSION_1_1,
+ };
VkInstanceCreateInfo instance_info = {
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
nullptr,
@@ -371,8 +313,9 @@
&app_info,
0,
nullptr,
- static_cast<uint32_t>(instance_extensions.size()),
- instance_extensions.data()};
+ 0,
+ nullptr,
+ };
VkInstance vkinstance;
result = vkCreateInstance(&instance_info, nullptr, &vkinstance);
if (result != VK_SUCCESS)
@@ -397,52 +340,38 @@
instance.devices.reserve(sz);
for (uint32_t i = 0; i < sz; ++i) {
device_map.insert(std::make_pair(devices[i], i));
- instance.devices.emplace_back(VkJsonGetDevice(vkinstance, devices[i],
- instance_extensions.size(),
- instance_extensions.data()));
+ instance.devices.emplace_back(VkJsonGetDevice(devices[i]));
}
- PFN_vkEnumerateInstanceVersion vkpEnumerateInstanceVersion =
- reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
- vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
- if (!vkpEnumerateInstanceVersion) {
- instance.api_version = VK_API_VERSION_1_0;
- } else {
- result = (*vkpEnumerateInstanceVersion)(&instance.api_version);
- if (result != VK_SUCCESS) {
- vkDestroyInstance(vkinstance, nullptr);
- return VkJsonInstance();
- }
+ result = vkEnumerateInstanceVersion(&instance.api_version);
+ if (result != VK_SUCCESS) {
+ vkDestroyInstance(vkinstance, nullptr);
+ return VkJsonInstance();
}
- PFN_vkEnumeratePhysicalDeviceGroups vkpEnumeratePhysicalDeviceGroups =
- reinterpret_cast<PFN_vkEnumeratePhysicalDeviceGroups>(
- vkGetInstanceProcAddr(vkinstance, "vkEnumeratePhysicalDeviceGroups"));
- if (vkpEnumeratePhysicalDeviceGroups) {
- count = 0;
- result = (*vkpEnumeratePhysicalDeviceGroups)(vkinstance, &count, nullptr);
- if (result != VK_SUCCESS) {
- vkDestroyInstance(vkinstance, nullptr);
- return VkJsonInstance();
- }
+ count = 0;
+ result = vkEnumeratePhysicalDeviceGroups(vkinstance, &count, nullptr);
+ if (result != VK_SUCCESS) {
+ vkDestroyInstance(vkinstance, nullptr);
+ return VkJsonInstance();
+ }
- VkJsonDeviceGroup device_group;
- std::vector<VkPhysicalDeviceGroupProperties> group_properties;
- group_properties.resize(count);
- result = (*vkpEnumeratePhysicalDeviceGroups)(vkinstance, &count,
- group_properties.data());
- if (result != VK_SUCCESS) {
- vkDestroyInstance(vkinstance, nullptr);
- return VkJsonInstance();
+ VkJsonDeviceGroup device_group;
+ std::vector<VkPhysicalDeviceGroupProperties> group_properties;
+ group_properties.resize(count);
+ result = vkEnumeratePhysicalDeviceGroups(vkinstance, &count,
+ group_properties.data());
+ if (result != VK_SUCCESS) {
+ vkDestroyInstance(vkinstance, nullptr);
+ return VkJsonInstance();
+ }
+ for (auto properties : group_properties) {
+ device_group.properties = properties;
+ for (uint32_t i = 0; i < properties.physicalDeviceCount; ++i) {
+ device_group.device_inds.push_back(
+ device_map[properties.physicalDevices[i]]);
}
- for (auto properties : group_properties) {
- device_group.properties = properties;
- for (uint32_t i = 0; i < properties.physicalDeviceCount; ++i) {
- device_group.device_inds.push_back(
- device_map[properties.physicalDevices[i]]);
- }
- instance.device_groups.push_back(device_group);
- }
+ instance.device_groups.push_back(device_group);
}
vkDestroyInstance(vkinstance, nullptr);