Merge changes I50e3a5e1,Icd043916 into main
* changes:
Remove use of legacy layers from TransactionApplicationTest
Remove use of legacy layers from composition test
diff --git a/Android.bp b/Android.bp
index 2520a71..4befb1b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -39,6 +39,11 @@
cc_library_headers {
name: "native_headers",
host_supported: true,
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
export_include_dirs: [
"include/",
],
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 1333599..0f251d2 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -249,6 +249,25 @@
return names;
}
+static std::optional<std::string> getVintfAccessorName(const std::string& name) {
+ AidlName aname;
+ if (!AidlName::fill(name, &aname)) return std::nullopt;
+
+ std::optional<std::string> accessor;
+ forEachManifest([&](const ManifestWithDescription& mwd) {
+ mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+ if (manifestInstance.format() != vintf::HalFormat::AIDL) return true;
+ if (manifestInstance.package() != aname.package) return true;
+ if (manifestInstance.interface() != aname.iface) return true;
+ if (manifestInstance.instance() != aname.instance) return true;
+ accessor = manifestInstance.accessor();
+ return false; // break (libvintf uses opposite convention)
+ });
+ return false; // continue
+ });
+ return accessor;
+}
+
static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
AidlName aname;
if (!AidlName::fill(name, &aname)) return std::nullopt;
@@ -364,23 +383,40 @@
}
}
-Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
+Status ServiceManager::getService(const std::string& name, os::Service* outService) {
SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str()));
- *outBinder = tryGetService(name, true);
+ *outService = tryGetService(name, true);
// returns ok regardless of result for legacy reasons
return Status::ok();
}
-Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
+Status ServiceManager::checkService(const std::string& name, os::Service* outService) {
SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str()));
- *outBinder = tryGetService(name, false);
+ *outService = tryGetService(name, false);
// returns ok regardless of result for legacy reasons
return Status::ok();
}
-sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
+os::Service ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
+ std::optional<std::string> accessorName;
+#ifndef VENDORSERVICEMANAGER
+ accessorName = getVintfAccessorName(name);
+#endif
+ if (accessorName.has_value()) {
+ auto ctx = mAccess->getCallingContext();
+ if (!mAccess->canFind(ctx, name)) {
+ return os::Service::make<os::Service::Tag::accessor>(nullptr);
+ }
+ return os::Service::make<os::Service::Tag::accessor>(
+ tryGetBinder(*accessorName, startIfNotFound));
+ } else {
+ return os::Service::make<os::Service::Tag::binder>(tryGetBinder(name, startIfNotFound));
+ }
+}
+
+sp<IBinder> ServiceManager::tryGetBinder(const std::string& name, bool startIfNotFound) {
SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str()));
auto ctx = mAccess->getCallingContext();
@@ -565,8 +601,11 @@
auto ctx = mAccess->getCallingContext();
- if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux");
+ // TODO(b/338541373): Implement the notification mechanism for services accessed via
+ // IAccessor.
+ std::optional<std::string> accessorName;
+ if (auto status = canFindService(ctx, name, &accessorName); !status.isOk()) {
+ return status;
}
// note - we could allow isolated apps to get notifications if we
@@ -613,8 +652,9 @@
auto ctx = mAccess->getCallingContext();
- if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
+ std::optional<std::string> accessorName;
+ if (auto status = canFindService(ctx, name, &accessorName); !status.isOk()) {
+ return status;
}
bool found = false;
@@ -638,8 +678,9 @@
auto ctx = mAccess->getCallingContext();
- if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
+ std::optional<std::string> accessorName;
+ if (auto status = canFindService(ctx, name, &accessorName); !status.isOk()) {
+ return status;
}
*outReturn = false;
@@ -662,8 +703,10 @@
outReturn->clear();
+ std::optional<std::string> _accessorName;
for (const std::string& instance : allInstances) {
- if (mAccess->canFind(ctx, interface + "/" + instance)) {
+ if (auto status = canFindService(ctx, interface + "/" + instance, &_accessorName);
+ status.isOk()) {
outReturn->push_back(instance);
}
}
@@ -681,8 +724,9 @@
auto ctx = mAccess->getCallingContext();
- if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
+ std::optional<std::string> _accessorName;
+ if (auto status = canFindService(ctx, name, &_accessorName); !status.isOk()) {
+ return status;
}
*outReturn = std::nullopt;
@@ -706,8 +750,9 @@
outReturn->clear();
+ std::optional<std::string> _accessorName;
for (const std::string& name : apexUpdatableNames) {
- if (mAccess->canFind(ctx, name)) {
+ if (auto status = canFindService(ctx, name, &_accessorName); status.isOk()) {
outReturn->push_back(name);
}
}
@@ -724,8 +769,9 @@
auto ctx = mAccess->getCallingContext();
- if (!mAccess->canFind(ctx, name)) {
- return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
+ std::optional<std::string> _accessorName;
+ if (auto status = canFindService(ctx, name, &_accessorName); !status.isOk()) {
+ return status;
}
*outReturn = std::nullopt;
@@ -1032,6 +1078,23 @@
return Status::ok();
}
+Status ServiceManager::canFindService(const Access::CallingContext& ctx, const std::string& name,
+ std::optional<std::string>* accessor) {
+ if (!mAccess->canFind(ctx, name)) {
+ return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied for service.");
+ }
+#ifndef VENDORSERVICEMANAGER
+ *accessor = getVintfAccessorName(name);
+#endif
+ if (accessor->has_value()) {
+ if (!mAccess->canFind(ctx, accessor->value())) {
+ return Status::fromExceptionCode(Status::EX_SECURITY,
+ "SELinux denied for the accessor of the service.");
+ }
+ }
+ return Status::ok();
+}
+
Status ServiceManager::getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) {
SM_PERFETTO_TRACE_FUNC();
if (!mAccess->canList(mAccess->getCallingContext())) {
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 1536014..18bae68 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -44,8 +44,8 @@
~ServiceManager();
// getService will try to start any services it cannot find
- binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override;
- binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override;
+ binder::Status getService(const std::string& name, os::Service* outService) override;
+ binder::Status checkService(const std::string& name, os::Service* outService) override;
binder::Status addService(const std::string& name, const sp<IBinder>& binder,
bool allowIsolated, int32_t dumpPriority) override;
binder::Status listServices(int32_t dumpPriority, std::vector<std::string>* outList) override;
@@ -112,7 +112,10 @@
// this updates the iterator to the next location
void removeClientCallback(const wp<IBinder>& who, ClientCallbackMap::iterator* it);
- sp<IBinder> tryGetService(const std::string& name, bool startIfNotFound);
+ os::Service tryGetService(const std::string& name, bool startIfNotFound);
+ sp<IBinder> tryGetBinder(const std::string& name, bool startIfNotFound);
+ binder::Status canFindService(const Access::CallingContext& ctx, const std::string& name,
+ std::optional<std::string>* accessor);
ServiceMap mNameToService;
ServiceCallbackMap mNameToRegistrationCallback;
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index b575053..9d22641 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -38,6 +38,7 @@
using android::binder::Status;
using android::os::BnServiceCallback;
using android::os::IServiceManager;
+using android::os::Service;
using testing::_;
using testing::ElementsAre;
using testing::NiceMock;
@@ -153,18 +154,18 @@
EXPECT_TRUE(sm->addService("foo", serviceA, false /*allowIsolated*/,
IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- sp<IBinder> outA;
+ Service outA;
EXPECT_TRUE(sm->getService("foo", &outA).isOk());
- EXPECT_EQ(serviceA, outA);
+ EXPECT_EQ(serviceA, outA.get<Service::Tag::binder>());
// serviceA should be overwritten by serviceB
sp<IBinder> serviceB = getBinder();
EXPECT_TRUE(sm->addService("foo", serviceB, false /*allowIsolated*/,
IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- sp<IBinder> outB;
+ Service outB;
EXPECT_TRUE(sm->getService("foo", &outB).isOk());
- EXPECT_EQ(serviceB, outB);
+ EXPECT_EQ(serviceB, outB.get<Service::Tag::binder>());
}
TEST(AddService, NoPermissions) {
@@ -186,17 +187,17 @@
EXPECT_TRUE(sm->addService("foo", service, false /*allowIsolated*/,
IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- sp<IBinder> out;
+ Service out;
EXPECT_TRUE(sm->getService("foo", &out).isOk());
- EXPECT_EQ(service, out);
+ EXPECT_EQ(service, out.get<Service::Tag::binder>());
}
TEST(GetService, NonExistant) {
auto sm = getPermissiveServiceManager();
- sp<IBinder> out;
+ Service out;
EXPECT_TRUE(sm->getService("foo", &out).isOk());
- EXPECT_EQ(nullptr, out.get());
+ EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
}
TEST(GetService, NoPermissionsForGettingService) {
@@ -211,10 +212,10 @@
EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- sp<IBinder> out;
+ Service out;
// returns nullptr but has OK status for legacy compatibility
EXPECT_TRUE(sm->getService("foo", &out).isOk());
- EXPECT_EQ(nullptr, out.get());
+ EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
}
TEST(GetService, AllowedFromIsolated) {
@@ -236,9 +237,9 @@
EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/,
IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- sp<IBinder> out;
+ Service out;
EXPECT_TRUE(sm->getService("foo", &out).isOk());
- EXPECT_EQ(service, out.get());
+ EXPECT_EQ(service, out.get<Service::Tag::binder>());
}
TEST(GetService, NotAllowedFromIsolated) {
@@ -261,10 +262,10 @@
EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
- sp<IBinder> out;
+ Service out;
// returns nullptr but has OK status for legacy compatibility
EXPECT_TRUE(sm->getService("foo", &out).isOk());
- EXPECT_EQ(nullptr, out.get());
+ EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
}
TEST(ListServices, NoPermissions) {
diff --git a/data/etc/input/motion_predictor_config.xml b/data/etc/input/motion_predictor_config.xml
index c3f2fed..14540ec 100644
--- a/data/etc/input/motion_predictor_config.xml
+++ b/data/etc/input/motion_predictor_config.xml
@@ -35,7 +35,10 @@
The jerk thresholds are based on normalized dt = 1 calculations.
-->
- <low-jerk>1.0</low-jerk>
- <high-jerk>1.1</high-jerk>
+ <low-jerk>1.5</low-jerk>
+ <high-jerk>2.0</high-jerk>
+
+ <!-- The forget factor in the first-order IIR filter for jerk smoothing -->
+ <jerk-forget-factor>0.25</jerk-forget-factor>
</motion-predictor>
diff --git a/include/input/Input.h b/include/input/Input.h
index 77d7448..1a3cb6a 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -900,9 +900,7 @@
void splitFrom(const MotionEvent& other, std::bitset<MAX_POINTER_ID + 1> splitPointerIds,
int32_t newEventId);
- void addSample(
- nsecs_t eventTime,
- const PointerCoords* pointerCoords);
+ void addSample(nsecs_t eventTime, const PointerCoords* pointerCoords, int32_t eventId);
void offsetLocation(float xOffset, float yOffset);
diff --git a/include/input/InputConsumerNoResampling.h b/include/input/InputConsumerNoResampling.h
index c7b1970..ae8de5f 100644
--- a/include/input/InputConsumerNoResampling.h
+++ b/include/input/InputConsumerNoResampling.h
@@ -16,8 +16,8 @@
#pragma once
+#include <input/InputTransport.h>
#include <utils/Looper.h>
-#include "InputTransport.h"
namespace android {
@@ -182,6 +182,16 @@
*/
std::map<DeviceId, std::queue<InputMessage>> mBatches;
/**
+ * Creates a MotionEvent by consuming samples from the provided queue. If one message has
+ * eventTime > frameTime, all subsequent messages in the queue will be skipped. It is assumed
+ * that messages are queued in chronological order. In other words, only events that occurred
+ * prior to the requested frameTime will be consumed.
+ * @param frameTime the time up to which to consume events
+ * @param messages the queue of messages to consume from
+ */
+ std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>> createBatchedMotionEvent(
+ const nsecs_t frameTime, std::queue<InputMessage>& messages);
+ /**
* A map from a single sequence number to several sequence numbers. This is needed because of
* batching. When batching is enabled, a single MotionEvent will contain several samples. Each
* sample came from an individual InputMessage of Type::Motion, and therefore will have to be
diff --git a/include/input/MotionPredictor.h b/include/input/MotionPredictor.h
index f715039..2f1ef86 100644
--- a/include/input/MotionPredictor.h
+++ b/include/input/MotionPredictor.h
@@ -56,12 +56,20 @@
// acceleration) and has the units of d^3p/dt^3.
std::optional<float> jerkMagnitude() const;
+ // forgetFactor is the coefficient of the first-order IIR filter for jerk. A factor of 1 results
+ // in no smoothing.
+ void setForgetFactor(float forgetFactor);
+ float getForgetFactor() const;
+
private:
const bool mNormalizedDt;
+ // Coefficient of first-order IIR filter to smooth jerk calculation.
+ float mForgetFactor = 1;
RingBuffer<int64_t> mTimestamps{4};
std::array<float, 4> mXDerivatives{}; // [x, x', x'', x''']
std::array<float, 4> mYDerivatives{}; // [y, y', y'', y''']
+ float mJerkMagnitude;
};
/**
@@ -116,6 +124,11 @@
bool isPredictionAvailable(int32_t deviceId, int32_t source);
+ /**
+ * Currently used to expose config constants in testing.
+ */
+ const TfLiteMotionPredictorModel::Config& getModelConfig();
+
private:
const nsecs_t mPredictionTimestampOffsetNanos;
const std::function<bool()> mCheckMotionPredictionEnabled;
diff --git a/include/input/TfLiteMotionPredictor.h b/include/input/TfLiteMotionPredictor.h
index 728a8e1..08a4330 100644
--- a/include/input/TfLiteMotionPredictor.h
+++ b/include/input/TfLiteMotionPredictor.h
@@ -110,6 +110,9 @@
// High jerk means more predictions will be pruned, vice versa for low.
float lowJerk = 0;
float highJerk = 0;
+
+ // Coefficient for the first-order IIR filter for jerk calculation.
+ float jerkForgetFactor = 1;
};
// Creates a model from an encoded Flatbuffer model.
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index cdc7166..de331b7 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -450,8 +450,31 @@
],
}
+soong_config_module_type {
+ name: "libbinder_client_cache_config",
+ module_type: "cc_defaults",
+ config_namespace: "libbinder",
+ bool_variables: ["release_libbinder_client_cache"],
+ properties: [
+ "cflags",
+ ],
+}
+
+libbinder_client_cache_config {
+ name: "libbinder_client_cache_flag",
+ soong_config_variables: {
+ release_libbinder_client_cache: {
+ cflags: ["-DLIBBINDER_CLIENT_CACHE"],
+ conditions_default: {
+ cflags: ["-DNO_LIBBINDER_CLIENT_CACHE"],
+ },
+ },
+ },
+}
+
cc_defaults {
name: "libbinder_kernel_defaults",
+ defaults: ["libbinder_client_cache_flag"],
srcs: [
"BufferedTextOutput.cpp",
"BackendUnifiedServiceManager.cpp",
@@ -771,11 +794,41 @@
"aidl/android/os/IClientCallback.aidl",
"aidl/android/os/IServiceCallback.aidl",
"aidl/android/os/IServiceManager.aidl",
+ "aidl/android/os/Service.aidl",
"aidl/android/os/ServiceDebugInfo.aidl",
+ ":libbinder_accessor_aidl",
],
path: "aidl",
}
+filegroup {
+ name: "libbinder_accessor_aidl",
+ srcs: [
+ "aidl/android/os/IAccessor.aidl",
+ ],
+ path: "aidl",
+}
+
+// TODO(b/353492849): Make this interface private to libbinder.
+aidl_interface {
+ name: "android.os.accessor",
+ srcs: [":libbinder_accessor_aidl"],
+ unstable: true,
+ backend: {
+ rust: {
+ enabled: true,
+ apex_available: [
+ "com.android.virt",
+ ],
+ },
+ },
+ visibility: [
+ ":__subpackages__",
+ "//system/tools/aidl:__subpackages__",
+ "//packages/modules/Virtualization:__subpackages__",
+ ],
+}
+
aidl_interface {
name: "packagemanager_aidl",
unstable: true,
diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp
index b0d3048..0bf3cad 100644
--- a/libs/binder/BackendUnifiedServiceManager.cpp
+++ b/libs/binder/BackendUnifiedServiceManager.cpp
@@ -15,6 +15,9 @@
*/
#include "BackendUnifiedServiceManager.h"
+#include <android/os/IAccessor.h>
+#include <binder/RpcSession.h>
+
#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
#include <android-base/properties.h>
#endif
@@ -22,6 +25,7 @@
namespace android {
using AidlServiceManager = android::os::IServiceManager;
+using IAccessor = android::os::IAccessor;
BackendUnifiedServiceManager::BackendUnifiedServiceManager(const sp<AidlServiceManager>& impl)
: mTheRealServiceManager(impl) {}
@@ -30,13 +34,57 @@
return mTheRealServiceManager;
}
binder::Status BackendUnifiedServiceManager::getService(const ::std::string& name,
- sp<IBinder>* _aidl_return) {
- return mTheRealServiceManager->getService(name, _aidl_return);
+ os::Service* _out) {
+ os::Service service;
+ binder::Status status = mTheRealServiceManager->getService(name, &service);
+ toBinderService(service, _out);
+ return status;
}
+
binder::Status BackendUnifiedServiceManager::checkService(const ::std::string& name,
- sp<IBinder>* _aidl_return) {
- return mTheRealServiceManager->checkService(name, _aidl_return);
+ os::Service* _out) {
+ os::Service service;
+ binder::Status status = mTheRealServiceManager->checkService(name, &service);
+ toBinderService(service, _out);
+ return status;
}
+
+void BackendUnifiedServiceManager::toBinderService(const os::Service& in, os::Service* _out) {
+ switch (in.getTag()) {
+ case os::Service::Tag::binder: {
+ *_out = in;
+ break;
+ }
+ case os::Service::Tag::accessor: {
+ sp<IBinder> accessorBinder = in.get<os::Service::Tag::accessor>();
+ sp<IAccessor> accessor = interface_cast<IAccessor>(accessorBinder);
+ if (accessor == nullptr) {
+ ALOGE("Service#accessor doesn't have accessor. VM is maybe starting...");
+ *_out = os::Service::make<os::Service::Tag::binder>(nullptr);
+ break;
+ }
+ auto request = [=] {
+ os::ParcelFileDescriptor fd;
+ binder::Status ret = accessor->addConnection(&fd);
+ if (ret.isOk()) {
+ return base::unique_fd(fd.release());
+ } else {
+ ALOGE("Failed to connect to RpcSession: %s", ret.toString8().c_str());
+ return base::unique_fd(-1);
+ }
+ };
+ auto session = RpcSession::make();
+ session->setupPreconnectedClient(base::unique_fd{}, request);
+ session->setSessionSpecificRoot(accessorBinder);
+ *_out = os::Service::make<os::Service::Tag::binder>(session->getRootObject());
+ break;
+ }
+ default: {
+ LOG_ALWAYS_FATAL("Unknown service type: %d", in.getTag());
+ }
+ }
+}
+
binder::Status BackendUnifiedServiceManager::addService(const ::std::string& name,
const sp<IBinder>& service,
bool allowIsolated, int32_t dumpPriority) {
diff --git a/libs/binder/BackendUnifiedServiceManager.h b/libs/binder/BackendUnifiedServiceManager.h
index d72b5bb..4715be4 100644
--- a/libs/binder/BackendUnifiedServiceManager.h
+++ b/libs/binder/BackendUnifiedServiceManager.h
@@ -26,8 +26,8 @@
explicit BackendUnifiedServiceManager(const sp<os::IServiceManager>& impl);
sp<os::IServiceManager> getImpl();
- binder::Status getService(const ::std::string& name, sp<IBinder>* _aidl_return) override;
- binder::Status checkService(const ::std::string& name, sp<IBinder>* _aidl_return) override;
+ binder::Status getService(const ::std::string& name, os::Service* out) override;
+ binder::Status checkService(const ::std::string& name, os::Service* out) override;
binder::Status addService(const ::std::string& name, const sp<IBinder>& service,
bool allowIsolated, int32_t dumpPriority) override;
binder::Status listServices(int32_t dumpPriority,
@@ -60,6 +60,7 @@
private:
sp<os::IServiceManager> mTheRealServiceManager;
+ void toBinderService(const os::Service& in, os::Service* _out);
};
sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager();
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 17e522d..12a18f2 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -26,6 +26,7 @@
#include <android-base/properties.h>
#include <android/os/BnServiceCallback.h>
+#include <android/os/IAccessor.h>
#include <android/os/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
@@ -57,6 +58,8 @@
using AidlServiceManager = android::os::IServiceManager;
using android::binder::Status;
+using android::os::IAccessor;
+using android::os::Service;
// libbinder's IServiceManager.h can't rely on the values generated by AIDL
// because many places use its headers via include_dirs (meaning, without
@@ -139,7 +142,10 @@
// When implementing ServiceManagerShim, use realGetService instead of
// mUnifiedServiceManager->getService so that it can be overridden in ServiceManagerHostShim.
virtual Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
- return mUnifiedServiceManager->getService(name, _aidl_return);
+ Service service;
+ Status status = mUnifiedServiceManager->getService(name, &service);
+ *_aidl_return = service.get<Service::Tag::binder>();
+ return status;
}
};
@@ -327,11 +333,11 @@
sp<IBinder> ServiceManagerShim::checkService(const String16& name) const
{
- sp<IBinder> ret;
+ Service ret;
if (!mUnifiedServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
return nullptr;
}
- return ret;
+ return ret.get<Service::Tag::binder>();
}
status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 16a7f9f..49def82 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -801,6 +801,14 @@
return true;
}
+void RpcSession::setSessionSpecificRoot(const sp<IBinder>& sessionSpecificRoot) {
+ LOG_ALWAYS_FATAL_IF(mSessionSpecificRootObject != nullptr,
+ "Session specific root object already set");
+ LOG_ALWAYS_FATAL_IF(mForServer != nullptr,
+ "Session specific root object cannot be set for a server");
+ mSessionSpecificRootObject = sessionSpecificRoot;
+}
+
sp<RpcSession::RpcConnection> RpcSession::assignIncomingConnectionToThisThread(
std::unique_ptr<RpcTransport> rpcTransport) {
RpcMutexLockGuard _l(mMutex);
diff --git a/libs/binder/aidl/android/os/IAccessor.aidl b/libs/binder/aidl/android/os/IAccessor.aidl
new file mode 100644
index 0000000..a3134a3
--- /dev/null
+++ b/libs/binder/aidl/android/os/IAccessor.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 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.os.ParcelFileDescriptor;
+
+/**
+ * Interface for accessing the RPC server of a service.
+ *
+ * @hide
+ */
+interface IAccessor {
+ /**
+ * Adds a connection to the RPC server of the service managed by the IAccessor.
+ *
+ * This method can be called multiple times to establish multiple distinct
+ * connections to the same RPC server.
+ *
+ * @return A file descriptor connected to the RPC session of the service managed
+ * by IAccessor.
+ */
+ ParcelFileDescriptor addConnection();
+
+ // TODO(b/350941051): Add API for debugging.
+}
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 0fb1615..ac95188 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -18,6 +18,7 @@
import android.os.IClientCallback;
import android.os.IServiceCallback;
+import android.os.Service;
import android.os.ServiceDebugInfo;
import android.os.ConnectionInfo;
@@ -61,7 +62,7 @@
* Returns null if the service does not exist.
*/
@UnsupportedAppUsage
- @nullable IBinder getService(@utf8InCpp String name);
+ Service getService(@utf8InCpp String name);
/**
* Retrieve an existing service called @a name from the service
@@ -69,7 +70,7 @@
* exist.
*/
@UnsupportedAppUsage
- @nullable IBinder checkService(@utf8InCpp String name);
+ Service checkService(@utf8InCpp String name);
/**
* Place a new @a service called @a name into the service
diff --git a/libs/binder/aidl/android/os/Service.aidl b/libs/binder/aidl/android/os/Service.aidl
new file mode 100644
index 0000000..4c52109
--- /dev/null
+++ b/libs/binder/aidl/android/os/Service.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 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;
+
+/**
+ * Service is a union of different service types that can be returned
+ * by the internal {@link ServiceManager#getService(name)} API.
+ *
+ * @hide
+ */
+union Service {
+ @nullable IBinder binder;
+ @nullable IBinder accessor;
+}
\ No newline at end of file
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 40102bb..af37bf2 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -220,6 +220,12 @@
// internal only
LIBBINDER_EXPORTED const std::unique_ptr<RpcState>& state() { return mRpcBinderState; }
+ /**
+ * Sets the session-specific root object. This is the object that will be used to attach
+ * the IAccessor binder to the RpcSession when a binder is set up via accessor.
+ */
+ LIBBINDER_EXPORTED void setSessionSpecificRoot(const sp<IBinder>& sessionSpecificRoot);
+
private:
friend sp<RpcSession>;
friend RpcServer;
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index 18b178b..201dfbc 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -118,13 +118,11 @@
class ServiceManagerProxyToNative : public android::os::BnServiceManager {
public:
ServiceManagerProxyToNative(const sp<android::os::IServiceManager>& impl) : mImpl(impl) {}
- android::binder::Status getService(const std::string&,
- android::sp<android::IBinder>*) override {
+ android::binder::Status getService(const std::string&, android::os::Service*) override {
// We can't send BpBinder for regular binder over RPC.
return android::binder::Status::fromStatusT(android::INVALID_OPERATION);
}
- android::binder::Status checkService(const std::string&,
- android::sp<android::IBinder>*) override {
+ android::binder::Status checkService(const std::string&, android::os::Service*) override {
// We can't send BpBinder for regular binder over RPC.
return android::binder::Status::fromStatusT(android::INVALID_OPERATION);
}
diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index 62b8433..7c19614 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -111,7 +111,9 @@
} else {
binder = getRandomBinder(&provider);
}
- CHECK(OK == p->writeStrongBinder(binder));
+
+ // may fail if mixing kernel binder and RPC binder
+ (void) p->writeStrongBinder(binder);
},
});
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index f4cf11e..a9bd11e 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <set>
+#include <utility>
#include <android-base/file.h>
#include <android-base/parseint.h>
@@ -115,7 +116,7 @@
/* list of extra hal interfaces to dump containing process during native dumps */
// This is filled when dumpstate is called.
-static std::set<const std::string> extra_hal_interfaces_to_dump;
+static std::set<std::string> extra_hal_interfaces_to_dump;
static void read_extra_hals_to_dump_from_property() {
// extra hals to dump are already filled
@@ -129,7 +130,7 @@
if (trimmed_token.length() == 0) {
continue;
}
- extra_hal_interfaces_to_dump.insert(trimmed_token);
+ extra_hal_interfaces_to_dump.insert(std::move(trimmed_token));
}
}
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 2699368..ff6b558 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -62,7 +62,7 @@
status_t setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state,
- Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
InputWindowCommands commands, int64_t desiredPresentTime, bool isAutoTimestamp,
const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 88d3a7c..2821b51 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -20,6 +20,8 @@
#include <stdint.h>
#include <sys/types.h>
+#include <com_android_graphics_libgui_flags.h>
+
#include <android/gui/BnWindowInfosReportedListener.h>
#include <android/gui/DisplayState.h>
#include <android/gui/EdgeExtensionParameters.h>
@@ -1172,8 +1174,7 @@
uncacheBuffer.token = BufferCache::getInstance().getToken();
uncacheBuffer.id = cacheId;
Vector<ComposerState> composerStates;
- Vector<DisplayState> displayStates;
- status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, displayStates,
+ status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, {},
ISurfaceComposer::eOneWay,
Transaction::getDefaultApplyToken(), {}, systemTime(),
true, {uncacheBuffer}, false, {}, generateId(), {});
@@ -2331,6 +2332,10 @@
return *this;
}
+bool SurfaceComposerClient::flagEdgeExtensionEffectUseShader() {
+ return com::android::graphics::libgui::flags::edge_extension_shader();
+}
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setEdgeExtensionEffect(
const sp<SurfaceControl>& sc, const gui::EdgeExtensionParameters& effect) {
layer_state_t* s = getLayerState(sc);
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 1ecc216..eb4a802 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -112,7 +112,7 @@
/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
virtual status_t setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state,
- Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
InputWindowCommands inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffer,
bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index a10283b..95574ee 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -339,6 +339,8 @@
static std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>
getDisplayDecorationSupport(const sp<IBinder>& displayToken);
+ static bool flagEdgeExtensionEffectUseShader();
+
// ------------------------------------------------------------------------
// surface creation / destruction
diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig
index 792966f..74d806e 100644
--- a/libs/gui/libgui_flags.aconfig
+++ b/libs/gui/libgui_flags.aconfig
@@ -35,3 +35,19 @@
purpose: PURPOSE_BUGFIX
}
} # trace_frame_rate_override
+
+flag {
+ name: "wb_platform_api_improvements"
+ namespace: "core_graphics"
+ description: "Simple improvements to Surface and ConsumerBase classes"
+ bug: "340933794"
+ is_fixed_read_only: true
+} # wb_platform_api_improvements
+
+flag {
+ name: "edge_extension_shader"
+ namespace: "windowing_frontend"
+ description: "Enable edge extension via shader"
+ bug: "322036393"
+ is_fixed_read_only: true
+} # edge_extension_shader
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 1d3174c..ace4423 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -636,7 +636,7 @@
status_t setTransactionState(
const FrameTimelineInfo& /*frameTimelineInfo*/, Vector<ComposerState>& /*state*/,
- Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
+ const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
const sp<IBinder>& /*applyToken*/, InputWindowCommands /*inputWindowCommands*/,
int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/,
const std::vector<client_cache_t>& /*cachedBuffer*/, bool /*hasListenerCallbacks*/,
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 45ebc66..8fbf5c6 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -258,7 +258,7 @@
],
shared_libs: [
- "android.companion.virtualdevice.flags-aconfig-cc-host",
+ "android.companion.virtualdevice.flags-aconfig-cc",
"libbase",
"libbinder",
"libbinder_ndk",
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index b098147..a2bb345 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -580,7 +580,7 @@
&pointerProperties[pointerCount]);
mSampleEventTimes.clear();
mSamplePointerCoords.clear();
- addSample(eventTime, pointerCoords);
+ addSample(eventTime, pointerCoords, mId);
}
void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
@@ -640,9 +640,9 @@
mSampleEventTimes = other.mSampleEventTimes;
}
-void MotionEvent::addSample(
- int64_t eventTime,
- const PointerCoords* pointerCoords) {
+void MotionEvent::addSample(int64_t eventTime, const PointerCoords* pointerCoords,
+ int32_t eventId) {
+ mId = eventId;
mSampleEventTimes.push_back(eventTime);
mSamplePointerCoords.insert(mSamplePointerCoords.end(), &pointerCoords[0],
&pointerCoords[getPointerCount()]);
diff --git a/libs/input/InputConsumer.cpp b/libs/input/InputConsumer.cpp
index dce528f..1eeb4e6 100644
--- a/libs/input/InputConsumer.cpp
+++ b/libs/input/InputConsumer.cpp
@@ -135,7 +135,7 @@
}
event.setMetaState(event.getMetaState() | msg.body.motion.metaState);
- event.addSample(msg.body.motion.eventTime, pointerCoords);
+ event.addSample(msg.body.motion.eventTime, pointerCoords, msg.body.motion.eventId);
}
void initializeTouchModeEvent(TouchModeEvent& event, const InputMessage& msg) {
@@ -697,7 +697,7 @@
currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha);
}
- event->addSample(sampleTime, touchState.lastResample.pointers);
+ event->addSample(sampleTime, touchState.lastResample.pointers, event->getId());
}
status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
diff --git a/libs/input/InputConsumerNoResampling.cpp b/libs/input/InputConsumerNoResampling.cpp
index e193983..c145d5c 100644
--- a/libs/input/InputConsumerNoResampling.cpp
+++ b/libs/input/InputConsumerNoResampling.cpp
@@ -114,7 +114,7 @@
// TODO(b/329770983): figure out if it's safe to combine events with mismatching metaState
event.setMetaState(event.getMetaState() | msg.body.motion.metaState);
- event.addSample(msg.body.motion.eventTime, pointerCoords.data());
+ event.addSample(msg.body.motion.eventTime, pointerCoords.data(), msg.body.motion.eventId);
}
std::unique_ptr<TouchModeEvent> createTouchModeEvent(const InputMessage& msg) {
@@ -445,6 +445,27 @@
}
}
+std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>>
+InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t frameTime,
+ std::queue<InputMessage>& messages) {
+ std::unique_ptr<MotionEvent> motionEvent;
+ std::optional<uint32_t> firstSeqForBatch;
+ while (!messages.empty() && !(messages.front().body.motion.eventTime > frameTime)) {
+ if (motionEvent == nullptr) {
+ motionEvent = createMotionEvent(messages.front());
+ firstSeqForBatch = messages.front().header.seq;
+ const auto [_, inserted] = mBatchedSequenceNumbers.insert({*firstSeqForBatch, {}});
+ LOG_IF(FATAL, !inserted)
+ << "The sequence " << messages.front().header.seq << " was already present!";
+ } else {
+ addSample(*motionEvent, messages.front());
+ mBatchedSequenceNumbers[*firstSeqForBatch].push_back(messages.front().header.seq);
+ }
+ messages.pop();
+ }
+ return std::make_pair(std::move(motionEvent), firstSeqForBatch);
+}
+
bool InputConsumerNoResampling::consumeBatchedInputEvents(
std::optional<nsecs_t> requestedFrameTime) {
ensureCalledOnLooperThread(__func__);
@@ -452,28 +473,8 @@
// infinite frameTime.
const nsecs_t frameTime = requestedFrameTime.value_or(std::numeric_limits<nsecs_t>::max());
bool producedEvents = false;
- for (auto& [deviceId, messages] : mBatches) {
- std::unique_ptr<MotionEvent> motion;
- std::optional<uint32_t> firstSeqForBatch;
- std::vector<uint32_t> sequences;
- while (!messages.empty()) {
- const InputMessage& msg = messages.front();
- if (msg.body.motion.eventTime > frameTime) {
- break;
- }
- if (motion == nullptr) {
- motion = createMotionEvent(msg);
- firstSeqForBatch = msg.header.seq;
- const auto [_, inserted] = mBatchedSequenceNumbers.insert({*firstSeqForBatch, {}});
- if (!inserted) {
- LOG(FATAL) << "The sequence " << msg.header.seq << " was already present!";
- }
- } else {
- addSample(*motion, msg);
- mBatchedSequenceNumbers[*firstSeqForBatch].push_back(msg.header.seq);
- }
- messages.pop();
- }
+ for (auto& [_, messages] : mBatches) {
+ auto [motion, firstSeqForBatch] = createBatchedMotionEvent(frameTime, messages);
if (motion != nullptr) {
LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value());
mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch);
diff --git a/libs/input/MotionPredictor.cpp b/libs/input/MotionPredictor.cpp
index 5b61d39..9c70535 100644
--- a/libs/input/MotionPredictor.cpp
+++ b/libs/input/MotionPredictor.cpp
@@ -75,6 +75,9 @@
JerkTracker::JerkTracker(bool normalizedDt) : mNormalizedDt(normalizedDt) {}
void JerkTracker::pushSample(int64_t timestamp, float xPos, float yPos) {
+ // If we previously had full samples, we have a previous jerk calculation
+ // to do weighted smoothing.
+ const bool applySmoothing = mTimestamps.size() == mTimestamps.capacity();
mTimestamps.pushBack(timestamp);
const int numSamples = mTimestamps.size();
@@ -115,6 +118,16 @@
}
}
+ if (numSamples == static_cast<int>(mTimestamps.capacity())) {
+ float newJerkMagnitude = std::hypot(newXDerivatives[3], newYDerivatives[3]);
+ ALOGD_IF(isDebug(), "raw jerk: %f", newJerkMagnitude);
+ if (applySmoothing) {
+ mJerkMagnitude = mJerkMagnitude + (mForgetFactor * (newJerkMagnitude - mJerkMagnitude));
+ } else {
+ mJerkMagnitude = newJerkMagnitude;
+ }
+ }
+
std::swap(newXDerivatives, mXDerivatives);
std::swap(newYDerivatives, mYDerivatives);
}
@@ -125,11 +138,19 @@
std::optional<float> JerkTracker::jerkMagnitude() const {
if (mTimestamps.size() == mTimestamps.capacity()) {
- return std::hypot(mXDerivatives[3], mYDerivatives[3]);
+ return mJerkMagnitude;
}
return std::nullopt;
}
+void JerkTracker::setForgetFactor(float forgetFactor) {
+ mForgetFactor = forgetFactor;
+}
+
+float JerkTracker::getForgetFactor() const {
+ return mForgetFactor;
+}
+
// --- MotionPredictor ---
MotionPredictor::MotionPredictor(nsecs_t predictionTimestampOffsetNanos,
@@ -159,6 +180,7 @@
if (!mModel) {
mModel = TfLiteMotionPredictorModel::create();
LOG_ALWAYS_FATAL_IF(!mModel);
+ mJerkTracker.setForgetFactor(mModel->config().jerkForgetFactor);
}
if (!mBuffers) {
@@ -323,7 +345,7 @@
event.getRawTransform(), event.getDownTime(), predictionTime,
event.getPointerCount(), event.getPointerProperties(), &coords);
} else {
- prediction->addSample(predictionTime, &coords);
+ prediction->addSample(predictionTime, &coords, prediction->getId());
}
axisFrom = axisTo;
@@ -357,4 +379,12 @@
return true;
}
+const TfLiteMotionPredictorModel::Config& MotionPredictor::getModelConfig() {
+ if (!mModel) {
+ mModel = TfLiteMotionPredictorModel::create();
+ LOG_ALWAYS_FATAL_IF(!mModel);
+ }
+ return mModel->config();
+}
+
} // namespace android
diff --git a/libs/input/TfLiteMotionPredictor.cpp b/libs/input/TfLiteMotionPredictor.cpp
index b843a4b..b401c98 100644
--- a/libs/input/TfLiteMotionPredictor.cpp
+++ b/libs/input/TfLiteMotionPredictor.cpp
@@ -283,6 +283,7 @@
.distanceNoiseFloor = parseXMLFloat(*configRoot, "distance-noise-floor"),
.lowJerk = parseXMLFloat(*configRoot, "low-jerk"),
.highJerk = parseXMLFloat(*configRoot, "high-jerk"),
+ .jerkForgetFactor = parseXMLFloat(*configRoot, "jerk-forget-factor"),
};
return std::unique_ptr<TfLiteMotionPredictorModel>(
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 3717f49..a67e1ef 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -371,8 +371,8 @@
mTransform, 2.0f, 2.1f, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, mRawTransform, ARBITRARY_DOWN_TIME,
ARBITRARY_EVENT_TIME, 2, mPointerProperties, mSamples[0].pointerCoords);
- event->addSample(ARBITRARY_EVENT_TIME + 1, mSamples[1].pointerCoords);
- event->addSample(ARBITRARY_EVENT_TIME + 2, mSamples[2].pointerCoords);
+ event->addSample(ARBITRARY_EVENT_TIME + 1, mSamples[1].pointerCoords, event->getId());
+ event->addSample(ARBITRARY_EVENT_TIME + 2, mSamples[2].pointerCoords, event->getId());
}
void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
@@ -591,6 +591,22 @@
ASSERT_EQ(event.getX(0), copy.getX(0));
}
+TEST_F(MotionEventTest, CheckEventIdWithHistoryIsIncremented) {
+ MotionEvent event;
+ constexpr int32_t ARBITRARY_ID = 42;
+ event.initialize(ARBITRARY_ID, 2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, INVALID_HMAC,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
+ AMOTION_EVENT_BUTTON_PRIMARY, MotionClassification::NONE, mTransform, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ mRawTransform, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2,
+ mPointerProperties, mSamples[0].pointerCoords);
+ ASSERT_EQ(event.getId(), ARBITRARY_ID);
+ event.addSample(ARBITRARY_EVENT_TIME + 1, mSamples[1].pointerCoords, ARBITRARY_ID + 1);
+ ASSERT_EQ(event.getId(), ARBITRARY_ID + 1);
+ event.addSample(ARBITRARY_EVENT_TIME + 2, mSamples[2].pointerCoords, ARBITRARY_ID + 2);
+ ASSERT_EQ(event.getId(), ARBITRARY_ID + 2);
+}
+
TEST_F(MotionEventTest, SplitPointerDown) {
MotionEvent event = MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
.downTime(ARBITRARY_DOWN_TIME)
diff --git a/libs/input/tests/MotionPredictorMetricsManager_test.cpp b/libs/input/tests/MotionPredictorMetricsManager_test.cpp
index cc41eeb..0542f39 100644
--- a/libs/input/tests/MotionPredictorMetricsManager_test.cpp
+++ b/libs/input/tests/MotionPredictorMetricsManager_test.cpp
@@ -167,7 +167,8 @@
.y(predictionPoints[i].position[0])
.axis(AMOTION_EVENT_AXIS_PRESSURE, predictionPoints[i].pressure)
.buildCoords();
- predictionEvent.addSample(predictionPoints[i].targetTimestamp, &coords);
+ predictionEvent.addSample(predictionPoints[i].targetTimestamp, &coords,
+ predictionEvent.getId());
}
return predictionEvent;
}
diff --git a/libs/input/tests/MotionPredictor_test.cpp b/libs/input/tests/MotionPredictor_test.cpp
index d077760..5bd5794 100644
--- a/libs/input/tests/MotionPredictor_test.cpp
+++ b/libs/input/tests/MotionPredictor_test.cpp
@@ -88,6 +88,7 @@
TEST(JerkTrackerTest, JerkCalculationNormalizedDtTrue) {
JerkTracker jerkTracker(true);
+ jerkTracker.setForgetFactor(.5);
jerkTracker.pushSample(/*timestamp=*/0, 20, 50);
jerkTracker.pushSample(/*timestamp=*/1, 25, 53);
jerkTracker.pushSample(/*timestamp=*/2, 30, 60);
@@ -118,11 +119,14 @@
* y'': 3 -> -15
* y''': -18
*/
- EXPECT_FLOAT_EQ(jerkTracker.jerkMagnitude().value(), std::hypot(-50, -18));
+ const float newJerk = (1 - jerkTracker.getForgetFactor()) * std::hypot(10, -1) +
+ jerkTracker.getForgetFactor() * std::hypot(-50, -18);
+ EXPECT_FLOAT_EQ(jerkTracker.jerkMagnitude().value(), newJerk);
}
TEST(JerkTrackerTest, JerkCalculationNormalizedDtFalse) {
JerkTracker jerkTracker(false);
+ jerkTracker.setForgetFactor(.5);
jerkTracker.pushSample(/*timestamp=*/0, 20, 50);
jerkTracker.pushSample(/*timestamp=*/10, 25, 53);
jerkTracker.pushSample(/*timestamp=*/20, 30, 60);
@@ -153,7 +157,9 @@
* y'': .03 -> -.125 (delta above, divide by 10)
* y''': -.0155 (delta above, divide by 10)
*/
- EXPECT_FLOAT_EQ(jerkTracker.jerkMagnitude().value(), std::hypot(-.0375, -.0155));
+ const float newJerk = (1 - jerkTracker.getForgetFactor()) * std::hypot(.01, -.001) +
+ jerkTracker.getForgetFactor() * std::hypot(-.0375, -.0155);
+ EXPECT_FLOAT_EQ(jerkTracker.jerkMagnitude().value(), newJerk);
}
TEST(JerkTrackerTest, JerkCalculationAfterReset) {
@@ -291,15 +297,19 @@
MotionPredictor predictor(/*predictionTimestampOffsetNanos=*/0,
[]() { return true /*enable prediction*/; });
- // Jerk is medium (1.05 normalized, which is halfway between LOW_JANK and HIGH_JANK)
- predictor.record(getMotionEvent(DOWN, 0, 5.2, 20ms));
- predictor.record(getMotionEvent(MOVE, 0, 11.5, 30ms));
- predictor.record(getMotionEvent(MOVE, 0, 22, 40ms));
- predictor.record(getMotionEvent(MOVE, 0, 37.75, 50ms));
- predictor.record(getMotionEvent(MOVE, 0, 59.8, 60ms));
+ const float mediumJerk =
+ (predictor.getModelConfig().lowJerk + predictor.getModelConfig().highJerk) / 2;
+ const float a = 3; // initial acceleration
+ const float b = 4; // initial velocity
+ const float c = 5; // initial position
+ predictor.record(getMotionEvent(DOWN, 0, c, 20ms));
+ predictor.record(getMotionEvent(MOVE, 0, c + b, 30ms));
+ predictor.record(getMotionEvent(MOVE, 0, c + 2 * b + a, 40ms));
+ predictor.record(getMotionEvent(MOVE, 0, c + 3 * b + 3 * a + mediumJerk, 50ms));
+ predictor.record(getMotionEvent(MOVE, 0, c + 4 * b + 6 * a + 4 * mediumJerk, 60ms));
std::unique_ptr<MotionEvent> predicted = predictor.predict(82 * NSEC_PER_MSEC);
EXPECT_NE(nullptr, predicted);
- // Halfway between LOW_JANK and HIGH_JANK means that half of the predictions
+ // Halfway between LOW_JERK and HIGH_JERK means that half of the predictions
// will be pruned. If model prediction window is close enough to predict()
// call time window, then half of the model predictions (5/2 -> 2) will be
// ouputted.
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 6fcb3a4..d05ff34 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -326,7 +326,7 @@
* COMPOSER_OVERLAY, the system will try to prioritize the buffer receiving
* an overlay plane & avoid caching it in intermediate composition buffers.
*/
- AHARDWAREBUFFER_USAGE_FRONT_BUFFER = 1UL << 32,
+ AHARDWAREBUFFER_USAGE_FRONT_BUFFER = 1ULL << 32,
AHARDWAREBUFFER_USAGE_VENDOR_0 = 1ULL << 28,
AHARDWAREBUFFER_USAGE_VENDOR_1 = 1ULL << 29,
diff --git a/libs/renderengine/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp
index 6f2a96a..8d0fbba 100644
--- a/libs/renderengine/ExternalTexture.cpp
+++ b/libs/renderengine/ExternalTexture.cpp
@@ -14,11 +14,11 @@
* limitations under the License.
*/
+#include <common/trace.h>
#include <log/log.h>
#include <renderengine/RenderEngine.h>
#include <renderengine/impl/ExternalTexture.h>
#include <ui/GraphicBuffer.h>
-#include <utils/Trace.h>
namespace android::renderengine::impl {
@@ -35,7 +35,7 @@
}
void ExternalTexture::remapBuffer() {
- ATRACE_CALL();
+ SFTRACE_CALL();
{
auto buf = mBuffer;
mRenderEngine.unmapExternalTextureBuffer(std::move(buf));
diff --git a/libs/renderengine/benchmark/Android.bp b/libs/renderengine/benchmark/Android.bp
index e1a6f6a..f84db0b 100644
--- a/libs/renderengine/benchmark/Android.bp
+++ b/libs/renderengine/benchmark/Android.bp
@@ -57,6 +57,7 @@
"libui",
"libutils",
"server_configurable_flags",
+ "libtracing_perfetto",
],
data: ["resources/*"],
diff --git a/libs/renderengine/skia/AutoBackendTexture.cpp b/libs/renderengine/skia/AutoBackendTexture.cpp
index 8aeef9f..b7b7a4d 100644
--- a/libs/renderengine/skia/AutoBackendTexture.cpp
+++ b/libs/renderengine/skia/AutoBackendTexture.cpp
@@ -25,8 +25,8 @@
#include "compat/SkiaBackendTexture.h"
+#include <common/trace.h>
#include <log/log_main.h>
-#include <utils/Trace.h>
namespace android {
namespace renderengine {
@@ -63,7 +63,7 @@
}
sk_sp<SkImage> AutoBackendTexture::makeImage(ui::Dataspace dataspace, SkAlphaType alphaType) {
- ATRACE_CALL();
+ SFTRACE_CALL();
sk_sp<SkImage> image = mBackendTexture->makeImage(alphaType, dataspace, releaseImageProc, this);
// The following ref will be counteracted by releaseProc, when SkImage is discarded.
@@ -75,7 +75,7 @@
}
sk_sp<SkSurface> AutoBackendTexture::getOrCreateSurface(ui::Dataspace dataspace) {
- ATRACE_CALL();
+ SFTRACE_CALL();
LOG_ALWAYS_FATAL_IF(!mBackendTexture->isOutputBuffer(),
"You can't generate an SkSurface for a read-only texture");
if (!mSurface.get() || mDataspace != dataspace) {
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index d246870..59b0656 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -729,8 +729,7 @@
const auto externalTexture =
std::make_shared<impl::ExternalTexture>(externalBuffer, *renderengine,
impl::ExternalTexture::Usage::READABLE);
- std::vector<const std::shared_ptr<ExternalTexture>> textures =
- {srcTexture, externalTexture};
+ std::vector<std::shared_ptr<ExternalTexture>> textures = {srcTexture, externalTexture};
// Another external texture with a different pixel format triggers useIsOpaqueWorkaround.
// It doesn't have to be f16, but it can't be the usual 8888.
diff --git a/libs/renderengine/skia/GaneshVkRenderEngine.cpp b/libs/renderengine/skia/GaneshVkRenderEngine.cpp
index 68798bf..a3a43e2 100644
--- a/libs/renderengine/skia/GaneshVkRenderEngine.cpp
+++ b/libs/renderengine/skia/GaneshVkRenderEngine.cpp
@@ -21,9 +21,9 @@
#include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
+#include <common/trace.h>
#include <log/log_main.h>
#include <sync/sync.h>
-#include <utils/Trace.h>
namespace android::renderengine::skia {
@@ -78,7 +78,7 @@
sk_sp<SkSurface> dstSurface) {
sk_sp<GrDirectContext> grContext = context->grDirectContext();
{
- ATRACE_NAME("flush surface");
+ SFTRACE_NAME("flush surface");
// TODO: Investigate feasibility of combining this "surface flush" into the "context flush"
// below.
context->grDirectContext()->flush(dstSurface.get());
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 48270e1..af24600 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -28,12 +28,11 @@
#include <GrContextOptions.h>
#include <GrTypes.h>
#include <android-base/stringprintf.h>
+#include <common/trace.h>
#include <gl/GrGLInterface.h>
#include <include/gpu/ganesh/gl/GrGLDirectContext.h>
-#include <gui/TraceUtils.h>
#include <sync/sync.h>
#include <ui/DebugUtils.h>
-#include <utils/Trace.h>
#include <cmath>
#include <cstdint>
@@ -332,7 +331,7 @@
void SkiaGLRenderEngine::waitFence(SkiaGpuContext*, base::borrowed_fd fenceFd) {
if (fenceFd.get() >= 0 && !waitGpuFence(fenceFd)) {
- ATRACE_NAME("SkiaGLRenderEngine::waitFence");
+ SFTRACE_NAME("SkiaGLRenderEngine::waitFence");
sync_wait(fenceFd.get(), -1);
}
}
@@ -341,19 +340,19 @@
sk_sp<SkSurface> dstSurface) {
sk_sp<GrDirectContext> grContext = context->grDirectContext();
{
- ATRACE_NAME("flush surface");
+ SFTRACE_NAME("flush surface");
grContext->flush(dstSurface.get());
}
base::unique_fd drawFence = flushGL();
bool requireSync = drawFence.get() < 0;
if (requireSync) {
- ATRACE_BEGIN("Submit(sync=true)");
+ SFTRACE_BEGIN("Submit(sync=true)");
} else {
- ATRACE_BEGIN("Submit(sync=false)");
+ SFTRACE_BEGIN("Submit(sync=false)");
}
bool success = grContext->submit(requireSync ? GrSyncCpu::kYes : GrSyncCpu::kNo);
- ATRACE_END();
+ SFTRACE_END();
if (!success) {
ALOGE("Failed to flush RenderEngine commands");
// Chances are, something illegal happened (Skia's internal GPU object
@@ -400,7 +399,7 @@
}
base::unique_fd SkiaGLRenderEngine::flushGL() {
- ATRACE_CALL();
+ SFTRACE_CALL();
if (!GLExtensions::getInstance().hasNativeFenceSync()) {
return base::unique_fd();
}
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index a609f2d..9709cd1 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -54,8 +54,8 @@
#include <SkTileMode.h>
#include <android-base/stringprintf.h>
#include <common/FlagManager.h>
+#include <common/trace.h>
#include <gui/FenceMonitor.h>
-#include <gui/TraceUtils.h>
#include <include/gpu/ganesh/SkSurfaceGanesh.h>
#include <pthread.h>
#include <src/core/SkTraceEventCommon.h>
@@ -64,7 +64,6 @@
#include <ui/DebugUtils.h>
#include <ui/GraphicBuffer.h>
#include <ui/HdrRenderTypeUtils.h>
-#include <utils/Trace.h>
#include <cmath>
#include <cstdint>
@@ -261,7 +260,7 @@
const SkString& description) {
mShadersCachedSinceLastCall++;
mTotalShadersCompiled++;
- ATRACE_FORMAT("SF cache: %i shaders", mTotalShadersCompiled);
+ SFTRACE_FORMAT("SF cache: %i shaders", mTotalShadersCompiled);
}
int SkiaRenderEngine::reportShadersCompiled() {
@@ -416,7 +415,7 @@
if (isProtectedBuffer || isProtected() || !isGpuSampleable) {
return;
}
- ATRACE_CALL();
+ SFTRACE_CALL();
// If we were to support caching protected buffers then we will need to switch the
// currently bound context if we are not already using the protected context (and subsequently
@@ -441,7 +440,7 @@
}
void SkiaRenderEngine::unmapExternalTextureBuffer(sp<GraphicBuffer>&& buffer) {
- ATRACE_CALL();
+ SFTRACE_CALL();
std::lock_guard<std::mutex> lock(mRenderingMutex);
if (const auto& iter = mGraphicBufferExternalRefs.find(buffer->getId());
iter != mGraphicBufferExternalRefs.end()) {
@@ -498,7 +497,7 @@
}
void SkiaRenderEngine::cleanupPostRender() {
- ATRACE_CALL();
+ SFTRACE_CALL();
std::lock_guard<std::mutex> lock(mRenderingMutex);
mTextureCleanupMgr.cleanup();
}
@@ -696,7 +695,7 @@
const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
const DisplaySettings& display, const std::vector<LayerSettings>& layers,
const std::shared_ptr<ExternalTexture>& buffer, base::unique_fd&& bufferFence) {
- ATRACE_FORMAT("%s for %s", __func__, display.namePlusId.c_str());
+ SFTRACE_FORMAT("%s for %s", __func__, display.namePlusId.c_str());
std::lock_guard<std::mutex> lock(mRenderingMutex);
@@ -788,7 +787,7 @@
logSettings(display);
}
for (const auto& layer : layers) {
- ATRACE_FORMAT("DrawLayer: %s", layer.name.c_str());
+ SFTRACE_FORMAT("DrawLayer: %s", layer.name.c_str());
if (kPrintLayerSettings) {
logSettings(layer);
@@ -882,7 +881,7 @@
// TODO(b/182216890): Filter out empty layers earlier
if (blurRect.width() > 0 && blurRect.height() > 0) {
if (layer.backgroundBlurRadius > 0) {
- ATRACE_NAME("BackgroundBlur");
+ SFTRACE_NAME("BackgroundBlur");
auto blurredImage = mBlurFilter->generate(context, layer.backgroundBlurRadius,
blurInput, blurRect);
@@ -895,7 +894,7 @@
canvas->concat(getSkM44(layer.blurRegionTransform).asM33());
for (auto region : layer.blurRegions) {
if (cachedBlurs[region.blurRadius] == nullptr) {
- ATRACE_NAME("BlurRegion");
+ SFTRACE_NAME("BlurRegion");
cachedBlurs[region.blurRadius] =
mBlurFilter->generate(context, region.blurRadius, blurInput,
blurRect);
@@ -978,7 +977,7 @@
SkPaint paint;
if (layer.source.buffer.buffer) {
- ATRACE_NAME("DrawImage");
+ SFTRACE_NAME("DrawImage");
validateInputBufferUsage(layer.source.buffer.buffer->getBuffer());
const auto& item = layer.source.buffer;
auto imageTextureRef = getOrCreateBackendTexture(item.buffer->getBuffer(), false);
@@ -1111,7 +1110,7 @@
paint.setColorFilter(SkColorFilters::Matrix(colorMatrix));
}
} else {
- ATRACE_NAME("DrawColor");
+ SFTRACE_NAME("DrawColor");
const auto color = layer.source.solidColor;
sk_sp<SkShader> shader = SkShaders::Color(SkColor4f{.fR = color.r,
.fG = color.g,
@@ -1168,7 +1167,7 @@
canvas->drawRect(bounds.rect(), paint);
}
if (kGaneshFlushAfterEveryLayer) {
- ATRACE_NAME("flush surface");
+ SFTRACE_NAME("flush surface");
// No-op in Graphite. If "flushing" Skia's drawing commands after each layer is desired
// in Graphite, then a graphite::Recording would need to be snapped and tracked for each
// layer, which is likely possible but adds non-trivial complexity (in both bookkeeping
@@ -1183,7 +1182,7 @@
LOG_ALWAYS_FATAL_IF(activeSurface != dstSurface);
auto drawFence = sp<Fence>::make(flushAndSubmit(context, dstSurface));
- if (ATRACE_ENABLED()) {
+ if (SFTRACE_ENABLED()) {
static gui::FenceMonitor sMonitor("RE Completion");
sMonitor.queueFence(drawFence);
}
@@ -1201,7 +1200,7 @@
void SkiaRenderEngine::drawShadow(SkCanvas* canvas,
const SkRRect& casterRRect,
const ShadowSettings& settings) {
- ATRACE_CALL();
+ SFTRACE_CALL();
const float casterZ = settings.length / 2.0f;
const auto flags =
settings.casterIsTranslucent ? kTransparentOccluder_ShadowFlag : kNone_ShadowFlag;
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index a1f917d..d89e818 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -32,9 +32,8 @@
#include <vk/GrVkTypes.h>
#include <android-base/stringprintf.h>
-#include <gui/TraceUtils.h>
+#include <common/trace.h>
#include <sync/sync.h>
-#include <utils/Trace.h>
#include <memory>
#include <string>
diff --git a/libs/renderengine/skia/compat/GaneshBackendTexture.cpp b/libs/renderengine/skia/compat/GaneshBackendTexture.cpp
index d246466..3fbc6ca 100644
--- a/libs/renderengine/skia/compat/GaneshBackendTexture.cpp
+++ b/libs/renderengine/skia/compat/GaneshBackendTexture.cpp
@@ -32,15 +32,15 @@
#include "skia/compat/SkiaBackendTexture.h"
#include <android/hardware_buffer.h>
+#include <common/trace.h>
#include <log/log_main.h>
-#include <utils/Trace.h>
namespace android::renderengine::skia {
GaneshBackendTexture::GaneshBackendTexture(sk_sp<GrDirectContext> grContext,
AHardwareBuffer* buffer, bool isOutputBuffer)
: SkiaBackendTexture(buffer, isOutputBuffer), mGrContext(grContext) {
- ATRACE_CALL();
+ SFTRACE_CALL();
AHardwareBuffer_Desc desc;
AHardwareBuffer_describe(buffer, &desc);
const bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
diff --git a/libs/renderengine/skia/compat/GraphiteBackendTexture.cpp b/libs/renderengine/skia/compat/GraphiteBackendTexture.cpp
index 3dd9ed2..a6e93ba 100644
--- a/libs/renderengine/skia/compat/GraphiteBackendTexture.cpp
+++ b/libs/renderengine/skia/compat/GraphiteBackendTexture.cpp
@@ -28,16 +28,16 @@
#include "skia/ColorSpaces.h"
#include <android/hardware_buffer.h>
+#include <common/trace.h>
#include <inttypes.h>
#include <log/log_main.h>
-#include <utils/Trace.h>
namespace android::renderengine::skia {
GraphiteBackendTexture::GraphiteBackendTexture(std::shared_ptr<skgpu::graphite::Recorder> recorder,
AHardwareBuffer* buffer, bool isOutputBuffer)
: SkiaBackendTexture(buffer, isOutputBuffer), mRecorder(std::move(recorder)) {
- ATRACE_CALL();
+ SFTRACE_CALL();
AHardwareBuffer_Desc desc;
AHardwareBuffer_describe(buffer, &desc);
const bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
diff --git a/libs/renderengine/skia/debug/CommonPool.cpp b/libs/renderengine/skia/debug/CommonPool.cpp
index bf15300..9d7c69b 100644
--- a/libs/renderengine/skia/debug/CommonPool.cpp
+++ b/libs/renderengine/skia/debug/CommonPool.cpp
@@ -20,8 +20,8 @@
#define LOG_TAG "RenderEngine"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <common/trace.h>
#include <sys/resource.h>
-#include <utils/Trace.h>
#include <system/thread_defs.h>
#include <array>
@@ -31,7 +31,7 @@
namespace skia {
CommonPool::CommonPool() {
- ATRACE_CALL();
+ SFTRACE_CALL();
CommonPool* pool = this;
// Create 2 workers
diff --git a/libs/renderengine/skia/debug/SkiaCapture.cpp b/libs/renderengine/skia/debug/SkiaCapture.cpp
index e778884..e6a0e22 100644
--- a/libs/renderengine/skia/debug/SkiaCapture.cpp
+++ b/libs/renderengine/skia/debug/SkiaCapture.cpp
@@ -22,9 +22,9 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
+#include <common/trace.h>
#include <log/log.h>
#include <renderengine/RenderEngine.h>
-#include <utils/Trace.h>
#include "CommonPool.h"
#include "SkCanvas.h"
@@ -48,7 +48,7 @@
}
SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) NO_THREAD_SAFETY_ANALYSIS {
- ATRACE_CALL();
+ SFTRACE_CALL();
// If we are not running yet, set up.
if (CC_LIKELY(!mCaptureRunning)) {
@@ -86,7 +86,7 @@
}
void SkiaCapture::endCapture() NO_THREAD_SAFETY_ANALYSIS {
- ATRACE_CALL();
+ SFTRACE_CALL();
// Don't end anything if we are not running.
if (CC_LIKELY(!mCaptureRunning)) {
return;
@@ -102,7 +102,7 @@
}
SkCanvas* SkiaCapture::tryOffscreenCapture(SkSurface* surface, OffscreenState* state) {
- ATRACE_CALL();
+ SFTRACE_CALL();
// Don't start anything if we are not running.
if (CC_LIKELY(!mCaptureRunning)) {
return surface->getCanvas();
@@ -122,7 +122,7 @@
}
uint64_t SkiaCapture::endOffscreenCapture(OffscreenState* state) {
- ATRACE_CALL();
+ SFTRACE_CALL();
// Don't end anything if we are not running.
if (CC_LIKELY(!mCaptureRunning)) {
return 0;
@@ -151,7 +151,7 @@
}
void SkiaCapture::writeToFile() {
- ATRACE_CALL();
+ SFTRACE_CALL();
// Pass mMultiPic and mOpenMultiPicStream to a background thread, which will
// handle the heavyweight serialization work and destroy them.
// mOpenMultiPicStream is released to a bare pointer because keeping it in
@@ -169,7 +169,7 @@
}
bool SkiaCapture::setupMultiFrameCapture() {
- ATRACE_CALL();
+ SFTRACE_CALL();
ALOGD("Set up multi-frame capture, ms = %llu", mTimerInterval.count());
base::SetProperty(PROPERTY_DEBUG_RENDERENGINE_CAPTURE_FILENAME, "");
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index 1e0c4cf..cd1bd71 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -25,8 +25,8 @@
#include <SkString.h>
#include <SkSurface.h>
#include <SkTileMode.h>
+#include <common/trace.h>
#include <log/log.h>
-#include <utils/Trace.h>
namespace android {
namespace renderengine {
@@ -79,7 +79,7 @@
const uint32_t blurRadius, const float blurAlpha,
const SkRect& blurRect, sk_sp<SkImage> blurredImage,
sk_sp<SkImage> input) {
- ATRACE_CALL();
+ SFTRACE_CALL();
SkPaint paint;
paint.setAlphaf(blurAlpha);
diff --git a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
index c9499cb..8c52c57 100644
--- a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
@@ -19,18 +19,18 @@
#include "GaussianBlurFilter.h"
#include <SkBlendMode.h>
#include <SkCanvas.h>
+#include <SkImageFilters.h>
#include <SkPaint.h>
#include <SkRRect.h>
#include <SkRuntimeEffect.h>
-#include <SkImageFilters.h>
#include <SkSize.h>
#include <SkString.h>
#include <SkSurface.h>
#include <SkTileMode.h>
+#include <common/trace.h>
#include <include/gpu/ganesh/SkSurfaceGanesh.h>
-#include "include/gpu/GpuTypes.h" // from Skia
#include <log/log.h>
-#include <utils/Trace.h>
+#include "include/gpu/GpuTypes.h" // from Skia
namespace android {
namespace renderengine {
diff --git a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
index 7a070d7..defaf6e 100644
--- a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
@@ -29,10 +29,10 @@
#include <SkString.h>
#include <SkSurface.h>
#include <SkTileMode.h>
+#include <common/trace.h>
#include <include/gpu/GpuTypes.h>
#include <include/gpu/ganesh/SkSurfaceGanesh.h>
#include <log/log.h>
-#include <utils/Trace.h>
namespace android {
namespace renderengine {
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index f7dcd3a..3bc3564 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -19,9 +19,9 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <SkString.h>
+#include <common/trace.h>
#include <log/log.h>
#include <shaders/shaders.h>
-#include <utils/Trace.h>
#include <math/mat4.h>
@@ -30,7 +30,7 @@
namespace skia {
sk_sp<SkRuntimeEffect> buildRuntimeEffect(const shaders::LinearEffect& linearEffect) {
- ATRACE_CALL();
+ SFTRACE_CALL();
SkString shaderString = SkString(shaders::buildLinearEffectSkSL(linearEffect));
auto [shader, error] = SkRuntimeEffect::MakeForShader(shaderString);
@@ -45,7 +45,7 @@
sk_sp<SkRuntimeEffect> runtimeEffect, const mat4& colorTransform, float maxDisplayLuminance,
float currentDisplayLuminanceNits, float maxLuminance, AHardwareBuffer* buffer,
aidl::android::hardware::graphics::composer3::RenderIntent renderIntent) {
- ATRACE_CALL();
+ SFTRACE_CALL();
SkRuntimeShaderBuilder effectBuilder(runtimeEffect);
effectBuilder.child("child") = shader;
diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp
index 0783714..7fbbf49 100644
--- a/libs/renderengine/tests/Android.bp
+++ b/libs/renderengine/tests/Android.bp
@@ -66,5 +66,6 @@
"libutils",
"server_configurable_flags",
"libaconfig_storage_read_api_cc",
+ "libtracing_perfetto",
],
}
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index d27c151..f5a90fd 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -23,9 +23,9 @@
#include <future>
#include <android-base/stringprintf.h>
+#include <common/trace.h>
#include <private/gui/SyncFeatures.h>
#include <processgroup/processgroup.h>
-#include <utils/Trace.h>
using namespace std::chrono_literals;
@@ -39,7 +39,7 @@
RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory)
: RenderEngine(Threaded::YES) {
- ATRACE_CALL();
+ SFTRACE_CALL();
std::lock_guard lockThread(mThreadMutex);
mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory);
@@ -76,7 +76,7 @@
// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
- ATRACE_CALL();
+ SFTRACE_CALL();
if (!SetTaskProfiles(0, {"SFRenderEnginePolicy"})) {
ALOGW("Failed to set render-engine task profile!");
@@ -133,13 +133,13 @@
std::future<void> RenderEngineThreaded::primeCache(PrimeCacheConfig config) {
const auto resultPromise = std::make_shared<std::promise<void>>();
std::future<void> resultFuture = resultPromise->get_future();
- ATRACE_CALL();
+ SFTRACE_CALL();
// This function is designed so it can run asynchronously, so we do not need to wait
// for the futures.
{
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push([resultPromise, config](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::primeCache");
+ SFTRACE_NAME("REThreaded::primeCache");
if (setSchedFifo(false) != NO_ERROR) {
ALOGW("Couldn't set SCHED_OTHER for primeCache");
}
@@ -163,7 +163,7 @@
{
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::dump");
+ SFTRACE_NAME("REThreaded::dump");
std::string localResult = result;
instance.dump(localResult);
resultPromise.set_value(std::move(localResult));
@@ -176,13 +176,13 @@
void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
bool isRenderable) {
- ATRACE_CALL();
+ SFTRACE_CALL();
// This function is designed so it can run asynchronously, so we do not need to wait
// for the futures.
{
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
+ SFTRACE_NAME("REThreaded::mapExternalTextureBuffer");
instance.mapExternalTextureBuffer(buffer, isRenderable);
});
}
@@ -190,14 +190,14 @@
}
void RenderEngineThreaded::unmapExternalTextureBuffer(sp<GraphicBuffer>&& buffer) {
- ATRACE_CALL();
+ SFTRACE_CALL();
// This function is designed so it can run asynchronously, so we do not need to wait
// for the futures.
{
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push(
[=, buffer = std::move(buffer)](renderengine::RenderEngine& instance) mutable {
- ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
+ SFTRACE_NAME("REThreaded::unmapExternalTextureBuffer");
instance.unmapExternalTextureBuffer(std::move(buffer));
});
}
@@ -229,7 +229,7 @@
{
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::cleanupPostRender");
+ SFTRACE_NAME("REThreaded::cleanupPostRender");
instance.cleanupPostRender();
});
mNeedsPostRenderCleanup = false;
@@ -252,7 +252,7 @@
ftl::Future<FenceResult> RenderEngineThreaded::drawLayers(
const DisplaySettings& display, const std::vector<LayerSettings>& layers,
const std::shared_ptr<ExternalTexture>& buffer, base::unique_fd&& bufferFence) {
- ATRACE_CALL();
+ SFTRACE_CALL();
const auto resultPromise = std::make_shared<std::promise<FenceResult>>();
std::future<FenceResult> resultFuture = resultPromise->get_future();
int fd = bufferFence.release();
@@ -261,7 +261,7 @@
mNeedsPostRenderCleanup = true;
mFunctionCalls.push(
[resultPromise, display, layers, buffer, fd](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::drawLayers");
+ SFTRACE_NAME("REThreaded::drawLayers");
instance.updateProtectedContext(layers, buffer);
instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer,
base::unique_fd(fd));
@@ -277,7 +277,7 @@
{
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::getContextPriority");
+ SFTRACE_NAME("REThreaded::getContextPriority");
int priority = instance.getContextPriority();
resultPromise.set_value(priority);
});
@@ -297,7 +297,7 @@
{
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::onActiveDisplaySizeChanged");
+ SFTRACE_NAME("REThreaded::onActiveDisplaySizeChanged");
instance.onActiveDisplaySizeChanged(size);
});
}
@@ -324,7 +324,7 @@
{
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push([tracingEnabled](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::setEnableTracing");
+ SFTRACE_NAME("REThreaded::setEnableTracing");
instance.setEnableTracing(tracingEnabled);
});
}
diff --git a/services/inputflinger/InputDeviceMetricsCollector.cpp b/services/inputflinger/InputDeviceMetricsCollector.cpp
index b5cb3cb..4621144 100644
--- a/services/inputflinger/InputDeviceMetricsCollector.cpp
+++ b/services/inputflinger/InputDeviceMetricsCollector.cpp
@@ -133,15 +133,6 @@
mNextListener.notify(args);
}
-void InputDeviceMetricsCollector::notifyConfigurationChanged(
- const NotifyConfigurationChangedArgs& args) {
- {
- std::scoped_lock lock(mLock);
- reportCompletedSessions();
- }
- mNextListener.notify(args);
-}
-
void InputDeviceMetricsCollector::notifyKey(const NotifyKeyArgs& args) {
{
std::scoped_lock lock(mLock);
diff --git a/services/inputflinger/InputDeviceMetricsCollector.h b/services/inputflinger/InputDeviceMetricsCollector.h
index 1bcd527..0a520e6 100644
--- a/services/inputflinger/InputDeviceMetricsCollector.h
+++ b/services/inputflinger/InputDeviceMetricsCollector.h
@@ -107,7 +107,6 @@
std::chrono::nanoseconds usageSessionTimeout);
void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
void notifyKey(const NotifyKeyArgs& args) override;
void notifyMotion(const NotifyMotionArgs& args) override;
void notifySwitch(const NotifySwitchArgs& args) override;
diff --git a/services/inputflinger/InputFilter.cpp b/services/inputflinger/InputFilter.cpp
index 8e73ce5..e4d73fc 100644
--- a/services/inputflinger/InputFilter.cpp
+++ b/services/inputflinger/InputFilter.cpp
@@ -67,10 +67,6 @@
mNextListener.notify(args);
}
-void InputFilter::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
- mNextListener.notify(args);
-}
-
void InputFilter::notifyKey(const NotifyKeyArgs& args) {
if (isFilterEnabled()) {
LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyKey(notifyKeyArgsToKeyEvent(args)).isOk());
diff --git a/services/inputflinger/InputFilter.h b/services/inputflinger/InputFilter.h
index 4ddc9f4..f626703 100644
--- a/services/inputflinger/InputFilter.h
+++ b/services/inputflinger/InputFilter.h
@@ -53,7 +53,6 @@
InputFilterPolicyInterface& policy);
~InputFilter() override = default;
void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
void notifyKey(const NotifyKeyArgs& args) override;
void notifyMotion(const NotifyMotionArgs& args) override;
void notifySwitch(const NotifySwitchArgs& args) override;
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index 016ae04..8b6accf 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -47,7 +47,6 @@
void InputListenerInterface::notify(const NotifyArgs& generalArgs) {
Visitor v{
[&](const NotifyInputDevicesChangedArgs& args) { notifyInputDevicesChanged(args); },
- [&](const NotifyConfigurationChangedArgs& args) { notifyConfigurationChanged(args); },
[&](const NotifyKeyArgs& args) { notifyKey(args); },
[&](const NotifyMotionArgs& args) { notifyMotion(args); },
[&](const NotifySwitchArgs& args) { notifySwitch(args); },
@@ -68,10 +67,6 @@
mArgsQueue.emplace_back(args);
}
-void QueuedInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
- mArgsQueue.emplace_back(args);
-}
-
void QueuedInputListener::notifyKey(const NotifyKeyArgs& args) {
mArgsQueue.emplace_back(args);
}
@@ -119,13 +114,6 @@
mInnerListener.notify(args);
}
-void TracedInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
- constexpr static auto& fnName = __func__;
- ATRACE_NAME_IF(ATRACE_ENABLED(),
- StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id));
- mInnerListener.notify(args);
-}
-
void TracedInputListener::notifyKey(const NotifyKeyArgs& args) {
constexpr static auto& fnName = __func__;
ATRACE_NAME_IF(ATRACE_ENABLED(),
diff --git a/services/inputflinger/InputProcessor.cpp b/services/inputflinger/InputProcessor.cpp
index 6dd267c..8b8b1ad 100644
--- a/services/inputflinger/InputProcessor.cpp
+++ b/services/inputflinger/InputProcessor.cpp
@@ -419,12 +419,6 @@
mQueuedListener.flush();
}
-void InputProcessor::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
- // pass through
- mQueuedListener.notifyConfigurationChanged(args);
- mQueuedListener.flush();
-}
-
void InputProcessor::notifyKey(const NotifyKeyArgs& args) {
// pass through
mQueuedListener.notifyKey(args);
diff --git a/services/inputflinger/InputProcessor.h b/services/inputflinger/InputProcessor.h
index 7a00a2d..2945dd2 100644
--- a/services/inputflinger/InputProcessor.h
+++ b/services/inputflinger/InputProcessor.h
@@ -246,7 +246,6 @@
explicit InputProcessor(InputListenerInterface& listener);
void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
void notifyKey(const NotifyKeyArgs& args) override;
void notifyMotion(const NotifyMotionArgs& args) override;
void notifySwitch(const NotifySwitchArgs& args) override;
diff --git a/services/inputflinger/NotifyArgs.cpp b/services/inputflinger/NotifyArgs.cpp
index 19a4f26..b2680a2 100644
--- a/services/inputflinger/NotifyArgs.cpp
+++ b/services/inputflinger/NotifyArgs.cpp
@@ -35,11 +35,6 @@
std::vector<InputDeviceInfo> infos)
: id(id), inputDeviceInfos(std::move(infos)) {}
-// --- NotifyConfigurationChangedArgs ---
-
-NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(int32_t id, nsecs_t eventTime)
- : id(id), eventTime(eventTime) {}
-
// --- NotifyKeyArgs ---
NotifyKeyArgs::NotifyKeyArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId,
@@ -198,7 +193,6 @@
const char* toString(const NotifyArgs& args) {
Visitor toStringVisitor{
[&](const NotifyInputDevicesChangedArgs&) { return "NotifyInputDevicesChangedArgs"; },
- [&](const NotifyConfigurationChangedArgs&) { return "NotifyConfigurationChangedArgs"; },
[&](const NotifyKeyArgs&) { return "NotifyKeyArgs"; },
[&](const NotifyMotionArgs&) { return "NotifyMotionArgs"; },
[&](const NotifySensorArgs&) { return "NotifySensorArgs"; },
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 31fbb51..625599a 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -165,10 +165,6 @@
mNextListener.notify(args);
}
-void PointerChoreographer::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
- mNextListener.notify(args);
-}
-
void PointerChoreographer::notifyKey(const NotifyKeyArgs& args) {
fadeMouseCursorOnKeyPress(args);
mNextListener.notify(args);
@@ -368,7 +364,8 @@
const uint8_t actionIndex = MotionEvent::getActionIndex(args.action);
std::array<uint32_t, MAX_POINTER_ID + 1> idToIndex;
BitSet32 idBits;
- if (maskedAction != AMOTION_EVENT_ACTION_UP && maskedAction != AMOTION_EVENT_ACTION_CANCEL) {
+ if (maskedAction != AMOTION_EVENT_ACTION_UP && maskedAction != AMOTION_EVENT_ACTION_CANCEL &&
+ maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT) {
for (size_t i = 0; i < args.getPointerCount(); i++) {
if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP && actionIndex == i) {
continue;
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index aaf1e3e..635487b 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -105,7 +105,6 @@
void setFocusedDisplay(ui::LogicalDisplayId displayId) override;
void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
void notifyKey(const NotifyKeyArgs& args) override;
void notifyMotion(const NotifyMotionArgs& args) override;
void notifySwitch(const NotifySwitchArgs& args) override;
diff --git a/services/inputflinger/UnwantedInteractionBlocker.cpp b/services/inputflinger/UnwantedInteractionBlocker.cpp
index 1e2b9b3a..0e9ec91 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.cpp
+++ b/services/inputflinger/UnwantedInteractionBlocker.cpp
@@ -342,12 +342,6 @@
bool enablePalmRejection)
: mQueuedListener(listener), mEnablePalmRejection(enablePalmRejection) {}
-void UnwantedInteractionBlocker::notifyConfigurationChanged(
- const NotifyConfigurationChangedArgs& args) {
- mQueuedListener.notifyConfigurationChanged(args);
- mQueuedListener.flush();
-}
-
void UnwantedInteractionBlocker::notifyKey(const NotifyKeyArgs& args) {
mQueuedListener.notifyKey(args);
mQueuedListener.flush();
diff --git a/services/inputflinger/UnwantedInteractionBlocker.h b/services/inputflinger/UnwantedInteractionBlocker.h
index 419da83..8a66e25 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.h
+++ b/services/inputflinger/UnwantedInteractionBlocker.h
@@ -91,7 +91,6 @@
explicit UnwantedInteractionBlocker(InputListenerInterface& listener, bool enablePalmRejection);
void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
void notifyKey(const NotifyKeyArgs& args) override;
void notifyMotion(const NotifyMotionArgs& args) override;
void notifySwitch(const NotifySwitchArgs& args) override;
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index ad9cec1..ff407af 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -68,15 +68,6 @@
injectionState(nullptr),
dispatchInProgress(false) {}
-// --- ConfigurationChangedEntry ---
-
-ConfigurationChangedEntry::ConfigurationChangedEntry(int32_t id, nsecs_t eventTime)
- : EventEntry(id, Type::CONFIGURATION_CHANGED, eventTime, 0) {}
-
-std::string ConfigurationChangedEntry::getDescription() const {
- return StringPrintf("ConfigurationChangedEvent(), policyFlags=0x%08x", policyFlags);
-}
-
// --- DeviceResetEntry ---
DeviceResetEntry::DeviceResetEntry(int32_t id, nsecs_t eventTime, int32_t deviceId)
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index f2f31d8..becfb05 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -32,7 +32,6 @@
struct EventEntry {
enum class Type {
- CONFIGURATION_CHANGED,
DEVICE_RESET,
FOCUS,
KEY,
@@ -78,11 +77,6 @@
virtual ~EventEntry() = default;
};
-struct ConfigurationChangedEntry : EventEntry {
- explicit ConfigurationChangedEntry(int32_t id, nsecs_t eventTime);
- std::string getDescription() const override;
-};
-
struct DeviceResetEntry : EventEntry {
int32_t deviceId;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6c4870f..4076817 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -558,7 +558,6 @@
// Returns true if the event type passed as argument represents a user activity.
bool isUserActivityEvent(const EventEntry& eventEntry) {
switch (eventEntry.type) {
- case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET:
case EventEntry::Type::DRAG:
case EventEntry::Type::FOCUS:
@@ -901,6 +900,24 @@
const nsecs_t mProcessingTimestamp;
};
+/**
+ * This is needed to help use "InputEventInjectionResult" with base::Result.
+ */
+template <typename T>
+struct EnumErrorWrapper {
+ T mVal;
+ EnumErrorWrapper(T&& e) : mVal(std::forward<T>(e)) {}
+ operator const T&() const { return mVal; }
+ T value() const { return mVal; }
+ std::string print() const { return ftl::enum_string(mVal); }
+};
+
+Error<EnumErrorWrapper<InputEventInjectionResult>> injectionError(InputEventInjectionResult&& e) {
+ LOG_ALWAYS_FATAL_IF(e == InputEventInjectionResult::SUCCEEDED);
+ return Error<EnumErrorWrapper<InputEventInjectionResult>>(
+ std::forward<InputEventInjectionResult>(e));
+}
+
} // namespace
// --- InputDispatcher ---
@@ -1153,14 +1170,6 @@
}
switch (mPendingEvent->type) {
- case EventEntry::Type::CONFIGURATION_CHANGED: {
- const ConfigurationChangedEntry& typedEntry =
- static_cast<const ConfigurationChangedEntry&>(*mPendingEvent);
- done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
- dropReason = DropReason::NOT_DROPPED; // configuration changes are never dropped
- break;
- }
-
case EventEntry::Type::DEVICE_RESET: {
const DeviceResetEntry& typedEntry =
static_cast<const DeviceResetEntry&>(*mPendingEvent);
@@ -1392,7 +1401,6 @@
break;
}
case EventEntry::Type::TOUCH_MODE_CHANGED:
- case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET:
case EventEntry::Type::SENSOR:
case EventEntry::Type::POINTER_CAPTURE_CHANGED:
@@ -1566,7 +1574,6 @@
}
case EventEntry::Type::FOCUS:
case EventEntry::Type::TOUCH_MODE_CHANGED:
- case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET: {
LOG_ALWAYS_FATAL("Should not drop %s events", ftl::enum_string(entry.type).c_str());
break;
@@ -1655,18 +1662,6 @@
return newEntry;
}
-bool InputDispatcher::dispatchConfigurationChangedLocked(nsecs_t currentTime,
- const ConfigurationChangedEntry& entry) {
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("dispatchConfigurationChanged - eventTime=%" PRId64, entry.eventTime);
- }
-
- // Reset key repeating in case a keyboard device was added or removed or something.
- resetKeyRepeatLocked();
-
- return true;
-}
-
bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime,
const DeviceResetEntry& entry) {
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
@@ -1929,20 +1924,21 @@
}
// Identify targets.
- InputEventInjectionResult injectionResult;
- sp<WindowInfoHandle> focusedWindow =
- findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime,
- /*byref*/ injectionResult);
- if (injectionResult == InputEventInjectionResult::PENDING) {
- return false;
- }
+ Result<sp<WindowInfoHandle>, InputEventInjectionResult> result =
+ findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime);
- setInjectionResult(*entry, injectionResult);
- if (injectionResult != InputEventInjectionResult::SUCCEEDED) {
+ if (!result.ok()) {
+ if (result.error().code() == InputEventInjectionResult::PENDING) {
+ return false;
+ }
+ setInjectionResult(*entry, result.error().code());
return true;
}
+ sp<WindowInfoHandle>& focusedWindow = *result;
LOG_ALWAYS_FATAL_IF(focusedWindow == nullptr);
+ setInjectionResult(*entry, InputEventInjectionResult::SUCCEEDED);
+
std::vector<InputTarget> inputTargets;
addWindowTargetLocked(focusedWindow, InputTarget::DispatchMode::AS_IS,
InputTarget::Flags::FOREGROUND, getDownTime(*entry), inputTargets);
@@ -2047,19 +2043,28 @@
pilferPointersLocked(mDragState->dragWindow->getToken());
}
- inputTargets =
- findTouchedWindowTargetsLocked(currentTime, *entry, /*byref*/ injectionResult);
- LOG_ALWAYS_FATAL_IF(injectionResult != InputEventInjectionResult::SUCCEEDED &&
- !inputTargets.empty());
+ Result<std::vector<InputTarget>, InputEventInjectionResult> result =
+ findTouchedWindowTargetsLocked(currentTime, *entry);
+
+ if (result.ok()) {
+ inputTargets = std::move(*result);
+ injectionResult = InputEventInjectionResult::SUCCEEDED;
+ } else {
+ injectionResult = result.error().code();
+ }
} else {
// Non touch event. (eg. trackball)
- sp<WindowInfoHandle> focusedWindow =
- findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime, injectionResult);
- if (injectionResult == InputEventInjectionResult::SUCCEEDED) {
+ Result<sp<WindowInfoHandle>, InputEventInjectionResult> result =
+ findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime);
+ if (result.ok()) {
+ sp<WindowInfoHandle>& focusedWindow = *result;
LOG_ALWAYS_FATAL_IF(focusedWindow == nullptr);
addWindowTargetLocked(focusedWindow, InputTarget::DispatchMode::AS_IS,
InputTarget::Flags::FOREGROUND, getDownTime(*entry),
inputTargets);
+ injectionResult = InputEventInjectionResult::SUCCEEDED;
+ } else {
+ injectionResult = result.error().code();
}
}
if (injectionResult == InputEventInjectionResult::PENDING) {
@@ -2224,7 +2229,6 @@
case EventEntry::Type::TOUCH_MODE_CHANGED:
case EventEntry::Type::POINTER_CAPTURE_CHANGED:
case EventEntry::Type::FOCUS:
- case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET:
case EventEntry::Type::SENSOR:
case EventEntry::Type::DRAG: {
@@ -2266,11 +2270,9 @@
return false;
}
-sp<WindowInfoHandle> InputDispatcher::findFocusedWindowTargetLocked(
- nsecs_t currentTime, const EventEntry& entry, nsecs_t& nextWakeupTime,
- InputEventInjectionResult& outInjectionResult) {
- outInjectionResult = InputEventInjectionResult::FAILED; // Default result
-
+Result<sp<WindowInfoHandle>, InputEventInjectionResult>
+InputDispatcher::findFocusedWindowTargetLocked(nsecs_t currentTime, const EventEntry& entry,
+ nsecs_t& nextWakeupTime) {
ui::LogicalDisplayId displayId = getTargetDisplayId(entry);
sp<WindowInfoHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId);
std::shared_ptr<InputApplicationHandle> focusedApplicationHandle =
@@ -2282,12 +2284,12 @@
ALOGI("Dropping %s event because there is no focused window or focused application in "
"display %s.",
ftl::enum_string(entry.type).c_str(), displayId.toString().c_str());
- return nullptr;
+ return injectionError(InputEventInjectionResult::FAILED);
}
// Drop key events if requested by input feature
if (focusedWindowHandle != nullptr && shouldDropInput(entry, focusedWindowHandle)) {
- return nullptr;
+ return injectionError(InputEventInjectionResult::FAILED);
}
// Compatibility behavior: raise ANR if there is a focused application, but no focused window.
@@ -2307,17 +2309,15 @@
"window when it finishes starting up. Will wait for %" PRId64 "ms",
mAwaitedFocusedApplication->getName().c_str(), millis(timeout));
nextWakeupTime = std::min(nextWakeupTime, *mNoFocusedWindowTimeoutTime);
- outInjectionResult = InputEventInjectionResult::PENDING;
- return nullptr;
+ return injectionError(InputEventInjectionResult::PENDING);
} else if (currentTime > *mNoFocusedWindowTimeoutTime) {
// Already raised ANR. Drop the event
ALOGE("Dropping %s event because there is no focused window",
ftl::enum_string(entry.type).c_str());
- return nullptr;
+ return injectionError(InputEventInjectionResult::FAILED);
} else {
// Still waiting for the focused window
- outInjectionResult = InputEventInjectionResult::PENDING;
- return nullptr;
+ return injectionError(InputEventInjectionResult::PENDING);
}
}
@@ -2327,15 +2327,13 @@
// Verify targeted injection.
if (const auto err = verifyTargetedInjection(focusedWindowHandle, entry); err) {
ALOGW("Dropping injected event: %s", (*err).c_str());
- outInjectionResult = InputEventInjectionResult::TARGET_MISMATCH;
- return nullptr;
+ return injectionError(InputEventInjectionResult::TARGET_MISMATCH);
}
if (focusedWindowHandle->getInfo()->inputConfig.test(
WindowInfo::InputConfig::PAUSE_DISPATCHING)) {
ALOGI("Waiting because %s is paused", focusedWindowHandle->getName().c_str());
- outInjectionResult = InputEventInjectionResult::PENDING;
- return nullptr;
+ return injectionError(InputEventInjectionResult::PENDING);
}
// If the event is a key event, then we must wait for all previous events to
@@ -2352,12 +2350,10 @@
if (entry.type == EventEntry::Type::KEY) {
if (shouldWaitToSendKeyLocked(currentTime, focusedWindowHandle->getName().c_str())) {
nextWakeupTime = std::min(nextWakeupTime, *mKeyIsWaitingForEventsTimeout);
- outInjectionResult = InputEventInjectionResult::PENDING;
- return nullptr;
+ return injectionError(InputEventInjectionResult::PENDING);
}
}
-
- outInjectionResult = InputEventInjectionResult::SUCCEEDED;
+ // Success!
return focusedWindowHandle;
}
@@ -2381,9 +2377,8 @@
return responsiveMonitors;
}
-std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
- nsecs_t currentTime, const MotionEntry& entry,
- InputEventInjectionResult& outInjectionResult) {
+base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
+InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) {
ATRACE_CALL();
std::vector<InputTarget> targets;
@@ -2393,9 +2388,6 @@
const int32_t action = entry.action;
const int32_t maskedAction = MotionEvent::getActionMasked(action);
- // Update the touch state as needed based on the properties of the touch event.
- outInjectionResult = InputEventInjectionResult::PENDING;
-
// Copy current touch state into tempTouchState.
// This state will be used to update mTouchStatesByDisplay at the end of this function.
// If no state for the specified display exists, then our initial state will be empty.
@@ -2435,8 +2427,7 @@
// Started hovering, but the device is already down: reject the hover event
LOG(ERROR) << "Got hover event " << entry.getDescription()
<< " but the device is already down " << oldState->dump();
- outInjectionResult = InputEventInjectionResult::FAILED;
- return {};
+ return injectionError(InputEventInjectionResult::FAILED);
}
// For hover actions, we will treat 'tempTouchState' as a new state, so let's erase
// all of the existing hovering pointers and recompute.
@@ -2468,9 +2459,7 @@
// Verify targeted injection.
if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
ALOGW("Dropping injected touch event: %s", (*err).c_str());
- outInjectionResult = os::InputEventInjectionResult::TARGET_MISMATCH;
- newTouchedWindowHandle = nullptr;
- return {};
+ return injectionError(InputEventInjectionResult::TARGET_MISMATCH);
}
// Figure out whether splitting will be allowed for this window.
@@ -2502,8 +2491,7 @@
if (newTouchedWindows.empty()) {
LOG(INFO) << "Dropping event because there is no touchable window at (" << x << ", "
<< y << ") on display " << displayId << ": " << entry;
- outInjectionResult = InputEventInjectionResult::FAILED;
- return {};
+ return injectionError(InputEventInjectionResult::FAILED);
}
for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) {
@@ -2603,8 +2591,7 @@
<< " is not down or we previously dropped the pointer down event in "
<< "display " << displayId << ": " << entry.getDescription();
}
- outInjectionResult = InputEventInjectionResult::FAILED;
- return {};
+ return injectionError(InputEventInjectionResult::FAILED);
}
// If the pointer is not currently hovering, then ignore the event.
@@ -2615,8 +2602,7 @@
LOG(INFO) << "Dropping event because the hovering pointer is not in any windows in "
"display "
<< displayId << ": " << entry.getDescription();
- outInjectionResult = InputEventInjectionResult::FAILED;
- return {};
+ return injectionError(InputEventInjectionResult::FAILED);
}
tempTouchState.removeHoveringPointer(entry.deviceId, pointerId);
}
@@ -2637,8 +2623,7 @@
// Verify targeted injection.
if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
ALOGW("Dropping injected event: %s", (*err).c_str());
- outInjectionResult = os::InputEventInjectionResult::TARGET_MISMATCH;
- return {};
+ return injectionError(InputEventInjectionResult::TARGET_MISMATCH);
}
// Do not slide events to the window which can not receive motion event
@@ -2707,6 +2692,9 @@
if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
continue;
}
+ if (!touchedWindow.hasTouchingPointers(entry.deviceId)) {
+ continue;
+ }
touchedWindow.addTouchingPointers(entry.deviceId, touchingPointers);
}
}
@@ -2738,8 +2726,7 @@
ALOGW("Dropping targeted injection: At least one touched window is not owned by uid "
"%s:%s",
entry.injectionState->targetUid->toString().c_str(), errs.c_str());
- outInjectionResult = InputEventInjectionResult::TARGET_MISMATCH;
- return {};
+ return injectionError(InputEventInjectionResult::TARGET_MISMATCH);
}
}
@@ -2796,8 +2783,7 @@
if (targets.empty()) {
LOG(INFO) << "Dropping event because no targets were found: " << entry.getDescription();
- outInjectionResult = InputEventInjectionResult::FAILED;
- return {};
+ return injectionError(InputEventInjectionResult::FAILED);
}
// If we only have windows getting ACTION_OUTSIDE, then drop the event, because there is no
@@ -2807,12 +2793,9 @@
})) {
LOG(INFO) << "Dropping event because all windows would just receive ACTION_OUTSIDE: "
<< entry.getDescription();
- outInjectionResult = InputEventInjectionResult::FAILED;
- return {};
+ return injectionError(InputEventInjectionResult::FAILED);
}
- outInjectionResult = InputEventInjectionResult::SUCCEEDED;
-
// Now that we have generated all of the input targets for this event, reset the dispatch
// mode for all touched window to AS_IS.
for (TouchedWindow& touchedWindow : tempTouchState.windows) {
@@ -3620,7 +3603,6 @@
LOG_ALWAYS_FATAL("SENSOR events should not go to apps via input channel");
break;
}
- case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET: {
LOG_ALWAYS_FATAL("%s events should not go to apps",
ftl::enum_string(eventEntry->type).c_str());
@@ -3881,7 +3863,6 @@
break;
}
- case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET:
case EventEntry::Type::SENSOR: {
LOG_ALWAYS_FATAL("Should never start dispatch cycles for %s events",
@@ -4277,7 +4258,6 @@
ftl::enum_string(cancelationEventEntry->type).c_str());
break;
}
- case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET:
case EventEntry::Type::SENSOR: {
LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue",
@@ -4360,7 +4340,6 @@
case EventEntry::Type::KEY:
case EventEntry::Type::FOCUS:
case EventEntry::Type::TOUCH_MODE_CHANGED:
- case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET:
case EventEntry::Type::POINTER_CAPTURE_CHANGED:
case EventEntry::Type::SENSOR:
@@ -4446,28 +4425,11 @@
void InputDispatcher::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
std::scoped_lock _l(mLock);
+ // Reset key repeating in case a keyboard device was added or removed or something.
+ resetKeyRepeatLocked();
mLatencyTracker.setInputDevices(args.inputDeviceInfos);
}
-void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
- if (debugInboundEventDetails()) {
- ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args.eventTime);
- }
-
- bool needWake = false;
- { // acquire lock
- std::scoped_lock _l(mLock);
-
- std::unique_ptr<ConfigurationChangedEntry> newEntry =
- std::make_unique<ConfigurationChangedEntry>(args.id, args.eventTime);
- needWake = enqueueInboundEventLocked(std::move(newEntry));
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
void InputDispatcher::notifyKey(const NotifyKeyArgs& args) {
ALOGD_IF(debugInboundEventDetails(),
"notifyKey - id=%" PRIx32 ", eventTime=%" PRId64
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 2125226..698bdba 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -97,7 +97,6 @@
status_t stop() override;
void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
void notifyKey(const NotifyKeyArgs& args) override;
void notifyMotion(const NotifyMotionArgs& args) override;
void notifySwitch(const NotifySwitchArgs& args) override;
@@ -447,8 +446,6 @@
REQUIRES(mLock);
// Dispatch inbound events.
- bool dispatchConfigurationChangedLocked(nsecs_t currentTime,
- const ConfigurationChangedEntry& entry) REQUIRES(mLock);
bool dispatchDeviceResetLocked(nsecs_t currentTime, const DeviceResetEntry& entry)
REQUIRES(mLock);
bool dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<const KeyEntry> entry,
@@ -537,12 +534,11 @@
void resetNoFocusedWindowTimeoutLocked() REQUIRES(mLock);
ui::LogicalDisplayId getTargetDisplayId(const EventEntry& entry);
- sp<android::gui::WindowInfoHandle> findFocusedWindowTargetLocked(
- nsecs_t currentTime, const EventEntry& entry, nsecs_t& nextWakeupTime,
- android::os::InputEventInjectionResult& outInjectionResult) REQUIRES(mLock);
- std::vector<InputTarget> findTouchedWindowTargetsLocked(
- nsecs_t currentTime, const MotionEntry& entry,
- android::os::InputEventInjectionResult& outInjectionResult) REQUIRES(mLock);
+ base::Result<sp<android::gui::WindowInfoHandle>, android::os::InputEventInjectionResult>
+ findFocusedWindowTargetLocked(nsecs_t currentTime, const EventEntry& entry,
+ nsecs_t& nextWakeupTime) REQUIRES(mLock);
+ base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
+ findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) REQUIRES(mLock);
std::vector<Monitor> selectResponsiveMonitorsLocked(
const std::vector<Monitor>& gestureMonitors) const REQUIRES(mLock);
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index 0b7f7c2..d8a9afa 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -38,7 +38,6 @@
virtual ~InputListenerInterface() { }
virtual void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) = 0;
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) = 0;
virtual void notifyKey(const NotifyKeyArgs& args) = 0;
virtual void notifyMotion(const NotifyMotionArgs& args) = 0;
virtual void notifySwitch(const NotifySwitchArgs& args) = 0;
@@ -60,7 +59,6 @@
explicit QueuedInputListener(InputListenerInterface& innerListener);
virtual void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
virtual void notifyKey(const NotifyKeyArgs& args) override;
virtual void notifyMotion(const NotifyMotionArgs& args) override;
virtual void notifySwitch(const NotifySwitchArgs& args) override;
@@ -84,7 +82,6 @@
explicit TracedInputListener(const char* name, InputListenerInterface& innerListener);
virtual void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
virtual void notifyKey(const NotifyKeyArgs& args) override;
virtual void notifyMotion(const NotifyMotionArgs& args) override;
virtual void notifySwitch(const NotifySwitchArgs& args) override;
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 35519d1..42a03c1 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -454,9 +454,6 @@
*/
virtual void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) = 0;
- /* Notifies the system that a configuration change has occurred. */
- virtual void notifyConfigurationChanged(nsecs_t when) = 0;
-
/* Gets the keyboard layout for a particular input device. */
virtual std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier& identifier,
diff --git a/services/inputflinger/include/NotifyArgs.h b/services/inputflinger/include/NotifyArgs.h
index db417cf..14487fe 100644
--- a/services/inputflinger/include/NotifyArgs.h
+++ b/services/inputflinger/include/NotifyArgs.h
@@ -39,21 +39,6 @@
NotifyInputDevicesChangedArgs& operator=(const NotifyInputDevicesChangedArgs&) = default;
};
-/* Describes a configuration change event. */
-struct NotifyConfigurationChangedArgs {
- int32_t id;
- nsecs_t eventTime;
-
- inline NotifyConfigurationChangedArgs() {}
-
- NotifyConfigurationChangedArgs(int32_t id, nsecs_t eventTime);
-
- bool operator==(const NotifyConfigurationChangedArgs& rhs) const = default;
-
- NotifyConfigurationChangedArgs(const NotifyConfigurationChangedArgs& other) = default;
- NotifyConfigurationChangedArgs& operator=(const NotifyConfigurationChangedArgs&) = default;
-};
-
/* Describes a key event. */
struct NotifyKeyArgs {
int32_t id;
@@ -234,8 +219,8 @@
};
using NotifyArgs =
- std::variant<NotifyInputDevicesChangedArgs, NotifyConfigurationChangedArgs, NotifyKeyArgs,
- NotifyMotionArgs, NotifySensorArgs, NotifySwitchArgs, NotifyDeviceResetArgs,
+ std::variant<NotifyInputDevicesChangedArgs, NotifyKeyArgs, NotifyMotionArgs,
+ NotifySensorArgs, NotifySwitchArgs, NotifyDeviceResetArgs,
NotifyPointerCaptureChangedArgs, NotifyVibratorStateArgs>;
const char* toString(const NotifyArgs& args);
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index a052a4e..b76e8c5 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -78,6 +78,7 @@
name: "libinputreader_defaults",
srcs: [":libinputreader_sources"],
shared_libs: [
+ "android.companion.virtualdevice.flags-aconfig-cc",
"libbase",
"libcap",
"libcrypto",
@@ -115,7 +116,6 @@
"libinputreader_defaults",
],
shared_libs: [
- "android.companion.virtualdevice.flags-aconfig-cc-host",
"libinputflinger_base",
],
export_header_lib_headers: [
@@ -141,7 +141,6 @@
shared_libs: [
// This should consist only of dependencies from inputflinger. Other dependencies should be
// in cc_defaults so that they are included in the tests.
- "android.companion.virtualdevice.flags-aconfig-cc-host",
"libinputflinger_base",
"libjsoncpp",
],
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 9381580..e11adb8 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -888,7 +888,6 @@
: mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
mNextDeviceId(1),
mControllerNumbers(),
- mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false),
mNeedToScanDevices(true),
mPendingEventCount(0),
@@ -1877,7 +1876,6 @@
.type = DEVICE_REMOVED,
});
it = mClosingDevices.erase(it);
- mNeedToSendFinishedDeviceScan = true;
if (events.size() == EVENT_BUFFER_SIZE) {
break;
}
@@ -1886,7 +1884,6 @@
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
scanDevicesLocked();
- mNeedToSendFinishedDeviceScan = true;
}
while (!mOpeningDevices.empty()) {
@@ -1915,18 +1912,6 @@
if (!inserted) {
ALOGW("Device id %d exists, replaced.", device->id);
}
- mNeedToSendFinishedDeviceScan = true;
- if (events.size() == EVENT_BUFFER_SIZE) {
- break;
- }
- }
-
- if (mNeedToSendFinishedDeviceScan) {
- mNeedToSendFinishedDeviceScan = false;
- events.push_back({
- .when = now,
- .type = FINISHED_DEVICE_SCAN,
- });
if (events.size() == EVENT_BUFFER_SIZE) {
break;
}
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 9e9e816..f0e53b5 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -180,6 +180,9 @@
}
if (oldGeneration != mGeneration) {
+ // Reset global meta state because it depends on connected input devices.
+ updateGlobalMetaStateLocked();
+
inputDevicesChanged = true;
inputDevices = getInputDevicesLocked();
mPendingArgs.emplace_back(
@@ -212,15 +215,6 @@
mPolicy->notifyInputDevicesChanged(inputDevices);
}
- // Notify the policy of configuration change. This must be after policy is notified about input
- // device changes so that policy can fetch newly added input devices on configuration change.
- for (const auto& args : notifyArgs) {
- const auto* configArgs = std::get_if<NotifyConfigurationChangedArgs>(&args);
- if (configArgs != nullptr) {
- mPolicy->notifyConfigurationChanged(configArgs->eventTime);
- }
- }
-
// Notify the policy of the start of every new stylus gesture.
for (const auto& args : notifyArgs) {
const auto* motionArgs = std::get_if<NotifyMotionArgs>(&args);
@@ -256,9 +250,6 @@
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
- case EventHubInterface::FINISHED_DEVICE_SCAN:
- handleConfigurationChangedLocked(rawEvent->when);
- break;
default:
ALOG_ASSERT(false); // can't happen
break;
@@ -423,14 +414,6 @@
return ++mNextInputDeviceId;
}
-void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
- // Reset global meta state because it depends on the list of all configured devices.
- updateGlobalMetaStateLocked();
-
- // Enqueue configuration changed.
- mPendingArgs.emplace_back(NotifyConfigurationChangedArgs{mContext.getNextId(), when});
-}
-
void InputReader::refreshConfigurationLocked(ConfigurationChanges changes) {
mPolicy->getReaderConfiguration(&mConfig);
mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index c647558..657126a 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -254,9 +254,6 @@
DEVICE_ADDED = 0x10000000,
// Sent when a device is removed.
DEVICE_REMOVED = 0x20000000,
- // Sent when all added/removed devices from the most recent scan have been reported.
- // This event is always sent at least once.
- FINISHED_DEVICE_SCAN = 0x30000000,
FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
};
@@ -789,7 +786,6 @@
std::vector<std::unique_ptr<Device>> mOpeningDevices;
std::vector<std::unique_ptr<Device>> mClosingDevices;
- bool mNeedToSendFinishedDeviceScan;
bool mNeedToReopenDevices;
bool mNeedToScanDevices;
std::vector<std::string> mExcludedDevices;
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 03ca840..4f60a8a 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -221,8 +221,6 @@
size_t count) REQUIRES(mLock);
[[nodiscard]] std::list<NotifyArgs> timeoutExpiredLocked(nsecs_t when) REQUIRES(mLock);
- void handleConfigurationChangedLocked(nsecs_t when) REQUIRES(mLock);
-
int32_t mGlobalMetaState GUARDED_BY(mLock);
void updateGlobalMetaStateLocked() REQUIRES(mLock);
int32_t getGlobalMetaStateLocked() REQUIRES(mLock);
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 65e0429..ab50646 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -78,10 +78,12 @@
"PropertyProvider_test.cpp",
"RotaryEncoderInputMapper_test.cpp",
"SlopController_test.cpp",
+ "SwitchInputMapper_test.cpp",
"SyncQueue_test.cpp",
"TimerProvider_test.cpp",
"TestInputListener.cpp",
"TouchpadInputMapper_test.cpp",
+ "VibratorInputMapper_test.cpp",
"MultiTouchInputMapper_test.cpp",
"KeyboardInputMapper_test.cpp",
"UinputDevice.cpp",
@@ -109,7 +111,6 @@
},
},
static_libs: [
- "android.companion.virtualdevice.flags-aconfig-cc-test",
"libflagtest",
"libgmock",
],
diff --git a/services/inputflinger/tests/EventHub_test.cpp b/services/inputflinger/tests/EventHub_test.cpp
index 2e296da..0e3d15a 100644
--- a/services/inputflinger/tests/EventHub_test.cpp
+++ b/services/inputflinger/tests/EventHub_test.cpp
@@ -48,9 +48,6 @@
case EventHubInterface::DEVICE_REMOVED:
ALOGI("Device removed: %i", event.deviceId);
break;
- case EventHubInterface::FINISHED_DEVICE_SCAN:
- ALOGI("Finished device scan.");
- break;
}
} else {
ALOGI("Device %" PRId32 " : time = %" PRId64 ", type %i, code %i, value %i",
@@ -145,15 +142,13 @@
// None of the existing system devices should be changing while this test is run.
// Check that the returned device ids are unique for all of the existing devices.
EXPECT_EQ(existingDevices.size(), events.size() - 1);
- // The last event should be "finished device scan"
- EXPECT_EQ(EventHubInterface::FINISHED_DEVICE_SCAN, events[events.size() - 1].type);
}
int32_t EventHubTest::waitForDeviceCreation() {
// Wait a little longer than usual, to ensure input device has time to be created
std::vector<RawEvent> events = getEvents(2);
- if (events.size() != 2) {
- ADD_FAILURE() << "Instead of 2 events, received " << events.size();
+ if (events.size() != 1) {
+ ADD_FAILURE() << "Instead of 1 event, received " << events.size();
return 0; // this value is unused
}
const RawEvent& deviceAddedEvent = events[0];
@@ -161,21 +156,15 @@
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceAddedEvent.deviceId);
const int32_t deviceId = deviceAddedEvent.deviceId;
EXPECT_EQ(identifier.name, mKeyboard->getName());
- const RawEvent& finishedDeviceScanEvent = events[1];
- EXPECT_EQ(static_cast<int32_t>(EventHubInterface::FINISHED_DEVICE_SCAN),
- finishedDeviceScanEvent.type);
return deviceId;
}
void EventHubTest::waitForDeviceClose(int32_t deviceId) {
std::vector<RawEvent> events = getEvents(2);
- ASSERT_EQ(2U, events.size());
+ ASSERT_EQ(1U, events.size());
const RawEvent& deviceRemovedEvent = events[0];
EXPECT_EQ(static_cast<int32_t>(EventHubInterface::DEVICE_REMOVED), deviceRemovedEvent.type);
EXPECT_EQ(deviceId, deviceRemovedEvent.deviceId);
- const RawEvent& finishedDeviceScanEvent = events[1];
- EXPECT_EQ(static_cast<int32_t>(EventHubInterface::FINISHED_DEVICE_SCAN),
- finishedDeviceScanEvent.type);
}
void EventHubTest::assertNoMoreEvents() {
diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp
index 7079278..31fbf20 100644
--- a/services/inputflinger/tests/FakeEventHub.cpp
+++ b/services/inputflinger/tests/FakeEventHub.cpp
@@ -88,10 +88,6 @@
return device->disable();
}
-void FakeEventHub::finishDeviceScan() {
- enqueueEvent(ARBITRARY_TIME, READ_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0);
-}
-
void FakeEventHub::addConfigurationProperty(int32_t deviceId, const char* key, const char* value) {
getDevice(deviceId)->configuration.addProperty(key, value);
}
diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h
index c2c875f..3d8dddd 100644
--- a/services/inputflinger/tests/FakeEventHub.h
+++ b/services/inputflinger/tests/FakeEventHub.h
@@ -112,8 +112,6 @@
status_t enableDevice(int32_t deviceId) override;
status_t disableDevice(int32_t deviceId) override;
- void finishDeviceScan();
-
void addConfigurationProperty(int32_t deviceId, const char* key, const char* value);
void addConfigurationMap(int32_t deviceId, const PropertyMap* configuration);
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
index 56a8918..6099c91 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
@@ -65,23 +65,6 @@
ASSERT_FALSE(mDeviceIdOfNotifiedStylusGesture);
}
-void FakeInputReaderPolicy::assertConfigurationChanged() {
- std::unique_lock lock(mLock);
- base::ScopedLockAssertion assumeLocked(mLock);
-
- const bool configurationChanged =
- mConfigurationChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
- return mConfigurationChanged;
- });
- ASSERT_TRUE(configurationChanged) << "Timed out waiting for configuration change";
- mConfigurationChanged = false;
-}
-
-void FakeInputReaderPolicy::assertConfigurationNotChanged() {
- std::scoped_lock lock(mLock);
- ASSERT_FALSE(mConfigurationChanged);
-}
-
void FakeInputReaderPolicy::clearViewports() {
mViewports.clear();
mConfig.setDisplayViewports(mViewports);
@@ -251,12 +234,6 @@
mDevicesChangedCondition.notify_all();
}
-void FakeInputReaderPolicy::notifyConfigurationChanged(nsecs_t when) {
- std::scoped_lock lock(mLock);
- mConfigurationChanged = true;
- mConfigurationChangedCondition.notify_all();
-}
-
std::shared_ptr<KeyCharacterMap> FakeInputReaderPolicy::getKeyboardLayoutOverlay(
const InputDeviceIdentifier&, const std::optional<KeyboardLayoutInfo>) {
return nullptr;
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h
index ea6e7f2..94f1311 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.h
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.h
@@ -42,8 +42,6 @@
void assertInputDevicesNotChanged();
void assertStylusGestureNotified(int32_t deviceId);
void assertStylusGestureNotNotified();
- void assertConfigurationChanged();
- void assertConfigurationNotChanged();
virtual void clearViewports();
std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueId) const;
@@ -84,7 +82,6 @@
private:
void getReaderConfiguration(InputReaderConfiguration* outConfig) override;
void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override;
- void notifyConfigurationChanged(nsecs_t when) override;
std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier&, const std::optional<KeyboardLayoutInfo>) override;
std::string getDeviceAlias(const InputDeviceIdentifier&) override;
@@ -93,12 +90,10 @@
mutable std::mutex mLock;
std::condition_variable mDevicesChangedCondition;
- std::condition_variable mConfigurationChangedCondition;
InputReaderConfiguration mConfig;
std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock);
bool mInputDevicesChanged GUARDED_BY(mLock){false};
- bool mConfigurationChanged GUARDED_BY(mLock){false};
std::vector<DisplayViewport> mViewports;
TouchAffineTransformation transform;
bool mIsInputMethodConnectionActive{false};
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 4e662d4..c70afd6 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -411,8 +411,6 @@
<< "Should reject motion events with duplicate pointer ids.";
}
-/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
-
TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
/*switchValues=*/1,
@@ -5659,6 +5657,72 @@
rightWindow->assertNoEvents();
}
+/**
+ * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
+ * down event to the right window. Device B sends a down event to the left window, and then a
+ * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
+ * POINTER_DOWN event should only go to the left window, and not to the right window.
+ * This test attempts to reproduce a crash.
+ */
+TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> leftWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
+ ui::LogicalDisplayId::DEFAULT);
+ leftWindow->setFrame(Rect(0, 0, 100, 100));
+ leftWindow->setPreventSplitting(true);
+
+ sp<FakeWindowHandle> rightWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
+ ui::LogicalDisplayId::DEFAULT);
+ rightWindow->setFrame(Rect(100, 0, 200, 100));
+
+ mDispatcher->onWindowInfosChanged(
+ {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
+
+ const DeviceId deviceA = 9;
+ const DeviceId deviceB = 3;
+ // Touch the right window with device A
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
+ .deviceId(deviceA)
+ .build());
+ rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
+ // Touch the left window with device B
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .deviceId(deviceB)
+ .build());
+ leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
+ // Send a second pointer from device B to the right window. It shouldn't go to the right window
+ // because the left window prevents splitting.
+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(deviceB)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
+ .build());
+ leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
+
+ // Finish the gesture for both devices
+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(deviceB)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
+ .build());
+ leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .deviceId(deviceB)
+ .build());
+ leftWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0)));
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
+ .deviceId(deviceA)
+ .build());
+ rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA)));
+}
+
TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
index 5722444..e773f58 100644
--- a/services/inputflinger/tests/InputMapperTest.cpp
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -89,6 +89,13 @@
}
}
+void InputMapperUnitTest::setSwitchState(int32_t state, std::set<int32_t> switchCodes) {
+ for (const auto& switchCode : switchCodes) {
+ EXPECT_CALL(mMockEventHub, getSwitchState(EVENTHUB_ID, switchCode))
+ .WillRepeatedly(testing::Return(static_cast<int>(state)));
+ }
+}
+
std::list<NotifyArgs> InputMapperUnitTest::process(int32_t type, int32_t code, int32_t value) {
nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
return process(when, type, code, value);
diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h
index 5bd8cda..88057dc 100644
--- a/services/inputflinger/tests/InputMapperTest.h
+++ b/services/inputflinger/tests/InputMapperTest.h
@@ -58,6 +58,8 @@
void setKeyCodeState(KeyState state, std::set<int> keyCodes);
+ void setSwitchState(int32_t state, std::set<int32_t> switchCodes);
+
std::list<NotifyArgs> process(int32_t type, int32_t code, int32_t value);
std::list<NotifyArgs> process(nsecs_t when, int32_t type, int32_t code, int32_t value);
diff --git a/services/inputflinger/tests/InputProcessor_test.cpp b/services/inputflinger/tests/InputProcessor_test.cpp
index f7e5e67..d4c5a00 100644
--- a/services/inputflinger/tests/InputProcessor_test.cpp
+++ b/services/inputflinger/tests/InputProcessor_test.cpp
@@ -63,20 +63,6 @@
void SetUp() override { mProcessor = std::make_unique<InputProcessor>(mTestListener); }
};
-/**
- * Create a basic configuration change and send it to input processor.
- * Expect that the event is received by the next input stage, unmodified.
- */
-TEST_F(InputProcessorTest, SendToNextStage_NotifyConfigurationChangedArgs) {
- // Create a basic configuration change and send to processor
- NotifyConfigurationChangedArgs args(/*sequenceNum=*/1, /*eventTime=*/2);
-
- mProcessor->notifyConfigurationChanged(args);
- NotifyConfigurationChangedArgs outArgs;
- ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyConfigurationChangedWasCalled(&outArgs));
- ASSERT_EQ(args, outArgs);
-}
-
TEST_F(InputProcessorTest, SendToNextStage_NotifyKeyArgs) {
// Create a basic key event and send to processor
NotifyKeyArgs args(/*sequenceNum=*/1, /*eventTime=*/2, /*readTime=*/21, /*deviceId=*/3,
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 1ba79a9..267c400 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -31,12 +31,10 @@
#include <PeripheralController.h>
#include <SensorInputMapper.h>
#include <SingleTouchInputMapper.h>
-#include <SwitchInputMapper.h>
#include <TestEventMatchers.h>
#include <TestInputListener.h>
#include <TouchInputMapper.h>
#include <UinputDevice.h>
-#include <VibratorInputMapper.h>
#include <android-base/thread_annotations.h>
#include <com_android_input_flags.h>
#include <ftl/enum.h>
@@ -624,7 +622,6 @@
if (configuration) {
mFakeEventHub->addConfigurationMap(eventHubId, configuration);
}
- mFakeEventHub->finishDeviceScan();
mReader->loopOnce();
mReader->loopOnce();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
@@ -758,8 +755,6 @@
mReader->pushNextDevice(device);
ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
-
NotifyDeviceResetArgs resetArgs;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
ASSERT_EQ(deviceId, resetArgs.deviceId);
@@ -775,7 +770,6 @@
disableDevice(deviceId);
mReader->loopOnce();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasNotCalled());
ASSERT_EQ(device->isEnabled(), false);
enableDevice(deviceId);
@@ -960,17 +954,6 @@
ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
}
-TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
- constexpr int32_t eventHubId = 1;
- addDevice(eventHubId, "ignored", InputDeviceClass::KEYBOARD, nullptr);
-
- NotifyConfigurationChangedArgs args;
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(&args));
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-}
-
TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
@@ -1075,7 +1058,6 @@
// The device is added after the input port associations are processed since
// we do not yet support dynamic device-to-display associations.
ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled());
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
@@ -1105,8 +1087,6 @@
ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
-
NotifyDeviceResetArgs resetArgs;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
ASSERT_EQ(deviceId, resetArgs.deviceId);
@@ -1479,9 +1459,7 @@
// to the test device will show up in mReader. We wait for those input devices to
// show up before beginning the tests.
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
- ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
}
};
@@ -1501,12 +1479,10 @@
// consider it as a valid device.
std::unique_ptr<UinputDevice> invalidDevice = createUinputDevice<InvalidUinputDevice>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationNotChanged());
ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
invalidDevice.reset();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationNotChanged());
ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
}
@@ -1515,7 +1491,6 @@
std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size());
const auto device = waitForDevice(keyboard->getName());
@@ -1526,7 +1501,6 @@
keyboard.reset();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
ASSERT_EQ(initialNumDevices, mFakePolicy->getInputDevices().size());
}
@@ -1534,21 +1508,14 @@
std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- NotifyConfigurationChangedArgs configChangedArgs;
- ASSERT_NO_FATAL_FAILURE(
- mTestListener->assertNotifyConfigurationChangedWasCalled(&configChangedArgs));
- int32_t prevId = configChangedArgs.id;
- nsecs_t prevTimestamp = configChangedArgs.eventTime;
-
NotifyKeyArgs keyArgs;
keyboard->pressAndReleaseHomeKey();
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_NE(prevId, keyArgs.id);
- prevId = keyArgs.id;
- ASSERT_LE(prevTimestamp, keyArgs.eventTime);
ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
- prevTimestamp = keyArgs.eventTime;
+
+ int32_t prevId = keyArgs.id;
+ nsecs_t prevTimestamp = keyArgs.eventTime;
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
@@ -1671,8 +1638,6 @@
mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
- ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
const auto info = waitForDevice(mDevice->getName());
ASSERT_TRUE(info);
mDeviceInfo = *info;
@@ -1741,8 +1706,6 @@
UNIQUE_ID, isInputPortAssociation ? DISPLAY_PORT : NO_PORT,
ViewportType::INTERNAL);
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
- ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
const auto info = waitForDevice(mDevice->getName());
ASSERT_TRUE(info);
mDeviceInfo = *info;
@@ -2075,7 +2038,6 @@
// Connecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
auto externalStylus = createUinputDevice<UinputExternalStylus>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
const auto stylusInfo = waitForDevice(externalStylus->getName());
ASSERT_TRUE(stylusInfo);
@@ -2088,7 +2050,6 @@
// Disconnecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
externalStylus.reset();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
// Up
@@ -2146,8 +2107,6 @@
mStylusDeviceLifecycleTracker = createUinputDevice<T>();
mStylus = mStylusDeviceLifecycleTracker.get();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
- ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
const auto info = waitForDevice(mStylus->getName());
ASSERT_TRUE(info);
mStylusInfo = *info;
@@ -2417,7 +2376,6 @@
std::unique_ptr<UinputExternalStylusWithPressure> stylus =
createUinputDevice<UinputExternalStylusWithPressure>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
const auto stylusInfo = waitForDevice(stylus->getName());
ASSERT_TRUE(stylusInfo);
@@ -2435,7 +2393,6 @@
std::unique_ptr<UinputExternalStylusWithPressure> stylus =
createUinputDevice<UinputExternalStylusWithPressure>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
const auto stylusInfo = waitForDevice(stylus->getName());
ASSERT_TRUE(stylusInfo);
@@ -2481,7 +2438,6 @@
std::unique_ptr<UinputExternalStylusWithPressure> stylus =
createUinputDevice<UinputExternalStylusWithPressure>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
const auto stylusInfo = waitForDevice(stylus->getName());
ASSERT_TRUE(stylusInfo);
@@ -2561,7 +2517,6 @@
// touch pointers.
std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
- ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
const auto stylusInfo = waitForDevice(stylus->getName());
ASSERT_TRUE(stylusInfo);
@@ -3063,106 +3018,6 @@
mapper.assertProcessWasCalled();
}
-// --- SwitchInputMapperTest ---
-
-class SwitchInputMapperTest : public InputMapperTest {
-protected:
-};
-
-TEST_F(SwitchInputMapperTest, GetSources) {
- SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
-
- ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mapper.getSources());
-}
-
-TEST_F(SwitchInputMapperTest, GetSwitchState) {
- SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
-
- mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 1);
- ASSERT_EQ(1, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
-
- mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 0);
- ASSERT_EQ(0, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
-}
-
-TEST_F(SwitchInputMapperTest, Process) {
- SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
- std::list<NotifyArgs> out;
- out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_LID, 1);
- ASSERT_TRUE(out.empty());
- out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
- ASSERT_TRUE(out.empty());
- out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_HEADPHONE_INSERT, 0);
- ASSERT_TRUE(out.empty());
- out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
-
- ASSERT_EQ(1u, out.size());
- const NotifySwitchArgs& args = std::get<NotifySwitchArgs>(*out.begin());
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT), args.switchValues);
- ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
- args.switchMask);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
-}
-
-// --- VibratorInputMapperTest ---
-class VibratorInputMapperTest : public InputMapperTest {
-protected:
- void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::VIBRATOR); }
-};
-
-TEST_F(VibratorInputMapperTest, GetSources) {
- VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
-
- ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
-}
-
-TEST_F(VibratorInputMapperTest, GetVibratorIds) {
- VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
-
- ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
-}
-
-TEST_F(VibratorInputMapperTest, Vibrate) {
- constexpr uint8_t DEFAULT_AMPLITUDE = 192;
- constexpr int32_t VIBRATION_TOKEN = 100;
- VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
-
- VibrationElement pattern(2);
- VibrationSequence sequence(2);
- pattern.duration = std::chrono::milliseconds(200);
- pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 2},
- {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
- sequence.addElement(pattern);
- pattern.duration = std::chrono::milliseconds(500);
- pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 4},
- {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
- sequence.addElement(pattern);
-
- std::vector<int64_t> timings = {0, 1};
- std::vector<uint8_t> amplitudes = {DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE / 2};
-
- ASSERT_FALSE(mapper.isVibrating());
- // Start vibrating
- std::list<NotifyArgs> out = mapper.vibrate(sequence, /*repeat=*/-1, VIBRATION_TOKEN);
- ASSERT_TRUE(mapper.isVibrating());
- // Verify vibrator state listener was notified.
- mReader->loopOnce();
- ASSERT_EQ(1u, out.size());
- const NotifyVibratorStateArgs& vibrateArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
- ASSERT_EQ(DEVICE_ID, vibrateArgs.deviceId);
- ASSERT_TRUE(vibrateArgs.isOn);
- // Stop vibrating
- out = mapper.cancelVibrate(VIBRATION_TOKEN);
- ASSERT_FALSE(mapper.isVibrating());
- // Verify vibrator state listener was notified.
- mReader->loopOnce();
- ASSERT_EQ(1u, out.size());
- const NotifyVibratorStateArgs& cancelArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
- ASSERT_EQ(DEVICE_ID, cancelArgs.deviceId);
- ASSERT_FALSE(cancelArgs.isOn);
-}
-
// --- SensorInputMapperTest ---
class SensorInputMapperTest : public InputMapperTest {
diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp
index 144e723..18222dd 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -196,7 +196,6 @@
TEST_F(PointerChoreographerTest, ForwardsArgsToInnerListener) {
const std::vector<NotifyArgs>
allArgs{NotifyInputDevicesChangedArgs{},
- NotifyConfigurationChangedArgs{},
KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build(),
MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
.pointer(FIRST_TOUCH_POINTER)
@@ -214,9 +213,6 @@
[&](const NotifyInputDevicesChangedArgs& args) {
mTestListener.assertNotifyInputDevicesChangedWasCalled();
},
- [&](const NotifyConfigurationChangedArgs& args) {
- mTestListener.assertNotifyConfigurationChangedWasCalled();
- },
[&](const NotifyKeyArgs& args) {
mTestListener.assertNotifyKeyWasCalled();
},
@@ -830,15 +826,20 @@
pc->assertSpotCount(DISPLAY_ID, 0);
}
+/**
+ * In this test, we simulate the complete event of the stylus approaching and clicking on the
+ * screen, and then leaving the screen. We should ensure that spots are displayed correctly.
+ */
TEST_F(PointerChoreographerTest, TouchSetsSpotsForStylusEvent) {
mChoreographer.setShowTouchesEnabled(true);
+ mChoreographer.setStylusPointerIconEnabled(false);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
DISPLAY_ID)}});
- // Emit down event with stylus properties.
- mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN,
+ // First, the stylus begin to approach the screen.
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS)
.pointer(STYLUS_POINTER)
.deviceId(DEVICE_ID)
@@ -846,6 +847,72 @@
.build());
auto pc = assertPointerControllerCreated(ControllerType::TOUCH);
pc->assertSpotCount(DISPLAY_ID, 1);
+
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
+ AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS)
+ .pointer(STYLUS_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+ pc->assertSpotCount(DISPLAY_ID, 1);
+
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
+ AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS)
+ .pointer(STYLUS_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+ pc->assertSpotCount(DISPLAY_ID, 0);
+
+ // Now, use stylus touch the screen.
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS)
+ .pointer(STYLUS_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+ pc->assertSpotCount(DISPLAY_ID, 1);
+
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE,
+ AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS)
+ .pointer(STYLUS_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+ pc->assertSpotCount(DISPLAY_ID, 1);
+
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP,
+ AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS)
+ .pointer(STYLUS_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+ pc->assertSpotCount(DISPLAY_ID, 0);
+
+ // Then, the stylus start leave from the screen.
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
+ AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS)
+ .pointer(STYLUS_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+ pc->assertSpotCount(DISPLAY_ID, 1);
+
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
+ AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS)
+ .pointer(STYLUS_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+ pc->assertSpotCount(DISPLAY_ID, 1);
+
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
+ AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS)
+ .pointer(STYLUS_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+ pc->assertSpotCount(DISPLAY_ID, 0);
}
TEST_F(PointerChoreographerTest, TouchSetsSpotsForTwoDisplays) {
diff --git a/services/inputflinger/tests/SwitchInputMapper_test.cpp b/services/inputflinger/tests/SwitchInputMapper_test.cpp
new file mode 100644
index 0000000..4020e78
--- /dev/null
+++ b/services/inputflinger/tests/SwitchInputMapper_test.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2024 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 "SwitchInputMapper.h"
+
+#include <list>
+#include <variant>
+
+#include <NotifyArgs.h>
+#include <gtest/gtest.h>
+#include <input/Input.h>
+#include <linux/input-event-codes.h>
+
+#include "InputMapperTest.h"
+#include "TestConstants.h"
+
+namespace android {
+
+class SwitchInputMapperTest : public InputMapperUnitTest {
+protected:
+ void SetUp() override {
+ InputMapperUnitTest::SetUp();
+ createDevice();
+ mMapper = createInputMapper<SwitchInputMapper>(*mDeviceContext,
+ mFakePolicy->getReaderConfiguration());
+ }
+};
+
+TEST_F(SwitchInputMapperTest, GetSources) {
+ ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mMapper->getSources());
+}
+
+TEST_F(SwitchInputMapperTest, GetSwitchState) {
+ setSwitchState(1, {SW_LID});
+ ASSERT_EQ(1, mMapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
+
+ setSwitchState(0, {SW_LID});
+ ASSERT_EQ(0, mMapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
+}
+
+TEST_F(SwitchInputMapperTest, Process) {
+ std::list<NotifyArgs> out;
+ out = process(ARBITRARY_TIME, EV_SW, SW_LID, 1);
+ ASSERT_TRUE(out.empty());
+ out = process(ARBITRARY_TIME, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
+ ASSERT_TRUE(out.empty());
+ out = process(ARBITRARY_TIME, EV_SW, SW_HEADPHONE_INSERT, 0);
+ ASSERT_TRUE(out.empty());
+ out = process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+
+ ASSERT_EQ(1u, out.size());
+ const NotifySwitchArgs& args = std::get<NotifySwitchArgs>(*out.begin());
+ ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+ ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT), args.switchValues);
+ ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
+ args.switchMask);
+ ASSERT_EQ(uint32_t(0), args.policyFlags);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp
index 41e250f..369f9cc 100644
--- a/services/inputflinger/tests/TestInputListener.cpp
+++ b/services/inputflinger/tests/TestInputListener.cpp
@@ -37,19 +37,6 @@
"to have been called."));
}
-void TestInputListener::assertNotifyConfigurationChangedWasCalled(
- NotifyConfigurationChangedArgs* outEventArgs) {
- ASSERT_NO_FATAL_FAILURE(
- assertCalled<NotifyConfigurationChangedArgs>(outEventArgs,
- "Expected notifyConfigurationChanged() "
- "to have been called."));
-}
-
-void TestInputListener::assertNotifyConfigurationChangedWasNotCalled() {
- ASSERT_NO_FATAL_FAILURE(assertNotCalled<NotifyConfigurationChangedArgs>(
- "notifyConfigurationChanged() should not be called."));
-}
-
void TestInputListener::assertNotifyDeviceResetWasCalled(NotifyDeviceResetArgs* outEventArgs) {
ASSERT_NO_FATAL_FAILURE(
assertCalled<
@@ -192,10 +179,6 @@
addToQueue<NotifyInputDevicesChangedArgs>(args);
}
-void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
- addToQueue<NotifyConfigurationChangedArgs>(args);
-}
-
void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
addToQueue<NotifyDeviceResetArgs>(args);
}
diff --git a/services/inputflinger/tests/TestInputListener.h b/services/inputflinger/tests/TestInputListener.h
index 3c5e014..47eae4d 100644
--- a/services/inputflinger/tests/TestInputListener.h
+++ b/services/inputflinger/tests/TestInputListener.h
@@ -38,11 +38,6 @@
void assertNotifyInputDevicesChangedWasCalled(
NotifyInputDevicesChangedArgs* outEventArgs = nullptr);
- void assertNotifyConfigurationChangedWasCalled(
- NotifyConfigurationChangedArgs* outEventArgs = nullptr);
-
- void assertNotifyConfigurationChangedWasNotCalled();
-
void clearNotifyDeviceResetCalls();
void assertNotifyDeviceResetWasCalled(const ::testing::Matcher<NotifyDeviceResetArgs>& matcher);
@@ -85,8 +80,6 @@
virtual void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
-
virtual void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
virtual void notifyKey(const NotifyKeyArgs& args) override;
@@ -107,7 +100,6 @@
const std::chrono::milliseconds mEventDidNotHappenTimeout;
std::tuple<std::vector<NotifyInputDevicesChangedArgs>, //
- std::vector<NotifyConfigurationChangedArgs>, //
std::vector<NotifyDeviceResetArgs>, //
std::vector<NotifyKeyArgs>, //
std::vector<NotifyMotionArgs>, //
diff --git a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
index 853f628..bbb2fc8 100644
--- a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
+++ b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
@@ -414,20 +414,6 @@
};
/**
- * Create a basic configuration change and send it to input processor.
- * Expect that the event is received by the next input stage, unmodified.
- */
-TEST_F(UnwantedInteractionBlockerTest, ConfigurationChangedIsPassedToNextListener) {
- // Create a basic configuration change and send to blocker
- NotifyConfigurationChangedArgs args(/*sequenceNum=*/1, /*eventTime=*/2);
-
- mBlocker->notifyConfigurationChanged(args);
- NotifyConfigurationChangedArgs outArgs;
- ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyConfigurationChangedWasCalled(&outArgs));
- ASSERT_EQ(args, outArgs);
-}
-
-/**
* Keys are not handled in 'UnwantedInteractionBlocker' and should be passed
* to next stage unmodified.
*/
diff --git a/services/inputflinger/tests/VibratorInputMapper_test.cpp b/services/inputflinger/tests/VibratorInputMapper_test.cpp
new file mode 100644
index 0000000..aa4a6bb
--- /dev/null
+++ b/services/inputflinger/tests/VibratorInputMapper_test.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2024 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 "VibratorInputMapper.h"
+
+#include <chrono>
+#include <list>
+#include <variant>
+#include <vector>
+
+#include <EventHub.h>
+#include <NotifyArgs.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <input/Input.h>
+
+#include "InputMapperTest.h"
+#include "VibrationElement.h"
+
+namespace android {
+
+class VibratorInputMapperTest : public InputMapperUnitTest {
+protected:
+ void SetUp() override {
+ InputMapperUnitTest::SetUp();
+ createDevice();
+ EXPECT_CALL(mMockEventHub, getDeviceClasses(EVENTHUB_ID))
+ .WillRepeatedly(testing::Return(InputDeviceClass::VIBRATOR));
+ EXPECT_CALL(mMockEventHub, getVibratorIds(EVENTHUB_ID))
+ .WillRepeatedly(testing::Return<std::vector<int32_t>>({0, 1}));
+ mMapper = createInputMapper<VibratorInputMapper>(*mDeviceContext,
+ mFakePolicy->getReaderConfiguration());
+ }
+};
+
+TEST_F(VibratorInputMapperTest, GetSources) {
+ ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mMapper->getSources());
+}
+
+TEST_F(VibratorInputMapperTest, GetVibratorIds) {
+ ASSERT_EQ(mMapper->getVibratorIds().size(), 2U);
+}
+
+TEST_F(VibratorInputMapperTest, Vibrate) {
+ constexpr uint8_t DEFAULT_AMPLITUDE = 192;
+ constexpr int32_t VIBRATION_TOKEN = 100;
+
+ VibrationElement pattern(2);
+ VibrationSequence sequence(2);
+ pattern.duration = std::chrono::milliseconds(200);
+ pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 2},
+ {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
+ sequence.addElement(pattern);
+ pattern.duration = std::chrono::milliseconds(500);
+ pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 4},
+ {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
+ sequence.addElement(pattern);
+
+ std::vector<int64_t> timings = {0, 1};
+ std::vector<uint8_t> amplitudes = {DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE / 2};
+
+ ASSERT_FALSE(mMapper->isVibrating());
+ // Start vibrating
+ std::list<NotifyArgs> out = mMapper->vibrate(sequence, /*repeat=*/-1, VIBRATION_TOKEN);
+ ASSERT_TRUE(mMapper->isVibrating());
+ // Verify vibrator state listener was notified.
+ ASSERT_EQ(1u, out.size());
+ const NotifyVibratorStateArgs& vibrateArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
+ ASSERT_EQ(DEVICE_ID, vibrateArgs.deviceId);
+ ASSERT_TRUE(vibrateArgs.isOn);
+ // Stop vibrating
+ out = mMapper->cancelVibrate(VIBRATION_TOKEN);
+ ASSERT_FALSE(mMapper->isVibrating());
+ // Verify vibrator state listener was notified.
+ ASSERT_EQ(1u, out.size());
+ const NotifyVibratorStateArgs& cancelArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
+ ASSERT_EQ(DEVICE_ID, cancelArgs.deviceId);
+ ASSERT_FALSE(cancelArgs.isOn);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
index 0b4ac1f..46a6189 100644
--- a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
@@ -39,12 +39,6 @@
while (fdp.remaining_bytes() > 0) {
fdp.PickValueInArray<std::function<void()>>({
[&]() -> void {
- // SendToNextStage_NotifyConfigurationChangedArgs
- mClassifier->notifyConfigurationChanged(
- {/*sequenceNum=*/fdp.ConsumeIntegral<int32_t>(),
- /*eventTime=*/fdp.ConsumeIntegral<nsecs_t>()});
- },
- [&]() -> void {
// SendToNextStage_NotifyKeyArgs
const nsecs_t eventTime =
fdp.ConsumeIntegralInRange<nsecs_t>(0,
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index d986b31..fea0d9a 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -32,8 +32,7 @@
EV_MSC,
EV_REL,
android::EventHubInterface::DEVICE_ADDED,
- android::EventHubInterface::DEVICE_REMOVED,
- android::EventHubInterface::FINISHED_DEVICE_SCAN};
+ android::EventHubInterface::DEVICE_REMOVED};
constexpr size_t kValidCodes[] = {
SYN_REPORT,
@@ -296,7 +295,6 @@
}
void setTouchAffineTransformation(const TouchAffineTransformation t) { mTransform = t; }
void notifyStylusGestureStarted(int32_t, nsecs_t) {}
- void notifyConfigurationChanged(nsecs_t) {}
bool isInputMethodConnectionActive() override { return mFdp->ConsumeBool(); }
std::optional<DisplayViewport> getPointerViewportForAssociatedDisplay(
ui::LogicalDisplayId associatedDisplayId) override {
@@ -307,7 +305,6 @@
class FuzzInputListener : public virtual InputListenerInterface {
public:
void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override {}
- void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override {}
void notifyKey(const NotifyKeyArgs& args) override {}
void notifyMotion(const NotifyMotionArgs& args) override {}
void notifySwitch(const NotifySwitchArgs& args) override {}
@@ -346,7 +343,6 @@
void updateLedMetaState(int32_t metaState) override{};
int32_t getLedMetaState() override { return mFdp->ConsumeIntegral<int32_t>(); };
void notifyStylusGestureStarted(int32_t, nsecs_t) {}
- void notifyConfigurationChanged(nsecs_t) {}
void setPreventingTouchpadTaps(bool prevent) override {}
bool isPreventingTouchpadTaps() override { return mFdp->ConsumeBool(); };
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
index 6be6735..9c0e072 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
@@ -92,15 +92,15 @@
}
private:
- std::vector<const LayerState> copyLayers(const std::vector<const LayerState*>& layers) {
- std::vector<const LayerState> copiedLayers;
+ std::vector<LayerState> copyLayers(const std::vector<const LayerState*>& layers) {
+ std::vector<LayerState> copiedLayers;
copiedLayers.reserve(layers.size());
std::transform(layers.cbegin(), layers.cend(), std::back_inserter(copiedLayers),
[](const LayerState* layerState) { return *layerState; });
return copiedLayers;
}
- std::vector<const LayerState> mLayers;
+ std::vector<LayerState> mLayers;
// TODO(b/180976743): Tune kMaxDifferingFields
constexpr static int kMaxDifferingFields = 6;
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index 30b8eee..0d2987c 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -331,6 +331,7 @@
TransactionTraceWriter::getInstance().invoke("DuplicateLayer", /* overwrite= */ false);
return;
}
+ mVisitedLayers.insert(snapshot->uniqueSequence);
LayerProtoHelper::writeSnapshotToProto(layerProto, layer, *snapshot, mTraceFlags);
for (const auto& [child, variant] : root.mChildren) {
diff --git a/services/surfaceflinger/LocklessQueue.h b/services/surfaceflinger/LocklessQueue.h
index 6b63360..4d0b261 100644
--- a/services/surfaceflinger/LocklessQueue.h
+++ b/services/surfaceflinger/LocklessQueue.h
@@ -15,11 +15,11 @@
*/
#pragma once
+
#include <atomic>
#include <optional>
-template <typename T>
-// Single consumer multi producer stack. We can understand the two operations independently to see
+// Single consumer multi producer queue. We can understand the two operations independently to see
// why they are without race condition.
//
// push is responsible for maintaining a linked list stored in mPush, and called from multiple
@@ -36,33 +36,27 @@
// then store the list and pop one element.
//
// If we already had something in the pop list we just pop directly.
+template <typename T>
class LocklessQueue {
public:
- class Entry {
- public:
- T mValue;
- std::atomic<Entry*> mNext;
- Entry(T value) : mValue(value) {}
- };
- std::atomic<Entry*> mPush = nullptr;
- std::atomic<Entry*> mPop = nullptr;
bool isEmpty() { return (mPush.load() == nullptr) && (mPop.load() == nullptr); }
void push(T value) {
- Entry* entry = new Entry(value);
+ Entry* entry = new Entry(std::move(value));
Entry* previousHead = mPush.load(/*std::memory_order_relaxed*/);
do {
entry->mNext = previousHead;
} while (!mPush.compare_exchange_weak(previousHead, entry)); /*std::memory_order_release*/
}
+
std::optional<T> pop() {
Entry* popped = mPop.load(/*std::memory_order_acquire*/);
if (popped) {
// Single consumer so this is fine
mPop.store(popped->mNext /* , std::memory_order_release */);
- auto value = popped->mValue;
+ auto value = std::move(popped->mValue);
delete popped;
- return std::move(value);
+ return value;
} else {
Entry* grabbedList = mPush.exchange(nullptr /* , std::memory_order_acquire */);
if (!grabbedList) return std::nullopt;
@@ -74,9 +68,19 @@
grabbedList = next;
}
mPop.store(popped /* , std::memory_order_release */);
- auto value = grabbedList->mValue;
+ auto value = std::move(grabbedList->mValue);
delete grabbedList;
- return std::move(value);
+ return value;
}
}
+
+private:
+ class Entry {
+ public:
+ T mValue;
+ std::atomic<Entry*> mNext;
+ Entry(T value) : mValue(value) {}
+ };
+ std::atomic<Entry*> mPush = nullptr;
+ std::atomic<Entry*> mPop = nullptr;
};
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index fbd788b..0cf7bdc 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -82,7 +82,7 @@
mTouchTimer.reset();
// Stop idle timer and clear callbacks, as the RefreshRateSelector may outlive the Scheduler.
- demotePacesetterDisplay();
+ demotePacesetterDisplay({.toggleIdleTimer = true});
}
void Scheduler::initVsync(frametimeline::TokenManager& tokenManager,
@@ -117,10 +117,11 @@
}
}
-void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt) {
- demotePacesetterDisplay();
+void Scheduler::setPacesetterDisplay(PhysicalDisplayId pacesetterId) {
+ constexpr PromotionParams kPromotionParams = {.toggleIdleTimer = true};
- promotePacesetterDisplay(pacesetterIdOpt);
+ demotePacesetterDisplay(kPromotionParams);
+ promotePacesetterDisplay(pacesetterId, kPromotionParams);
}
void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr,
@@ -139,16 +140,22 @@
RefreshRateSelectorPtr selectorPtr,
VsyncSchedulePtr schedulePtr,
PhysicalDisplayId activeDisplayId) {
- demotePacesetterDisplay();
+ const bool isPrimary = (ftl::FakeGuard(mDisplayLock), !mPacesetterDisplayId);
- auto [pacesetterVsyncSchedule, isNew] = [&]() FTL_FAKE_GUARD(kMainThreadContext) {
+ // Start the idle timer for the first registered (i.e. primary) display.
+ const PromotionParams promotionParams = {.toggleIdleTimer = isPrimary};
+
+ demotePacesetterDisplay(promotionParams);
+
+ auto [pacesetterVsyncSchedule, isNew] = [&]() REQUIRES(kMainThreadContext) {
std::scoped_lock lock(mDisplayLock);
const bool isNew = mDisplays
.emplace_or_replace(displayId, displayId, std::move(selectorPtr),
std::move(schedulePtr), mFeatures)
.second;
- return std::make_pair(promotePacesetterDisplayLocked(activeDisplayId), isNew);
+ return std::make_pair(promotePacesetterDisplayLocked(activeDisplayId, promotionParams),
+ isNew);
}();
applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
@@ -166,7 +173,8 @@
dispatchHotplug(displayId, Hotplug::Disconnected);
- demotePacesetterDisplay();
+ constexpr PromotionParams kPromotionParams = {.toggleIdleTimer = false};
+ demotePacesetterDisplay(kPromotionParams);
std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
{
@@ -178,7 +186,7 @@
// headless virtual display.)
LOG_ALWAYS_FATAL_IF(mDisplays.empty(), "Cannot unregister all displays!");
- pacesetterVsyncSchedule = promotePacesetterDisplayLocked(activeDisplayId);
+ pacesetterVsyncSchedule = promotePacesetterDisplayLocked(activeDisplayId, kPromotionParams);
}
applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
}
@@ -917,36 +925,38 @@
return mFrameRateOverrideMappings.updateFrameRateOverridesByContent(frameRateOverrides);
}
-void Scheduler::promotePacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt) {
+void Scheduler::promotePacesetterDisplay(PhysicalDisplayId pacesetterId, PromotionParams params) {
std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
-
{
std::scoped_lock lock(mDisplayLock);
- pacesetterVsyncSchedule = promotePacesetterDisplayLocked(pacesetterIdOpt);
+ pacesetterVsyncSchedule = promotePacesetterDisplayLocked(pacesetterId, params);
}
applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
}
std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked(
- std::optional<PhysicalDisplayId> pacesetterIdOpt) {
- // TODO(b/241286431): Choose the pacesetter display.
- mPacesetterDisplayId = pacesetterIdOpt.value_or(mDisplays.begin()->first);
- ALOGI("Display %s is the pacesetter", to_string(*mPacesetterDisplayId).c_str());
+ PhysicalDisplayId pacesetterId, PromotionParams params) {
+ // TODO: b/241286431 - Choose the pacesetter among mDisplays.
+ mPacesetterDisplayId = pacesetterId;
+ ALOGI("Display %s is the pacesetter", to_string(pacesetterId).c_str());
std::shared_ptr<VsyncSchedule> newVsyncSchedulePtr;
if (const auto pacesetterOpt = pacesetterDisplayLocked()) {
const Display& pacesetter = *pacesetterOpt;
- pacesetter.selectorPtr->setIdleTimerCallbacks(
- {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
- .onExpired = [this] { idleTimerCallback(TimerState::Expired); }},
- .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); },
- .onExpired = [this] { kernelIdleTimerCallback(TimerState::Expired); }},
- .vrr = {.onReset = [this] { mSchedulerCallback.vrrDisplayIdle(false); },
- .onExpired = [this] { mSchedulerCallback.vrrDisplayIdle(true); }}});
+ if (!FlagManager::getInstance().connected_display() || params.toggleIdleTimer) {
+ pacesetter.selectorPtr->setIdleTimerCallbacks(
+ {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
+ .onExpired = [this] { idleTimerCallback(TimerState::Expired); }},
+ .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); },
+ .onExpired =
+ [this] { kernelIdleTimerCallback(TimerState::Expired); }},
+ .vrr = {.onReset = [this] { mSchedulerCallback.vrrDisplayIdle(false); },
+ .onExpired = [this] { mSchedulerCallback.vrrDisplayIdle(true); }}});
- pacesetter.selectorPtr->startIdleTimer();
+ pacesetter.selectorPtr->startIdleTimer();
+ }
newVsyncSchedulePtr = pacesetter.schedulePtr;
@@ -966,11 +976,14 @@
}
}
-void Scheduler::demotePacesetterDisplay() {
- // No need to lock for reads on kMainThreadContext.
- if (const auto pacesetterPtr = FTL_FAKE_GUARD(mDisplayLock, pacesetterSelectorPtrLocked())) {
- pacesetterPtr->stopIdleTimer();
- pacesetterPtr->clearIdleTimerCallbacks();
+void Scheduler::demotePacesetterDisplay(PromotionParams params) {
+ if (!FlagManager::getInstance().connected_display() || params.toggleIdleTimer) {
+ // No need to lock for reads on kMainThreadContext.
+ if (const auto pacesetterPtr =
+ FTL_FAKE_GUARD(mDisplayLock, pacesetterSelectorPtrLocked())) {
+ pacesetterPtr->stopIdleTimer();
+ pacesetterPtr->clearIdleTimerCallbacks();
+ }
}
// Clear state that depends on the pacesetter's RefreshRateSelector.
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 1a4aa79..94583db 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -92,8 +92,8 @@
void startTimers();
- // TODO(b/241285191): Remove this API by promoting pacesetter in onScreen{Acquired,Released}.
- void setPacesetterDisplay(std::optional<PhysicalDisplayId>) REQUIRES(kMainThreadContext)
+ // TODO: b/241285191 - Remove this API by promoting pacesetter in onScreen{Acquired,Released}.
+ void setPacesetterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext)
EXCLUDES(mDisplayLock);
using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>;
@@ -377,9 +377,16 @@
void resyncAllToHardwareVsync(bool allowToEnable) EXCLUDES(mDisplayLock);
void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod);
- // Chooses a pacesetter among the registered displays, unless `pacesetterIdOpt` is specified.
- // The new `mPacesetterDisplayId` is never `std::nullopt`.
- void promotePacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterIdOpt = std::nullopt)
+ // TODO: b/241286431 - Remove this option, which assumes that the pacesetter does not change
+ // when a (secondary) display is registered or unregistered. In the short term, this avoids
+ // a deadlock where the main thread joins with the timer thread as the timer thread waits to
+ // lock a mutex held by the main thread.
+ struct PromotionParams {
+ // Whether to stop and start the idle timer. Ignored unless connected_display flag is set.
+ bool toggleIdleTimer;
+ };
+
+ void promotePacesetterDisplay(PhysicalDisplayId pacesetterId, PromotionParams)
REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
// Changes to the displays (e.g. registering and unregistering) must be made
@@ -388,14 +395,16 @@
// MessageQueue and EventThread need to use the new pacesetter's
// VsyncSchedule, and this must happen while mDisplayLock is *not* locked,
// or else we may deadlock with EventThread.
- std::shared_ptr<VsyncSchedule> promotePacesetterDisplayLocked(
- std::optional<PhysicalDisplayId> pacesetterIdOpt = std::nullopt)
+ std::shared_ptr<VsyncSchedule> promotePacesetterDisplayLocked(PhysicalDisplayId pacesetterId,
+ PromotionParams)
REQUIRES(kMainThreadContext, mDisplayLock);
void applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule>) EXCLUDES(mDisplayLock);
- // Blocks until the pacesetter's idle timer thread exits. `mDisplayLock` must not be locked by
- // the caller on the main thread to avoid deadlock, since the timer thread locks it before exit.
- void demotePacesetterDisplay() REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock, mPolicyLock);
+ // If toggleIdleTimer is true, the calling thread blocks until the pacesetter's idle timer
+ // thread exits, in which case mDisplayLock must not be locked by the caller to avoid deadlock,
+ // since the timer thread locks it before exit.
+ void demotePacesetterDisplay(PromotionParams) REQUIRES(kMainThreadContext)
+ EXCLUDES(mDisplayLock, mPolicyLock);
void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr,
PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext)
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7fa523d..1d35730 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1416,6 +1416,8 @@
return future.get();
}
+// TODO: b/241285876 - Restore thread safety analysis once mStateLock below is unconditional.
+[[clang::no_thread_safety_analysis]]
void SurfaceFlinger::finalizeDisplayModeChange(PhysicalDisplayId displayId) {
SFTRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str());
@@ -1431,7 +1433,7 @@
if (const auto oldResolution =
mDisplayModeController.getActiveMode(displayId).modePtr->getResolution();
oldResolution != activeMode.modePtr->getResolution()) {
- Mutex::Autolock lock(mStateLock);
+ ConditionalLock lock(mStateLock, !FlagManager::getInstance().connected_display());
auto& state = mCurrentState.displays.editValueFor(getPhysicalDisplayTokenLocked(displayId));
// We need to generate new sequenceId in order to recreate the display (and this
@@ -1483,7 +1485,7 @@
void SurfaceFlinger::initiateDisplayModeChanges() {
SFTRACE_CALL();
- for (const auto& [displayId, physical] : FTL_FAKE_GUARD(mStateLock, mPhysicalDisplays)) {
+ for (const auto& [displayId, physical] : mPhysicalDisplays) {
auto desiredModeOpt = mDisplayModeController.getDesiredMode(displayId);
if (!desiredModeOpt) {
continue;
@@ -2611,9 +2613,13 @@
return false;
}
- for (const auto [displayId, _] : frameTargets) {
- if (mDisplayModeController.isModeSetPending(displayId)) {
- finalizeDisplayModeChange(displayId);
+ {
+ ConditionalLock lock(mStateLock, FlagManager::getInstance().connected_display());
+
+ for (const auto [displayId, _] : frameTargets) {
+ if (mDisplayModeController.isModeSetPending(displayId)) {
+ finalizeDisplayModeChange(displayId);
+ }
}
}
@@ -2712,9 +2718,16 @@
? &mLayerHierarchyBuilder.getHierarchy()
: nullptr,
updateAttachedChoreographer);
+
+ if (FlagManager::getInstance().connected_display()) {
+ initiateDisplayModeChanges();
+ }
}
- initiateDisplayModeChanges();
+ if (!FlagManager::getInstance().connected_display()) {
+ ftl::FakeGuard guard(mStateLock);
+ initiateDisplayModeChanges();
+ }
updateCursorAsync();
if (!mustComposite) {
@@ -3768,7 +3781,7 @@
if (const auto& physical = state.physical) {
const auto& mode = *physical->activeMode;
mDisplayModeController.setActiveMode(physical->id, mode.getId(), mode.getVsyncRate(),
- mode.getVsyncRate());
+ mode.getPeakFps());
}
display->setLayerFilter(makeLayerFilterForDisplay(display->getId(), state.layerStack));
@@ -5168,7 +5181,7 @@
status_t SurfaceFlinger::setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states,
- Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp,
const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId,
@@ -5183,7 +5196,7 @@
composerState.state.sanitize(permissions);
}
- for (DisplayState& display : displays) {
+ for (DisplayState display : displays) {
display.sanitize(permissions);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3369e00..af504ca 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -560,7 +560,7 @@
sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const;
status_t setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state,
- Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
InputWindowCommands inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers,
bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
@@ -739,9 +739,9 @@
status_t setActiveModeFromBackdoor(const sp<display::DisplayToken>&, DisplayModeId, Fps minFps,
Fps maxFps);
- void initiateDisplayModeChanges() REQUIRES(kMainThreadContext) EXCLUDES(mStateLock);
+ void initiateDisplayModeChanges() REQUIRES(kMainThreadContext) REQUIRES(mStateLock);
void finalizeDisplayModeChange(PhysicalDisplayId) REQUIRES(kMainThreadContext)
- EXCLUDES(mStateLock);
+ REQUIRES(mStateLock);
void dropModeRequest(PhysicalDisplayId) REQUIRES(kMainThreadContext);
void applyActiveMode(PhysicalDisplayId) REQUIRES(kMainThreadContext);
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index d355e72..ebe11fb 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -26,7 +26,6 @@
#include <private/android_filesystem_config.h>
#include <private/gui/ComposerServiceAIDL.h>
#include <ui/DisplayMode.h>
-#include <ui/DisplayState.h>
#include <ui/DynamicDisplayInfo.h>
#include <utils/String8.h>
#include <functional>
@@ -277,7 +276,7 @@
TEST_F(CredentialsTest, CaptureLayersTest) {
setupBackgroundSurface();
sp<GraphicBuffer> outBuffer;
- std::function<status_t()> condition = [=, this]() {
+ std::function<status_t()> condition = [=]() {
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = mBGSurfaceControl->getHandle();
captureArgs.sourceCrop = {0, 0, 1, 1};
@@ -397,56 +396,6 @@
}
}
-TEST_F(CredentialsTest, DisplayTransactionPermissionTest) {
- const auto display = getFirstDisplayToken();
-
- ui::DisplayState displayState;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState));
- const ui::Rotation initialOrientation = displayState.orientation;
-
- // Set display orientation from an untrusted process. This should fail silently.
- {
- UIDFaker f{AID_BIN};
- Transaction transaction;
- Rect layerStackRect;
- Rect displayRect;
- transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90,
- layerStackRect, displayRect);
- transaction.apply(/*synchronous=*/true);
- }
-
- // Verify that the display orientation did not change.
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState));
- ASSERT_EQ(initialOrientation, displayState.orientation);
-
- // Set display orientation from a trusted process.
- {
- UIDFaker f{AID_SYSTEM};
- Transaction transaction;
- Rect layerStackRect;
- Rect displayRect;
- transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90,
- layerStackRect, displayRect);
- transaction.apply(/*synchronous=*/true);
- }
-
- // Verify that the display orientation did change.
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState));
- ASSERT_EQ(initialOrientation + ui::ROTATION_90, displayState.orientation);
-
- // Reset orientation
- {
- UIDFaker f{AID_SYSTEM};
- Transaction transaction;
- Rect layerStackRect;
- Rect displayRect;
- transaction.setDisplayProjection(display, initialOrientation, layerStackRect, displayRect);
- transaction.apply(/*synchronous=*/true);
- }
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState));
- ASSERT_EQ(initialOrientation, displayState.orientation);
-}
-
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/benchmarks/Android.bp b/services/surfaceflinger/tests/benchmarks/Android.bp
new file mode 100644
index 0000000..1c47be34
--- /dev/null
+++ b/services/surfaceflinger/tests/benchmarks/Android.bp
@@ -0,0 +1,31 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_benchmark {
+ name: "surfaceflinger_microbenchmarks",
+ srcs: [
+ ":libsurfaceflinger_mock_sources",
+ ":libsurfaceflinger_sources",
+ "*.cpp",
+ ],
+ defaults: [
+ "libsurfaceflinger_mocks_defaults",
+ "skia_renderengine_deps",
+ "surfaceflinger_defaults",
+ ],
+ static_libs: [
+ "libgmock",
+ "libgtest",
+ "libc++fs",
+ ],
+ header_libs: [
+ "libsurfaceflinger_mocks_headers",
+ "surfaceflinger_tests_common_headers",
+ ],
+}
diff --git a/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp b/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp
new file mode 100644
index 0000000..7641a45
--- /dev/null
+++ b/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 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 <memory>
+#include <optional>
+
+#include <benchmark/benchmark.h>
+
+#include <Client.h> // temporarily needed for LayerCreationArgs
+#include <FrontEnd/LayerCreationArgs.h>
+#include <FrontEnd/LayerLifecycleManager.h>
+#include <LayerLifecycleManagerHelper.h>
+
+namespace android::surfaceflinger {
+
+namespace {
+
+using namespace android::surfaceflinger::frontend;
+
+static void addRemoveLayers(benchmark::State& state) {
+ LayerLifecycleManager lifecycleManager;
+ for (auto _ : state) {
+ std::vector<std::unique_ptr<RequestedLayerState>> layers;
+ layers.emplace_back(LayerLifecycleManagerHelper::rootLayer(1));
+ layers.emplace_back(LayerLifecycleManagerHelper::rootLayer(2));
+ layers.emplace_back(LayerLifecycleManagerHelper::rootLayer(3));
+ lifecycleManager.addLayers(std::move(layers));
+ lifecycleManager.onHandlesDestroyed({{1, "1"}, {2, "2"}, {3, "3"}});
+ lifecycleManager.commitChanges();
+ }
+}
+BENCHMARK(addRemoveLayers);
+
+static void updateClientStates(benchmark::State& state) {
+ LayerLifecycleManager lifecycleManager;
+ std::vector<std::unique_ptr<RequestedLayerState>> layers;
+ layers.emplace_back(LayerLifecycleManagerHelper::rootLayer(1));
+ lifecycleManager.addLayers(std::move(layers));
+ lifecycleManager.commitChanges();
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ auto& transactionState = transactions.back().states.front();
+ transactionState.state.what = layer_state_t::eColorChanged;
+ transactionState.state.color.rgb = {0.f, 0.f, 0.f};
+ transactionState.layerId = 1;
+ lifecycleManager.applyTransactions(transactions);
+ lifecycleManager.commitChanges();
+ int i = 0;
+ for (auto s : state) {
+ if (i++ % 100 == 0) i = 0;
+ transactionState.state.color.b = static_cast<float>(i / 100.f);
+ lifecycleManager.applyTransactions(transactions);
+ lifecycleManager.commitChanges();
+ }
+}
+BENCHMARK(updateClientStates);
+
+static void updateClientStatesNoChanges(benchmark::State& state) {
+ LayerLifecycleManager lifecycleManager;
+ std::vector<std::unique_ptr<RequestedLayerState>> layers;
+ layers.emplace_back(LayerLifecycleManagerHelper::rootLayer(1));
+ lifecycleManager.addLayers(std::move(layers));
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ auto& transactionState = transactions.back().states.front();
+ transactionState.state.what = layer_state_t::eColorChanged;
+ transactionState.state.color.rgb = {0.f, 0.f, 0.f};
+ transactionState.layerId = 1;
+ lifecycleManager.applyTransactions(transactions);
+ lifecycleManager.commitChanges();
+ for (auto _ : state) {
+ lifecycleManager.applyTransactions(transactions);
+ lifecycleManager.commitChanges();
+ }
+}
+BENCHMARK(updateClientStatesNoChanges);
+
+} // namespace
+} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/tests/benchmarks/LocklessQueue_benchmarks.cpp b/services/surfaceflinger/tests/benchmarks/LocklessQueue_benchmarks.cpp
new file mode 100644
index 0000000..60bd58a
--- /dev/null
+++ b/services/surfaceflinger/tests/benchmarks/LocklessQueue_benchmarks.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 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 <memory>
+#include <optional>
+
+#include <benchmark/benchmark.h>
+
+#include <LocklessQueue.h>
+
+namespace android::surfaceflinger {
+
+namespace {
+static void pushPop(benchmark::State& state) {
+ LocklessQueue<std::vector<uint32_t>> queue;
+ for (auto _ : state) {
+ queue.push({10, 5});
+ std::vector<uint32_t> poppedValue = *queue.pop();
+ benchmark::DoNotOptimize(poppedValue);
+ }
+}
+BENCHMARK(pushPop);
+
+} // namespace
+} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/tests/benchmarks/main.cpp b/services/surfaceflinger/tests/benchmarks/main.cpp
new file mode 100644
index 0000000..685c7c6
--- /dev/null
+++ b/services/surfaceflinger/tests/benchmarks/main.cpp
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2024 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 <benchmark/benchmark.h>
+BENCHMARK_MAIN();
diff --git a/services/surfaceflinger/tests/common/Android.bp b/services/surfaceflinger/tests/common/Android.bp
new file mode 100644
index 0000000..2dfa8af
--- /dev/null
+++ b/services/surfaceflinger/tests/common/Android.bp
@@ -0,0 +1,13 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_library_headers {
+ name: "surfaceflinger_tests_common_headers",
+ export_include_dirs: ["."],
+}
diff --git a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h
new file mode 100644
index 0000000..2e5913b
--- /dev/null
+++ b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2024 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 <gui/fake/BufferData.h>
+#include <renderengine/mock/FakeExternalTexture.h>
+#include <ui/ShadowSettings.h>
+
+#include <Client.h> // temporarily needed for LayerCreationArgs
+#include <FrontEnd/LayerCreationArgs.h>
+#include <FrontEnd/LayerHierarchy.h>
+#include <FrontEnd/LayerLifecycleManager.h>
+#include <FrontEnd/LayerSnapshotBuilder.h>
+
+namespace android::surfaceflinger::frontend {
+
+class LayerLifecycleManagerHelper {
+public:
+ LayerLifecycleManagerHelper(LayerLifecycleManager& layerLifecycleManager)
+ : mLifecycleManager(layerLifecycleManager) {}
+ ~LayerLifecycleManagerHelper() = default;
+
+ static LayerCreationArgs createArgs(uint32_t id, bool canBeRoot, uint32_t parentId,
+ uint32_t layerIdToMirror) {
+ LayerCreationArgs args(std::make_optional(id));
+ args.name = "testlayer";
+ args.addToRoot = canBeRoot;
+ args.parentId = parentId;
+ args.layerIdToMirror = layerIdToMirror;
+ return args;
+ }
+
+ static LayerCreationArgs createDisplayMirrorArgs(uint32_t id,
+ ui::LayerStack layerStackToMirror) {
+ LayerCreationArgs args(std::make_optional(id));
+ args.name = "testlayer";
+ args.addToRoot = true;
+ args.layerStackToMirror = layerStackToMirror;
+ return args;
+ }
+
+ static std::unique_ptr<RequestedLayerState> rootLayer(uint32_t id) {
+ return std::make_unique<RequestedLayerState>(createArgs(/*id=*/id, /*canBeRoot=*/true,
+ /*parent=*/UNASSIGNED_LAYER_ID,
+ /*mirror=*/UNASSIGNED_LAYER_ID));
+ }
+
+ static std::unique_ptr<RequestedLayerState> childLayer(uint32_t id, uint32_t parentId) {
+ return std::make_unique<RequestedLayerState>(createArgs(/*id=*/id, /*canBeRoot=*/false,
+ parentId,
+ /*mirror=*/UNASSIGNED_LAYER_ID));
+ }
+
+ static std::vector<TransactionState> setZTransaction(uint32_t id, int32_t z) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eLayerChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.z = z;
+ return transactions;
+ }
+
+ void createRootLayer(uint32_t id) {
+ std::vector<std::unique_ptr<RequestedLayerState>> layers;
+ layers.emplace_back(std::make_unique<RequestedLayerState>(
+ createArgs(/*id=*/id, /*canBeRoot=*/true, /*parent=*/UNASSIGNED_LAYER_ID,
+ /*mirror=*/UNASSIGNED_LAYER_ID)));
+ mLifecycleManager.addLayers(std::move(layers));
+ }
+
+ void createDisplayMirrorLayer(uint32_t id, ui::LayerStack layerStack) {
+ std::vector<std::unique_ptr<RequestedLayerState>> layers;
+ layers.emplace_back(std::make_unique<RequestedLayerState>(
+ createDisplayMirrorArgs(/*id=*/id, layerStack)));
+ mLifecycleManager.addLayers(std::move(layers));
+ }
+
+ void createLayer(uint32_t id, uint32_t parentId) {
+ std::vector<std::unique_ptr<RequestedLayerState>> layers;
+ layers.emplace_back(std::make_unique<RequestedLayerState>(
+ createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/parentId,
+ /*mirror=*/UNASSIGNED_LAYER_ID)));
+ mLifecycleManager.addLayers(std::move(layers));
+ }
+
+ std::vector<TransactionState> reparentLayerTransaction(uint32_t id, uint32_t newParentId) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().parentId = newParentId;
+ transactions.back().states.front().state.what = layer_state_t::eReparent;
+ transactions.back().states.front().relativeParentId = UNASSIGNED_LAYER_ID;
+ transactions.back().states.front().layerId = id;
+ return transactions;
+ }
+
+ void reparentLayer(uint32_t id, uint32_t newParentId) {
+ mLifecycleManager.applyTransactions(reparentLayerTransaction(id, newParentId));
+ }
+
+ std::vector<TransactionState> relativeLayerTransaction(uint32_t id, uint32_t relativeParentId) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().relativeParentId = relativeParentId;
+ transactions.back().states.front().state.what = layer_state_t::eRelativeLayerChanged;
+ transactions.back().states.front().layerId = id;
+ return transactions;
+ }
+
+ void reparentRelativeLayer(uint32_t id, uint32_t relativeParentId) {
+ mLifecycleManager.applyTransactions(relativeLayerTransaction(id, relativeParentId));
+ }
+
+ void removeRelativeZ(uint32_t id) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().state.what = layer_state_t::eLayerChanged;
+ transactions.back().states.front().layerId = id;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setPosition(uint32_t id, float x, float y) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().state.what = layer_state_t::ePositionChanged;
+ transactions.back().states.front().state.x = x;
+ transactions.back().states.front().state.y = y;
+ transactions.back().states.front().layerId = id;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void mirrorLayer(uint32_t id, uint32_t parentId, uint32_t layerIdToMirror) {
+ std::vector<std::unique_ptr<RequestedLayerState>> layers;
+ layers.emplace_back(std::make_unique<RequestedLayerState>(
+ createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/parentId,
+ /*mirror=*/layerIdToMirror)));
+ mLifecycleManager.addLayers(std::move(layers));
+ }
+
+ void updateBackgroundColor(uint32_t id, half alpha) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
+ transactions.back().states.front().state.bgColor.a = alpha;
+ transactions.back().states.front().layerId = id;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void destroyLayerHandle(uint32_t id) { mLifecycleManager.onHandlesDestroyed({{id, "test"}}); }
+
+ void setZ(uint32_t id, int32_t z) {
+ mLifecycleManager.applyTransactions(setZTransaction(id, z));
+ }
+
+ void setCrop(uint32_t id, const Rect& crop) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eCropChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.crop = crop;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setFlags(uint32_t id, uint32_t mask, uint32_t flags) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eFlagsChanged;
+ transactions.back().states.front().state.flags = flags;
+ transactions.back().states.front().state.mask = mask;
+ transactions.back().states.front().layerId = id;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setAlpha(uint32_t id, float alpha) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eAlphaChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.color.a = static_cast<half>(alpha);
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void hideLayer(uint32_t id) {
+ setFlags(id, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
+ }
+
+ void showLayer(uint32_t id) { setFlags(id, layer_state_t::eLayerHidden, 0); }
+
+ void setColor(uint32_t id, half3 rgb = half3(1._hf, 1._hf, 1._hf)) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().state.what = layer_state_t::eColorChanged;
+ transactions.back().states.front().state.color.rgb = rgb;
+ transactions.back().states.front().layerId = id;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setLayerStack(uint32_t id, int32_t layerStack) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eLayerStackChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.layerStack = ui::LayerStack::fromValue(layerStack);
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setTouchableRegion(uint32_t id, Region region) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.windowInfoHandle =
+ sp<gui::WindowInfoHandle>::make();
+ auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo();
+ inputInfo->touchableRegion = region;
+ inputInfo->token = sp<BBinder>::make();
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setInputInfo(uint32_t id, std::function<void(gui::WindowInfo&)> configureInput) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.windowInfoHandle =
+ sp<gui::WindowInfoHandle>::make();
+ auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo();
+ if (!inputInfo->token) {
+ inputInfo->token = sp<BBinder>::make();
+ }
+ configureInput(*inputInfo);
+
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setTouchableRegionCrop(uint32_t id, Region region, uint32_t touchCropId,
+ bool replaceTouchableRegionWithCrop) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.windowInfoHandle =
+ sp<gui::WindowInfoHandle>::make();
+ auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo();
+ inputInfo->touchableRegion = region;
+ inputInfo->replaceTouchableRegionWithCrop = replaceTouchableRegionWithCrop;
+ transactions.back().states.front().touchCropId = touchCropId;
+
+ inputInfo->token = sp<BBinder>::make();
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setBackgroundBlurRadius(uint32_t id, uint32_t backgroundBlurRadius) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eBackgroundBlurRadiusChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.backgroundBlurRadius = backgroundBlurRadius;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setFrameRateSelectionPriority(uint32_t id, int32_t priority) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eFrameRateSelectionPriority;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.frameRateSelectionPriority = priority;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setFrameRate(uint32_t id, float frameRate, int8_t compatibility,
+ int8_t changeFrameRateStrategy) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eFrameRateChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.frameRate = frameRate;
+ transactions.back().states.front().state.frameRateCompatibility = compatibility;
+ transactions.back().states.front().state.changeFrameRateStrategy = changeFrameRateStrategy;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setFrameRateCategory(uint32_t id, int8_t frameRateCategory) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eFrameRateCategoryChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.frameRateCategory = frameRateCategory;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setFrameRateSelectionStrategy(uint32_t id, int8_t strategy) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what =
+ layer_state_t::eFrameRateSelectionStrategyChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.frameRateSelectionStrategy = strategy;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setDefaultFrameRateCompatibility(uint32_t id, int8_t defaultFrameRateCompatibility) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what =
+ layer_state_t::eDefaultFrameRateCompatibilityChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.defaultFrameRateCompatibility =
+ defaultFrameRateCompatibility;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setRoundedCorners(uint32_t id, float radius) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eCornerRadiusChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.cornerRadius = radius;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setBuffer(uint32_t id, std::shared_ptr<renderengine::ExternalTexture> texture) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eBufferChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().externalTexture = texture;
+ transactions.back().states.front().state.bufferData =
+ std::make_shared<fake::BufferData>(texture->getId(), texture->getWidth(),
+ texture->getHeight(), texture->getPixelFormat(),
+ texture->getUsage());
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setBuffer(uint32_t id) {
+ static uint64_t sBufferId = 1;
+ setBuffer(id,
+ std::make_shared<renderengine::mock::
+ FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ sBufferId++,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_PROTECTED /*usage*/));
+ }
+
+ void setBufferCrop(uint32_t id, const Rect& bufferCrop) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eBufferCropChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.bufferCrop = bufferCrop;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setDamageRegion(uint32_t id, const Region& damageRegion) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eSurfaceDamageRegionChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.surfaceDamageRegion = damageRegion;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setDataspace(uint32_t id, ui::Dataspace dataspace) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eDataspaceChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.dataspace = dataspace;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setMatrix(uint32_t id, float dsdx, float dtdx, float dtdy, float dsdy) {
+ layer_state_t::matrix22_t matrix{dsdx, dtdx, dtdy, dsdy};
+
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eMatrixChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.matrix = matrix;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setShadowRadius(uint32_t id, float shadowRadius) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eShadowRadiusChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.shadowRadius = shadowRadius;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setTrustedOverlay(uint32_t id, gui::TrustedOverlay trustedOverlay) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eTrustedOverlayChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.trustedOverlay = trustedOverlay;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setDropInputMode(uint32_t id, gui::DropInputMode dropInputMode) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eDropInputModeChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.dropInputMode = dropInputMode;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+private:
+ LayerLifecycleManager& mLifecycleManager;
+};
+
+} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 518f2a1..9ebef8c 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -58,6 +58,7 @@
],
test_suites: ["device-tests"],
static_libs: ["libc++fs"],
+ header_libs: ["surfaceflinger_tests_common_headers"],
srcs: [
":libsurfaceflinger_mock_sources",
":libsurfaceflinger_sources",
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
index 8b3303c..37cda3e 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -25,13 +25,15 @@
#include "FrontEnd/LayerCreationArgs.h"
#include "FrontEnd/LayerHierarchy.h"
#include "FrontEnd/LayerLifecycleManager.h"
+#include "LayerLifecycleManagerHelper.h"
+
#include "FrontEnd/LayerSnapshotBuilder.h"
namespace android::surfaceflinger::frontend {
-class LayerHierarchyTestBase : public testing::Test {
+class LayerHierarchyTestBase : public testing::Test, public LayerLifecycleManagerHelper {
protected:
- LayerHierarchyTestBase() {
+ LayerHierarchyTestBase() : LayerLifecycleManagerHelper(mLifecycleManager) {
// tree with 3 levels of children
// ROOT
// ├── 1
@@ -55,24 +57,6 @@
createLayer(1221, 122);
}
- LayerCreationArgs createArgs(uint32_t id, bool canBeRoot, uint32_t parentId,
- uint32_t layerIdToMirror) {
- LayerCreationArgs args(std::make_optional(id));
- args.name = "testlayer";
- args.addToRoot = canBeRoot;
- args.parentId = parentId;
- args.layerIdToMirror = layerIdToMirror;
- return args;
- }
-
- LayerCreationArgs createDisplayMirrorArgs(uint32_t id, ui::LayerStack layerStackToMirror) {
- LayerCreationArgs args(std::make_optional(id));
- args.name = "testlayer";
- args.addToRoot = true;
- args.layerStackToMirror = layerStackToMirror;
- return args;
- }
-
std::vector<uint32_t> getTraversalPath(const LayerHierarchy& hierarchy) const {
std::vector<uint32_t> layerIds;
hierarchy.traverse([&layerIds = layerIds](const LayerHierarchy& hierarchy,
@@ -94,98 +78,6 @@
return layerIds;
}
- virtual void createRootLayer(uint32_t id) {
- std::vector<std::unique_ptr<RequestedLayerState>> layers;
- layers.emplace_back(std::make_unique<RequestedLayerState>(
- createArgs(/*id=*/id, /*canBeRoot=*/true, /*parent=*/UNASSIGNED_LAYER_ID,
- /*mirror=*/UNASSIGNED_LAYER_ID)));
- mLifecycleManager.addLayers(std::move(layers));
- }
-
- void createDisplayMirrorLayer(uint32_t id, ui::LayerStack layerStack) {
- std::vector<std::unique_ptr<RequestedLayerState>> layers;
- layers.emplace_back(std::make_unique<RequestedLayerState>(
- createDisplayMirrorArgs(/*id=*/id, layerStack)));
- mLifecycleManager.addLayers(std::move(layers));
- }
-
- virtual void createLayer(uint32_t id, uint32_t parentId) {
- std::vector<std::unique_ptr<RequestedLayerState>> layers;
- layers.emplace_back(std::make_unique<RequestedLayerState>(
- createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/parentId,
- /*mirror=*/UNASSIGNED_LAYER_ID)));
- mLifecycleManager.addLayers(std::move(layers));
- }
-
- std::vector<TransactionState> reparentLayerTransaction(uint32_t id, uint32_t newParentId) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
- transactions.back().states.front().parentId = newParentId;
- transactions.back().states.front().state.what = layer_state_t::eReparent;
- transactions.back().states.front().relativeParentId = UNASSIGNED_LAYER_ID;
- transactions.back().states.front().layerId = id;
- return transactions;
- }
-
- void reparentLayer(uint32_t id, uint32_t newParentId) {
- mLifecycleManager.applyTransactions(reparentLayerTransaction(id, newParentId));
- }
-
- std::vector<TransactionState> relativeLayerTransaction(uint32_t id, uint32_t relativeParentId) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
- transactions.back().states.front().relativeParentId = relativeParentId;
- transactions.back().states.front().state.what = layer_state_t::eRelativeLayerChanged;
- transactions.back().states.front().layerId = id;
- return transactions;
- }
-
- void reparentRelativeLayer(uint32_t id, uint32_t relativeParentId) {
- mLifecycleManager.applyTransactions(relativeLayerTransaction(id, relativeParentId));
- }
-
- void removeRelativeZ(uint32_t id) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
- transactions.back().states.front().state.what = layer_state_t::eLayerChanged;
- transactions.back().states.front().layerId = id;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setPosition(uint32_t id, float x, float y) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
- transactions.back().states.front().state.what = layer_state_t::ePositionChanged;
- transactions.back().states.front().state.x = x;
- transactions.back().states.front().state.y = y;
- transactions.back().states.front().layerId = id;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- virtual void mirrorLayer(uint32_t id, uint32_t parentId, uint32_t layerIdToMirror) {
- std::vector<std::unique_ptr<RequestedLayerState>> layers;
- layers.emplace_back(std::make_unique<RequestedLayerState>(
- createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/parentId,
- /*mirror=*/layerIdToMirror)));
- mLifecycleManager.addLayers(std::move(layers));
- }
-
- void updateBackgroundColor(uint32_t id, half alpha) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
- transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
- transactions.back().states.front().state.bgColor.a = alpha;
- transactions.back().states.front().layerId = id;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void destroyLayerHandle(uint32_t id) { mLifecycleManager.onHandlesDestroyed({{id, "test"}}); }
-
void updateAndVerify(LayerHierarchyBuilder& hierarchyBuilder) {
hierarchyBuilder.update(mLifecycleManager);
mLifecycleManager.commitChanges();
@@ -201,321 +93,6 @@
mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
}
- std::vector<TransactionState> setZTransaction(uint32_t id, int32_t z) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eLayerChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.z = z;
- return transactions;
- }
-
- void setZ(uint32_t id, int32_t z) {
- mLifecycleManager.applyTransactions(setZTransaction(id, z));
- }
-
- void setCrop(uint32_t id, const Rect& crop) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eCropChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.crop = crop;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setFlags(uint32_t id, uint32_t mask, uint32_t flags) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eFlagsChanged;
- transactions.back().states.front().state.flags = flags;
- transactions.back().states.front().state.mask = mask;
- transactions.back().states.front().layerId = id;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setAlpha(uint32_t id, float alpha) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eAlphaChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.color.a = static_cast<half>(alpha);
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void hideLayer(uint32_t id) {
- setFlags(id, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
- }
-
- void showLayer(uint32_t id) { setFlags(id, layer_state_t::eLayerHidden, 0); }
-
- void setColor(uint32_t id, half3 rgb = half3(1._hf, 1._hf, 1._hf)) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
- transactions.back().states.front().state.what = layer_state_t::eColorChanged;
- transactions.back().states.front().state.color.rgb = rgb;
- transactions.back().states.front().layerId = id;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setLayerStack(uint32_t id, int32_t layerStack) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eLayerStackChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.layerStack = ui::LayerStack::fromValue(layerStack);
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setTouchableRegion(uint32_t id, Region region) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.windowInfoHandle =
- sp<gui::WindowInfoHandle>::make();
- auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo();
- inputInfo->touchableRegion = region;
- inputInfo->token = sp<BBinder>::make();
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setInputInfo(uint32_t id, std::function<void(gui::WindowInfo&)> configureInput) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.windowInfoHandle =
- sp<gui::WindowInfoHandle>::make();
- auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo();
- if (!inputInfo->token) {
- inputInfo->token = sp<BBinder>::make();
- }
- configureInput(*inputInfo);
-
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setTouchableRegionCrop(uint32_t id, Region region, uint32_t touchCropId,
- bool replaceTouchableRegionWithCrop) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.windowInfoHandle =
- sp<gui::WindowInfoHandle>::make();
- auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo();
- inputInfo->touchableRegion = region;
- inputInfo->replaceTouchableRegionWithCrop = replaceTouchableRegionWithCrop;
- transactions.back().states.front().touchCropId = touchCropId;
-
- inputInfo->token = sp<BBinder>::make();
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setBackgroundBlurRadius(uint32_t id, uint32_t backgroundBlurRadius) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eBackgroundBlurRadiusChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.backgroundBlurRadius = backgroundBlurRadius;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setFrameRateSelectionPriority(uint32_t id, int32_t priority) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eFrameRateSelectionPriority;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.frameRateSelectionPriority = priority;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setFrameRate(uint32_t id, float frameRate, int8_t compatibility,
- int8_t changeFrameRateStrategy) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eFrameRateChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.frameRate = frameRate;
- transactions.back().states.front().state.frameRateCompatibility = compatibility;
- transactions.back().states.front().state.changeFrameRateStrategy = changeFrameRateStrategy;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setFrameRateCategory(uint32_t id, int8_t frameRateCategory) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eFrameRateCategoryChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.frameRateCategory = frameRateCategory;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setFrameRateSelectionStrategy(uint32_t id, int8_t strategy) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what =
- layer_state_t::eFrameRateSelectionStrategyChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.frameRateSelectionStrategy = strategy;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setDefaultFrameRateCompatibility(uint32_t id, int8_t defaultFrameRateCompatibility) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what =
- layer_state_t::eDefaultFrameRateCompatibilityChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.defaultFrameRateCompatibility =
- defaultFrameRateCompatibility;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setRoundedCorners(uint32_t id, float radius) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eCornerRadiusChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.cornerRadius = radius;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setBuffer(uint32_t id, std::shared_ptr<renderengine::ExternalTexture> texture) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eBufferChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().externalTexture = texture;
- transactions.back().states.front().state.bufferData =
- std::make_shared<fake::BufferData>(texture->getId(), texture->getWidth(),
- texture->getHeight(), texture->getPixelFormat(),
- texture->getUsage());
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setBuffer(uint32_t id) {
- static uint64_t sBufferId = 1;
- setBuffer(id,
- std::make_shared<renderengine::mock::
- FakeExternalTexture>(1U /*width*/, 1U /*height*/,
- sBufferId++,
- HAL_PIXEL_FORMAT_RGBA_8888,
- GRALLOC_USAGE_PROTECTED /*usage*/));
- }
-
- void setBufferCrop(uint32_t id, const Rect& bufferCrop) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eBufferCropChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.bufferCrop = bufferCrop;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setDamageRegion(uint32_t id, const Region& damageRegion) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eSurfaceDamageRegionChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.surfaceDamageRegion = damageRegion;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setDataspace(uint32_t id, ui::Dataspace dataspace) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eDataspaceChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.dataspace = dataspace;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setMatrix(uint32_t id, float dsdx, float dtdx, float dtdy, float dsdy) {
- layer_state_t::matrix22_t matrix{dsdx, dtdx, dtdy, dsdy};
-
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eMatrixChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.matrix = matrix;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setShadowRadius(uint32_t id, float shadowRadius) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eShadowRadiusChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.shadowRadius = shadowRadius;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setTrustedOverlay(uint32_t id, gui::TrustedOverlay trustedOverlay) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eTrustedOverlayChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.trustedOverlay = trustedOverlay;
- mLifecycleManager.applyTransactions(transactions);
- }
-
- void setDropInputMode(uint32_t id, gui::DropInputMode dropInputMode) {
- std::vector<TransactionState> transactions;
- transactions.emplace_back();
- transactions.back().states.push_back({});
-
- transactions.back().states.front().state.what = layer_state_t::eDropInputModeChanged;
- transactions.back().states.front().layerId = id;
- transactions.back().states.front().state.dropInputMode = dropInputMode;
- mLifecycleManager.applyTransactions(transactions);
- }
-
LayerLifecycleManager mLifecycleManager;
};
@@ -523,21 +100,6 @@
protected:
LayerSnapshotTestBase() : LayerHierarchyTestBase() {}
- void createRootLayer(uint32_t id) override {
- LayerHierarchyTestBase::createRootLayer(id);
- setColor(id);
- }
-
- void createLayer(uint32_t id, uint32_t parentId) override {
- LayerHierarchyTestBase::createLayer(id, parentId);
- setColor(parentId);
- }
-
- void mirrorLayer(uint32_t id, uint32_t parent, uint32_t layerToMirror) override {
- LayerHierarchyTestBase::mirrorLayer(id, parent, layerToMirror);
- setColor(id);
- }
-
void update(LayerSnapshotBuilder& snapshotBuilder) {
mHierarchyBuilder.update(mLifecycleManager);
LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
index bc15dec..b4efe0f 100644
--- a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
@@ -61,18 +61,6 @@
class LayerLifecycleManagerTest : public LayerHierarchyTestBase {
protected:
- std::unique_ptr<RequestedLayerState> rootLayer(uint32_t id) {
- return std::make_unique<RequestedLayerState>(createArgs(/*id=*/id, /*canBeRoot=*/true,
- /*parent=*/UNASSIGNED_LAYER_ID,
- /*mirror=*/UNASSIGNED_LAYER_ID));
- }
-
- std::unique_ptr<RequestedLayerState> childLayer(uint32_t id, uint32_t parentId) {
- return std::make_unique<RequestedLayerState>(createArgs(/*id=*/id, /*canBeRoot=*/false,
- parentId,
- /*mirror=*/UNASSIGNED_LAYER_ID));
- }
-
RequestedLayerState* getRequestedLayerState(LayerLifecycleManager& lifecycleManager,
uint32_t layerId) {
return lifecycleManager.getLayerFromId(layerId);
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 9e62f38..216b66b 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -528,7 +528,7 @@
auto setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states,
- Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers,
bool hasListenerCallbacks, std::vector<ListenerCallbacks>& listenerCallbacks,