Merge changes I2e0a0d49,Iccbe9cc4 into main
* changes:
Fix FrameRateCategory::NoPreference in SF
Add perfetto trace for layer vote
diff --git a/include/input/PrintTools.h b/include/input/PrintTools.h
index 0e3fbb1..63c0e40 100644
--- a/include/input/PrintTools.h
+++ b/include/input/PrintTools.h
@@ -75,11 +75,12 @@
}
/**
- * Convert a map to string. Both keys and values of the map should be integral type.
+ * Convert a map or multimap to string. Both keys and values of the map should be integral type.
*/
-template <typename K, typename V>
-std::string dumpMap(const std::map<K, V>& map, std::string (*keyToString)(const K&) = constToString,
- std::string (*valueToString)(const V&) = constToString) {
+template <typename T>
+std::string dumpMap(const T& map,
+ std::string (*keyToString)(const typename T::key_type&) = constToString,
+ std::string (*valueToString)(const typename T::mapped_type&) = constToString) {
std::string out;
for (const auto& [k, v] : map) {
if (!out.empty()) {
@@ -104,15 +105,13 @@
return out.empty() ? "{}" : (out + "}");
}
-/**
- * Convert a vector to a string. The values of the vector should be of a type supported by
- * constToString.
- */
+/** Convert a vector to a string. */
template <typename T>
-std::string dumpVector(std::vector<T> values) {
- std::string dump = constToString(values[0]);
+std::string dumpVector(const std::vector<T>& values,
+ std::string (*valueToString)(const T&) = constToString) {
+ std::string dump = valueToString(values[0]);
for (size_t i = 1; i < values.size(); i++) {
- dump += ", " + constToString(values[i]);
+ dump += ", " + valueToString(values[i]);
}
return dump;
}
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 2af5a4a..a0563f9 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -20,3 +20,10 @@
description: "Set to true to enable PointerChoreographer: the new pipeline for showing pointer icons"
bug: "293587049"
}
+
+flag {
+ name: "enable_gestures_library_timer_provider"
+ namespace: "input"
+ description: "Set to true to enable timer support for the touchpad Gestures library"
+ bug: "297192727"
+}
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index 82ee95c..7ec98ea 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -400,7 +400,10 @@
// simply match the existing behavior for protected buffers.) We also never cache any
// buffers while in a protected context.
const bool isProtectedBuffer = buffer->getUsage() & GRALLOC_USAGE_PROTECTED;
- if (isProtectedBuffer || isProtected()) {
+ // Don't attempt to map buffers if we're not gpu sampleable. Callers shouldn't send a buffer
+ // over to RenderEngine.
+ const bool isGpuSampleable = buffer->getUsage() & GRALLOC_USAGE_HW_TEXTURE;
+ if (isProtectedBuffer || isProtected() || !isGpuSampleable) {
return;
}
ATRACE_CALL();
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 7451037..5d1d4af 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -240,9 +240,6 @@
"libinputservice_test",
"Bug-115739809",
"StructLayout_test",
- // currently unused, but still must build correctly
- "inputflinger",
- "libinputflingerhost",
// rust targets
"libinput_rust_test",
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
deleted file mode 100644
index 4d2839f..0000000
--- a/services/inputflinger/host/Android.bp
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (C) 2015 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 {
- // 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_shared {
- name: "libinputflingerhost",
- cpp_std: "c++20",
- srcs: [
- "InputFlinger.cpp",
- "InputDriver.cpp",
- "InputHost.cpp",
- ],
-
- header_libs: ["jni_headers"],
- shared_libs: [
- "libbase",
- "libbinder",
- "libcrypto",
- "libcutils",
- "libinput",
- "liblog",
- "libutils",
- "libhardware",
- ],
- static_libs: [
- "libarect",
- ],
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-parameter",
- // TODO: Move inputflinger to its own process and mark it hidden
- //-fvisibility=hidden
- ],
-
- export_header_lib_headers: ["jni_headers"],
- export_include_dirs: ["."],
-}
-
-//#######################################################################
-// build input flinger executable
-cc_binary {
- name: "inputflinger",
-
- srcs: ["main.cpp"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- shared_libs: [
- "libbase",
- "libbinder",
- "libinputflingerhost",
- "libutils",
- "libinput",
- ],
- static_libs: [
- "libarect",
- "libui-types",
- ],
-}
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
deleted file mode 100644
index de99fc7..0000000
--- a/services/inputflinger/host/InputDriver.cpp
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Copyright (C) 2015 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 <functional>
-#include <stdint.h>
-#include <sys/types.h>
-#include <unordered_map>
-#include <vector>
-
-#define LOG_TAG "InputDriver"
-
-#define LOG_NDEBUG 0
-
-#include "InputDriver.h"
-#include "InputHost.h"
-
-#include <hardware/input.h>
-#include <input/InputDevice.h>
-#include <input/PropertyMap.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#define INDENT2 " "
-
-struct input_property_map {
- std::unique_ptr<android::PropertyMap> propertyMap;
-};
-
-struct input_property {
- android::String8 key;
- android::String8 value;
-};
-
-struct input_device_identifier {
- const char* name;
- const char* uniqueId;
- input_bus_t bus;
- int32_t vendorId;
- int32_t productId;
- int32_t version;
-};
-
-struct input_device_definition {
- std::vector<input_report_definition*> reportDefs;
-};
-
-struct input_device_handle {
- input_device_identifier_t* id;
- input_device_definition_t* def;
-};
-
-struct input_int_usage {
- input_usage_t usage;
- int32_t min;
- int32_t max;
- float resolution;
-};
-
-struct input_collection {
- int32_t arity;
- std::vector<input_int_usage> intUsages;
- std::vector<input_usage_t> boolUsages;
-};
-
-struct InputCollectionIdHasher {
- std::size_t operator()(const input_collection_id& id) const {
- return std::hash<int>()(static_cast<int>(id));
- }
-};
-
-struct input_report_definition {
- std::unordered_map<input_collection_id_t, input_collection, InputCollectionIdHasher> collections;
-};
-
-
-namespace android {
-
-static input_host_callbacks_t kCallbacks = {
- .create_device_identifier = create_device_identifier,
- .create_device_definition = create_device_definition,
- .create_input_report_definition = create_input_report_definition,
- .create_output_report_definition = create_output_report_definition,
- .free_report_definition = free_report_definition,
- .input_device_definition_add_report = input_device_definition_add_report,
- .input_report_definition_add_collection = input_report_definition_add_collection,
- .input_report_definition_declare_usage_int = input_report_definition_declare_usage_int,
- .input_report_definition_declare_usages_bool = input_report_definition_declare_usages_bool,
- .register_device = register_device,
- .input_allocate_report = input_allocate_report,
- .input_report_set_usage_int = input_report_set_usage_int,
- .input_report_set_usage_bool = input_report_set_usage_bool,
- .report_event = report_event,
- .input_get_device_property_map = input_get_device_property_map,
- .input_get_device_property = input_get_device_property,
- .input_get_property_key = input_get_property_key,
- .input_get_property_value = input_get_property_value,
- .input_free_device_property = input_free_device_property,
- .input_free_device_property_map = input_free_device_property_map,
-};
-
-InputDriver::InputDriver(const char* name) : mName(String8(name)) {
- const hw_module_t* module;
- int err = input_open(&module, name);
- LOG_ALWAYS_FATAL_IF(err != 0, "Input module %s not found", name);
- mHal = reinterpret_cast<const input_module_t*>(module);
-}
-
-void InputDriver::init() {
- mHal->init(mHal, static_cast<input_host_t*>(this), kCallbacks);
-}
-
-input_device_identifier_t* InputDriver::createDeviceIdentifier(
- const char* name, int32_t productId, int32_t vendorId,
- input_bus_t bus, const char* uniqueId) {
- auto identifier = new ::input_device_identifier {
- .name = name,
- .uniqueId = uniqueId,
- .bus = bus,
- .vendorId = vendorId,
- .productId = productId,
- };
- // TODO: store this identifier somewhere
- return identifier;
-}
-
-input_device_definition_t* InputDriver::createDeviceDefinition() {
- return new ::input_device_definition;
-}
-
-input_report_definition_t* InputDriver::createInputReportDefinition() {
- return new ::input_report_definition;
-}
-
-input_report_definition_t* InputDriver::createOutputReportDefinition() {
- return new ::input_report_definition;
-}
-
-void InputDriver::freeReportDefinition(input_report_definition_t* reportDef) {
- delete reportDef;
-}
-
-void InputDriver::inputDeviceDefinitionAddReport(input_device_definition_t* d,
- input_report_definition_t* r) {
- d->reportDefs.push_back(r);
-}
-
-void InputDriver::inputReportDefinitionAddCollection(input_report_definition_t* report,
- input_collection_id_t id, int32_t arity) {
- report->collections[id] = {.arity = arity};
-}
-
-void InputDriver::inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
- input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
- float resolution) {
- if (report->collections.find(id) != report->collections.end()) {
- report->collections[id].intUsages.push_back({
- .usage = usage, .min = min, .max = max, .resolution = resolution});
- }
-}
-
-void InputDriver::inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
- input_collection_id_t id, input_usage_t* usage, size_t usageCount) {
- if (report->collections.find(id) != report->collections.end()) {
- for (size_t i = 0; i < usageCount; ++i) {
- report->collections[id].boolUsages.push_back(usage[i]);
- }
- }
-}
-
-input_device_handle_t* InputDriver::registerDevice(input_device_identifier_t* id,
- input_device_definition_t* d) {
- ALOGD("Registering device %s with %zu input reports", id->name, d->reportDefs.size());
- // TODO: save this device handle
- return new input_device_handle{ .id = id, .def = d };
-}
-
-void InputDriver::unregisterDevice(input_device_handle_t* handle) {
- delete handle;
-}
-
-input_report_t* InputDriver::inputAllocateReport(input_report_definition_t* r) {
- ALOGD("Allocating input report for definition %p", r);
- return nullptr;
-}
-
-void InputDriver::inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
- input_usage_t usage, int32_t value, int32_t arity_index) {
-}
-
-void InputDriver::inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
- input_usage_t usage, bool value, int32_t arity_index) {
-}
-
-void InputDriver::reportEvent(input_device_handle_t* d, input_report_t* report) {
- ALOGD("report_event %p for handle %p", report, d);
-}
-
-input_property_map_t* InputDriver::inputGetDevicePropertyMap(input_device_identifier_t* id) {
- InputDeviceIdentifier idi;
- idi.name = id->name;
- idi.uniqueId = id->uniqueId;
- idi.bus = id->bus;
- idi.vendor = id->vendorId;
- idi.product = id->productId;
- idi.version = id->version;
-
- std::string configFile =
- getInputDeviceConfigurationFilePathByDeviceIdentifier(idi,
- InputDeviceConfigurationFileType::
- CONFIGURATION);
- if (configFile.empty()) {
- ALOGD("No input device configuration file found for device '%s'.",
- idi.name.c_str());
- } else {
- std::unique_ptr<input_property_map_t> propMap = std::make_unique<input_property_map_t>();
- android::base::Result<std::unique_ptr<PropertyMap>> result =
- PropertyMap::load(configFile.c_str());
- if (!result.ok()) {
- ALOGE("Error loading input device configuration file for device '%s'. "
- "Using default configuration.",
- idi.name.c_str());
- return nullptr;
- }
- propMap->propertyMap = std::move(*result);
- return propMap.release();
- }
- return nullptr;
-}
-
-input_property_t* InputDriver::inputGetDeviceProperty(input_property_map_t* map, const char* key) {
- if (map != nullptr) {
- std::optional<std::string> value = map->propertyMap->getString(key);
- if (!value.has_value()) {
- return nullptr;
- }
- auto prop = std::make_unique<input_property_t>();
- prop->key = key;
- prop->value = value->c_str();
- return prop.release();
- }
- return nullptr;
-}
-
-const char* InputDriver::inputGetPropertyKey(input_property_t* property) {
- if (property != nullptr) {
- return property->key.c_str();
- }
- return nullptr;
-}
-
-const char* InputDriver::inputGetPropertyValue(input_property_t* property) {
- if (property != nullptr) {
- return property->value.c_str();
- }
- return nullptr;
-}
-
-void InputDriver::inputFreeDeviceProperty(input_property_t* property) {
- if (property != nullptr) {
- delete property;
- }
-}
-
-void InputDriver::inputFreeDevicePropertyMap(input_property_map_t* map) {
- if (map != nullptr) {
- delete map;
- }
-}
-
-void InputDriver::dump(String8& result) {
- result.appendFormat(INDENT2 "HAL Input Driver (%s)\n", mName.c_str());
-}
-
-} // namespace android
-
-// HAL wrapper functions
-
-namespace android {
-
-::input_device_identifier_t* create_device_identifier(input_host_t* host,
- const char* name, int32_t product_id, int32_t vendor_id,
- input_bus_t bus, const char* unique_id) {
- auto driver = static_cast<InputDriverInterface*>(host);
- return driver->createDeviceIdentifier(name, product_id, vendor_id, bus, unique_id);
-}
-
-input_device_definition_t* create_device_definition(input_host_t* host) {
- auto driver = static_cast<InputDriverInterface*>(host);
- return driver->createDeviceDefinition();
-}
-
-input_report_definition_t* create_input_report_definition(input_host_t* host) {
- auto driver = static_cast<InputDriverInterface*>(host);
- return driver->createInputReportDefinition();
-}
-
-input_report_definition_t* create_output_report_definition(input_host_t* host) {
- auto driver = static_cast<InputDriverInterface*>(host);
- return driver->createOutputReportDefinition();
-}
-
-void free_report_definition(input_host_t* host, input_report_definition_t* report_def) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->freeReportDefinition(report_def);
-}
-
-void input_device_definition_add_report(input_host_t* host,
- input_device_definition_t* d, input_report_definition_t* r) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->inputDeviceDefinitionAddReport(d, r);
-}
-
-void input_report_definition_add_collection(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id, int32_t arity) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->inputReportDefinitionAddCollection(report, id, arity);
-}
-
-void input_report_definition_declare_usage_int(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id,
- input_usage_t usage, int32_t min, int32_t max, float resolution) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->inputReportDefinitionDeclareUsageInt(report, id, usage, min, max, resolution);
-}
-
-void input_report_definition_declare_usages_bool(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id,
- input_usage_t* usage, size_t usage_count) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->inputReportDefinitionDeclareUsagesBool(report, id, usage, usage_count);
-}
-
-input_device_handle_t* register_device(input_host_t* host,
- input_device_identifier_t* id, input_device_definition_t* d) {
- auto driver = static_cast<InputDriverInterface*>(host);
- return driver->registerDevice(id, d);
-}
-
-void unregister_device(input_host_t* host, input_device_handle_t* handle) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->unregisterDevice(handle);
-}
-
-input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
- auto driver = static_cast<InputDriverInterface*>(host);
- return driver->inputAllocateReport(r);
-}
-
-void input_report_set_usage_int(input_host_t* host, input_report_t* r,
- input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->inputReportSetUsageInt(r, id, usage, value, arity_index);
-}
-
-void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
- input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->inputReportSetUsageBool(r, id, usage, value, arity_index);
-}
-
-void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->reportEvent(d, report);
-}
-
-input_property_map_t* input_get_device_property_map(input_host_t* host,
- input_device_identifier_t* id) {
- auto driver = static_cast<InputDriverInterface*>(host);
- return driver->inputGetDevicePropertyMap(id);
-}
-
-input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
- const char* key) {
- auto driver = static_cast<InputDriverInterface*>(host);
- return driver->inputGetDeviceProperty(map, key);
-}
-
-const char* input_get_property_key(input_host_t* host, input_property_t* property) {
- auto driver = static_cast<InputDriverInterface*>(host);
- return driver->inputGetPropertyKey(property);
-}
-
-const char* input_get_property_value(input_host_t* host, input_property_t* property) {
- auto driver = static_cast<InputDriverInterface*>(host);
- return driver->inputGetPropertyValue(property);
-}
-
-void input_free_device_property(input_host_t* host, input_property_t* property) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->inputFreeDeviceProperty(property);
-}
-
-void input_free_device_property_map(input_host_t* host, input_property_map_t* map) {
- auto driver = static_cast<InputDriverInterface*>(host);
- driver->inputFreeDevicePropertyMap(map);
-}
-
-} // namespace android
diff --git a/services/inputflinger/host/InputDriver.h b/services/inputflinger/host/InputDriver.h
deleted file mode 100644
index b4c9094..0000000
--- a/services/inputflinger/host/InputDriver.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2015 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 <stdint.h>
-#include <sys/types.h>
-
-#include "InputHost.h"
-
-#include <hardware/input.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-
-// Declare a concrete type for the HAL
-struct input_host {
-};
-
-namespace android {
-
-class InputDriverInterface : public input_host_t, public virtual RefBase {
-protected:
- InputDriverInterface() = default;
- virtual ~InputDriverInterface() = default;
-
-public:
- virtual void init() = 0;
-
- virtual input_device_identifier_t* createDeviceIdentifier(
- const char* name, int32_t productId, int32_t vendorId,
- input_bus_t bus, const char* uniqueId) = 0;
- virtual input_device_definition_t* createDeviceDefinition() = 0;
- virtual input_report_definition_t* createInputReportDefinition() = 0;
- virtual input_report_definition_t* createOutputReportDefinition() = 0;
- virtual void freeReportDefinition(input_report_definition_t* reportDef) = 0;
-
- virtual void inputDeviceDefinitionAddReport(input_device_definition_t* d,
- input_report_definition_t* r) = 0;
- virtual void inputReportDefinitionAddCollection(input_report_definition_t* report,
- input_collection_id_t id, int32_t arity) = 0;
- virtual void inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
- input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
- float resolution) = 0;
- virtual void inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
- input_collection_id_t id, input_usage_t* usage, size_t usageCount) = 0;
-
- virtual input_device_handle_t* registerDevice(input_device_identifier_t* id,
- input_device_definition_t* d) = 0;
- virtual void unregisterDevice(input_device_handle_t* handle) = 0;
-
- virtual input_report_t* inputAllocateReport(input_report_definition_t* r) = 0;
- virtual void inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
- input_usage_t usage, int32_t value, int32_t arity_index) = 0;
- virtual void inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
- input_usage_t usage, bool value, int32_t arity_index) = 0;
- virtual void reportEvent(input_device_handle_t* d, input_report_t* report) = 0;
-
- virtual input_property_map_t* inputGetDevicePropertyMap(input_device_identifier_t* id) = 0;
- virtual input_property_t* inputGetDeviceProperty(input_property_map_t* map,
- const char* key) = 0;
- virtual const char* inputGetPropertyKey(input_property_t* property) = 0;
- virtual const char* inputGetPropertyValue(input_property_t* property) = 0;
- virtual void inputFreeDeviceProperty(input_property_t* property) = 0;
- virtual void inputFreeDevicePropertyMap(input_property_map_t* map) = 0;
-
- virtual void dump(String8& result) = 0;
-};
-
-class InputDriver : public InputDriverInterface {
-public:
- explicit InputDriver(const char* name);
- virtual ~InputDriver() = default;
-
- virtual void init() override;
-
- virtual input_device_identifier_t* createDeviceIdentifier(
- const char* name, int32_t productId, int32_t vendorId,
- input_bus_t bus, const char* uniqueId) override;
- virtual input_device_definition_t* createDeviceDefinition() override;
- virtual input_report_definition_t* createInputReportDefinition() override;
- virtual input_report_definition_t* createOutputReportDefinition() override;
- virtual void freeReportDefinition(input_report_definition_t* reportDef) override;
-
- virtual void inputDeviceDefinitionAddReport(input_device_definition_t* d,
- input_report_definition_t* r) override;
- virtual void inputReportDefinitionAddCollection(input_report_definition_t* report,
- input_collection_id_t id, int32_t arity) override;
- virtual void inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
- input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
- float resolution) override;
- virtual void inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
- input_collection_id_t id, input_usage_t* usage, size_t usageCount) override;
-
- virtual input_device_handle_t* registerDevice(input_device_identifier_t* id,
- input_device_definition_t* d) override;
- virtual void unregisterDevice(input_device_handle_t* handle) override;
-
- virtual input_report_t* inputAllocateReport(input_report_definition_t* r) override;
- virtual void inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
- input_usage_t usage, int32_t value, int32_t arity_index) override;
- virtual void inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
- input_usage_t usage, bool value, int32_t arity_index) override;
- virtual void reportEvent(input_device_handle_t* d, input_report_t* report) override;
-
- virtual input_property_map_t* inputGetDevicePropertyMap(input_device_identifier_t* id) override;
- virtual input_property_t* inputGetDeviceProperty(input_property_map_t* map,
- const char* key) override;
- virtual const char* inputGetPropertyKey(input_property_t* property) override;
- virtual const char* inputGetPropertyValue(input_property_t* property) override;
- virtual void inputFreeDeviceProperty(input_property_t* property) override;
- virtual void inputFreeDevicePropertyMap(input_property_map_t* map) override;
-
- virtual void dump(String8& result) override;
-
-private:
- String8 mName;
- const input_module_t* mHal;
-};
-
-
-extern "C" {
-
-input_device_identifier_t* create_device_identifier(input_host_t* host,
- const char* name, int32_t product_id, int32_t vendor_id,
- input_bus_t bus, const char* unique_id);
-
-input_device_definition_t* create_device_definition(input_host_t* host);
-
-input_report_definition_t* create_input_report_definition(input_host_t* host);
-
-input_report_definition_t* create_output_report_definition(input_host_t* host);
-
-void free_report_definition(input_host_t* host, input_report_definition_t* report_def);
-
-void input_device_definition_add_report(input_host_t* host,
- input_device_definition_t* d, input_report_definition_t* r);
-
-void input_report_definition_add_collection(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id, int32_t arity);
-
-void input_report_definition_declare_usage_int(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id,
- input_usage_t usage, int32_t min, int32_t max, float resolution);
-
-void input_report_definition_declare_usages_bool(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id,
- input_usage_t* usage, size_t usage_count);
-
-
-input_device_handle_t* register_device(input_host_t* host,
- input_device_identifier_t* id, input_device_definition_t* d);
-
-void unregister_device(input_host_t* host, input_device_handle_t* handle);
-
-input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r);
-
-void input_report_set_usage_int(input_host_t* host, input_report_t* r,
- input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index);
-
-void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
- input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index);
-
-void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report);
-
-input_property_map_t* input_get_device_property_map(input_host_t* host,
- input_device_identifier_t* id);
-
-input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
- const char* key);
-
-const char* input_get_property_key(input_host_t* host, input_property_t* property);
-
-const char* input_get_property_value(input_host_t* host, input_property_t* property);
-
-void input_free_device_property(input_host_t* host, input_property_t* property);
-
-void input_free_device_property_map(input_host_t* host, input_property_map_t* map);
-}
-
-} // namespace android
diff --git a/services/inputflinger/host/InputFlinger.cpp b/services/inputflinger/host/InputFlinger.cpp
deleted file mode 100644
index d974c43..0000000
--- a/services/inputflinger/host/InputFlinger.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputFlinger"
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/PermissionCache.h>
-#include <hardware/input.h>
-#include <log/log.h>
-#include <private/android_filesystem_config.h>
-
-#include "InputFlinger.h"
-#include "InputDriver.h"
-
-namespace android {
-
-const String16 sAccessInputFlingerPermission("android.permission.ACCESS_INPUT_FLINGER");
-const String16 sDumpPermission("android.permission.DUMP");
-
-
-InputFlinger::InputFlinger() :
- BnInputFlinger() {
- ALOGI("InputFlinger is starting");
- mHost = new InputHost();
- mHost->registerInputDriver(new InputDriver(INPUT_INSTANCE_EVDEV));
-}
-
-InputFlinger::~InputFlinger() {
-}
-
-status_t InputFlinger::dump(int fd, const Vector<String16>& args) {
- String8 result;
- const IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_SHELL)
- && !PermissionCache::checkPermission(sDumpPermission, pid, uid)) {
- result.appendFormat("Permission Denial: "
- "can't dump InputFlinger from pid=%d, uid=%d\n", pid, uid);
- } else {
- dumpInternal(result);
- }
- write(fd, result.c_str(), result.size());
- return OK;
-}
-
-void InputFlinger::dumpInternal(String8& result) {
- result.append("INPUT FLINGER (dumpsys inputflinger)\n");
- mHost->dump(result);
-}
-
-}; // namespace android
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
deleted file mode 100644
index 388988b..0000000
--- a/services/inputflinger/host/InputFlinger.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "InputHost.h"
-
-#include <android/os/BnInputFlinger.h>
-#include <binder/Binder.h>
-#include <cutils/compiler.h>
-#include <utils/String16.h>
-#include <utils/String8.h>
-#include <utils/StrongPointer.h>
-
-using android::gui::FocusRequest;
-using android::os::BnInputFlinger;
-
-namespace android {
-
-class InputFlinger : public BnInputFlinger {
-public:
- static char const* getServiceName() ANDROID_API {
- return "inputflinger";
- }
-
- InputFlinger() ANDROID_API;
-
- status_t dump(int fd, const Vector<String16>& args) override;
- binder::Status createInputChannel(const std::string&, InputChannel*) override {
- return binder::Status::ok();
- }
- binder::Status removeInputChannel(const sp<IBinder>&) override { return binder::Status::ok(); }
- binder::Status setFocusedWindow(const FocusRequest&) override { return binder::Status::ok(); }
-
-private:
- ~InputFlinger() override;
-
- void dumpInternal(String8& result);
-
- sp<InputHostInterface> mHost;
-};
-
-} // namespace android
diff --git a/services/inputflinger/host/InputHost.cpp b/services/inputflinger/host/InputHost.cpp
deleted file mode 100644
index 094200a..0000000
--- a/services/inputflinger/host/InputHost.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2015 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 <vector>
-
-#include "InputDriver.h"
-#include "InputHost.h"
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#define INDENT " "
-
-namespace android {
-
-void InputHost::registerInputDriver(InputDriverInterface* driver) {
- LOG_ALWAYS_FATAL_IF(driver == nullptr, "Cannot register a nullptr as an InputDriver!");
- driver->init();
- mDrivers.push_back(driver);
-}
-
-void InputHost::dump(String8& result) {
- result.append(INDENT "Input Drivers:\n");
- for (size_t i = 0; i < mDrivers.size(); i++) {
- mDrivers[i]->dump(result);
- }
-}
-
-} // namespace android
diff --git a/services/inputflinger/host/InputHost.h b/services/inputflinger/host/InputHost.h
deleted file mode 100644
index bdc4225..0000000
--- a/services/inputflinger/host/InputHost.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2015 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 <vector>
-
-#include <hardware/input.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/StrongPointer.h>
-
-#include "InputDriver.h"
-
-namespace android {
-
-class InputDriverInterface;
-
-class InputHostInterface : public virtual RefBase {
-protected:
- InputHostInterface() = default;
- virtual ~InputHostInterface() = default;
-
-public:
-
- virtual void registerInputDriver(InputDriverInterface* driver) = 0;
-
- virtual void dump(String8& result) = 0;
-};
-
-class InputHost : public InputHostInterface {
-public:
- InputHost() = default;
-
- virtual void registerInputDriver(InputDriverInterface* driver) override;
-
- virtual void dump(String8& result) override;
-
-private:
- std::vector<sp<InputDriverInterface>> mDrivers;
-};
-
-} // namespace android
diff --git a/services/inputflinger/host/inputflinger.rc b/services/inputflinger/host/inputflinger.rc
deleted file mode 100644
index 4130ddc..0000000
--- a/services/inputflinger/host/inputflinger.rc
+++ /dev/null
@@ -1,5 +0,0 @@
-service inputflinger /system/bin/inputflinger
- class main
- user system
- group input wakelock
-# onrestart restart zygote
diff --git a/services/inputflinger/host/main.cpp b/services/inputflinger/host/main.cpp
deleted file mode 100644
index 0a517cc..0000000
--- a/services/inputflinger/host/main.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <binder/BinderService.h>
-#include "InputFlinger.h"
-
-using namespace android;
-
-int main(int, char**) {
- ProcessState::self()->setThreadPoolMaxThreadCount(4);
- BinderService<InputFlinger>::publishAndJoinThreadPool(true);
- return 0;
-}
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 8fe6411..e1806a0 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -69,6 +69,7 @@
"mapper/gestures/HardwareProperties.cpp",
"mapper/gestures/HardwareStateConverter.cpp",
"mapper/gestures/PropertyProvider.cpp",
+ "mapper/gestures/TimerProvider.cpp",
],
}
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 0aea0b3..5766b14 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -946,6 +946,7 @@
device->dump(dump, eventHubDevStr);
}
+ dump += StringPrintf(INDENT "NextTimeout: %" PRId64 "\n", mNextTimeout);
dump += INDENT "Configuration:\n";
dump += INDENT2 "ExcludedDeviceNames: [";
for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index c3c9fdb..c76fec7 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -25,6 +25,7 @@
#include <android-base/stringprintf.h>
#include <android/input.h>
+#include <com_android_input_flags.h>
#include <ftl/enum.h>
#include <input/PrintTools.h>
#include <linux/input-event-codes.h>
@@ -34,8 +35,11 @@
#include "TouchCursorInputMapperCommon.h"
#include "TouchpadInputMapper.h"
#include "gestures/HardwareProperties.h"
+#include "gestures/TimerProvider.h"
#include "ui/Rotation.h"
+namespace input_flags = com::android::input::flags;
+
namespace android {
namespace {
@@ -238,6 +242,7 @@
: InputMapper(deviceContext, readerConfig),
mGestureInterpreter(NewGestureInterpreter(), DeleteGestureInterpreter),
mPointerController(getContext()->getPointerController(getDeviceId())),
+ mTimerProvider(*getContext()),
mStateConverter(deviceContext, mMotionAccumulator),
mGestureConverter(*getContext(), deviceContext, getDeviceId()),
mCapturedEventConverter(*getContext(), deviceContext, mMotionAccumulator, getDeviceId()),
@@ -259,8 +264,12 @@
// 2) TouchpadInputMapper is stored as a unique_ptr and not moved.
mGestureInterpreter->SetPropProvider(const_cast<GesturesPropProvider*>(&gesturePropProvider),
&mPropertyProvider);
+ if (input_flags::enable_gestures_library_timer_provider()) {
+ mGestureInterpreter->SetTimerProvider(const_cast<GesturesTimerProvider*>(
+ &kGestureTimerProvider),
+ &mTimerProvider);
+ }
mGestureInterpreter->SetCallback(gestureInterpreterCallback, this);
- // TODO(b/251196347): set a timer provider, so the library can use timers.
}
TouchpadInputMapper::~TouchpadInputMapper() {
@@ -268,14 +277,14 @@
mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
}
- // The gesture interpreter's destructor will call its property provider's free function for all
- // gesture properties, in this case calling PropertyProvider::freeProperty using a raw pointer
- // to mPropertyProvider. Depending on the declaration order in TouchpadInputMapper.h, this may
- // happen after mPropertyProvider has been destructed, causing allocation errors. Depending on
- // declaration order to avoid crashes seems rather fragile, so explicitly clear the property
- // provider here to ensure all the freeProperty calls happen before mPropertyProvider is
- // destructed.
+ // The gesture interpreter's destructor will try to free its property and timer providers,
+ // calling PropertyProvider::freeProperty and TimerProvider::freeTimer using a raw pointers.
+ // Depending on the declaration order in TouchpadInputMapper.h, those providers may have already
+ // been freed, causing allocation errors or use-after-free bugs. Depending on declaration order
+ // to avoid this seems rather fragile, so explicitly clear the providers here to ensure all the
+ // freeProperty and freeTimer calls happen before the providers are destructed.
mGestureInterpreter->SetPropProvider(nullptr, nullptr);
+ mGestureInterpreter->SetTimerProvider(nullptr, nullptr);
}
uint32_t TouchpadInputMapper::getSources() const {
@@ -293,9 +302,6 @@
void TouchpadInputMapper::dump(std::string& dump) {
dump += INDENT2 "Touchpad Input Mapper:\n";
- if (mProcessing) {
- dump += INDENT3 "Currently processing a hardware state\n";
- }
if (mResettingInterpreter) {
dump += INDENT3 "Currently resetting gesture interpreter\n";
}
@@ -304,6 +310,12 @@
dump += addLinePrefix(mGestureConverter.dump(), INDENT4);
dump += INDENT3 "Gesture properties:\n";
dump += addLinePrefix(mPropertyProvider.dump(), INDENT4);
+ if (input_flags::enable_gestures_library_timer_provider()) {
+ dump += INDENT3 "Timer provider:\n";
+ dump += addLinePrefix(mTimerProvider.dump(), INDENT4);
+ } else {
+ dump += INDENT3 "Timer provider: disabled by flag\n";
+ }
dump += INDENT3 "Captured event converter:\n";
dump += addLinePrefix(mCapturedEventConverter.dump(), INDENT4);
dump += StringPrintf(INDENT3 "DisplayId: %s\n", toString(mDisplayId).c_str());
@@ -449,13 +461,18 @@
std::list<NotifyArgs> TouchpadInputMapper::sendHardwareState(nsecs_t when, nsecs_t readTime,
SelfContainedHardwareState schs) {
ALOGD_IF(DEBUG_TOUCHPAD_GESTURES, "New hardware state: %s", schs.state.String().c_str());
- mProcessing = true;
mGestureInterpreter->PushHardwareState(&schs.state);
- mProcessing = false;
-
return processGestures(when, readTime);
}
+std::list<NotifyArgs> TouchpadInputMapper::timeoutExpired(nsecs_t when) {
+ if (!input_flags::enable_gestures_library_timer_provider()) {
+ return {};
+ }
+ mTimerProvider.triggerCallbacks(when);
+ return processGestures(when, when);
+}
+
void TouchpadInputMapper::consumeGesture(const Gesture* gesture) {
ALOGD_IF(DEBUG_TOUCHPAD_GESTURES, "Gesture ready: %s", gesture->String().c_str());
if (mResettingInterpreter) {
@@ -463,10 +480,6 @@
// ignore any gestures produced from the interpreter while we're resetting it.
return;
}
- if (!mProcessing) {
- ALOGE("Received gesture outside of the normal processing flow; ignoring it.");
- return;
- }
mGesturesToProcess.push_back(*gesture);
}
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index 47d712e..a68ae43 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -34,6 +34,7 @@
#include "gestures/GestureConverter.h"
#include "gestures/HardwareStateConverter.h"
#include "gestures/PropertyProvider.h"
+#include "gestures/TimerProvider.h"
#include "include/gestures.h"
@@ -56,6 +57,7 @@
ConfigurationChanges changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> timeoutExpired(nsecs_t when) override;
void consumeGesture(const Gesture* gesture);
@@ -80,6 +82,7 @@
std::shared_ptr<PointerControllerInterface> mPointerController;
PropertyProvider mPropertyProvider;
+ TimerProvider mTimerProvider;
// The MultiTouchMotionAccumulator is shared between the HardwareStateConverter and
// CapturedTouchpadEventConverter, so that if the touchpad is captured or released while touches
@@ -92,7 +95,6 @@
CapturedTouchpadEventConverter mCapturedEventConverter;
bool mPointerCaptured = false;
- bool mProcessing = false;
bool mResettingInterpreter = false;
std::vector<Gesture> mGesturesToProcess;
diff --git a/services/inputflinger/reader/mapper/gestures/TimerProvider.cpp b/services/inputflinger/reader/mapper/gestures/TimerProvider.cpp
new file mode 100644
index 0000000..df2f260
--- /dev/null
+++ b/services/inputflinger/reader/mapper/gestures/TimerProvider.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2023 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 "TimerProvider.h"
+
+#include <chrono>
+#include <string>
+
+#include <android-base/logging.h>
+#include <input/PrintTools.h>
+
+namespace android {
+
+namespace {
+
+nsecs_t stimeToNsecs(stime_t time) {
+ return std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::duration<stime_t>(time))
+ .count();
+}
+
+stime_t nsecsToStime(nsecs_t time) {
+ return std::chrono::duration_cast<std::chrono::duration<stime_t>>(
+ std::chrono::nanoseconds(time))
+ .count();
+}
+
+GesturesTimer* createTimer(void* data) {
+ return static_cast<TimerProvider*>(data)->createTimer();
+}
+
+void setDeadline(void* data, GesturesTimer* timer, stime_t delay, GesturesTimerCallback callback,
+ void* callbackData) {
+ static_cast<TimerProvider*>(data)->setDeadline(timer, stimeToNsecs(delay), callback,
+ callbackData);
+};
+
+void cancelTimer(void* data, GesturesTimer* timer) {
+ static_cast<TimerProvider*>(data)->cancelTimer(timer);
+}
+
+void freeTimer(void* data, GesturesTimer* timer) {
+ static_cast<TimerProvider*>(data)->freeTimer(timer);
+}
+
+} // namespace
+
+const GesturesTimerProvider kGestureTimerProvider = {
+ .create_fn = createTimer,
+ .set_fn = setDeadline,
+ .cancel_fn = cancelTimer,
+ .free_fn = freeTimer,
+};
+
+TimerProvider::TimerProvider(InputReaderContext& context) : mReaderContext(context) {}
+
+std::string TimerProvider::dump() {
+ std::string dump;
+ auto timerPtrToString = [](const std::unique_ptr<GesturesTimer>& timer) {
+ return std::to_string(timer->id);
+ };
+ dump += "Timer IDs: " + dumpVector<std::unique_ptr<GesturesTimer>>(mTimers, timerPtrToString) +
+ "\n";
+ dump += "Deadlines and corresponding timer IDs:\n";
+ dump += addLinePrefix(dumpMap(mDeadlines, constToString,
+ [](const Deadline& deadline) {
+ return std::to_string(deadline.timerId);
+ }),
+ " ") +
+ "\n";
+ return dump;
+}
+
+void TimerProvider::triggerCallbacks(nsecs_t when) {
+ while (!mDeadlines.empty() && when >= mDeadlines.begin()->first) {
+ const auto& deadlinePair = mDeadlines.begin();
+ deadlinePair->second.callback(when);
+ mDeadlines.erase(deadlinePair);
+ }
+ requestTimeout();
+}
+
+GesturesTimer* TimerProvider::createTimer() {
+ mTimers.push_back(std::make_unique<GesturesTimer>());
+ mTimers.back()->id = mNextTimerId;
+ mNextTimerId++;
+ return mTimers.back().get();
+}
+
+void TimerProvider::setDeadline(GesturesTimer* timer, nsecs_t delay, GesturesTimerCallback callback,
+ void* callbackData) {
+ setDeadlineWithoutRequestingTimeout(timer, delay, callback, callbackData);
+ requestTimeout();
+}
+
+void TimerProvider::setDeadlineWithoutRequestingTimeout(GesturesTimer* timer, nsecs_t delay,
+ GesturesTimerCallback callback,
+ void* callbackData) {
+ const nsecs_t now = getCurrentTime();
+ const nsecs_t time = now + delay;
+ std::function<void(nsecs_t)> wrappedCallback = [=, this](nsecs_t triggerTime) {
+ stime_t nextDelay = callback(nsecsToStime(triggerTime), callbackData);
+ if (nextDelay >= 0.0) {
+ // When rescheduling a deadline, we know that we're running inside a call to
+ // triggerCallbacks, at the end of which requestTimeout will be called. This means that
+ // we don't want to call the public setDeadline, as that will request a timeout before
+ // triggerCallbacks has removed this current deadline, resulting in a request for a
+ // timeout that has already passed.
+ setDeadlineWithoutRequestingTimeout(timer, stimeToNsecs(nextDelay), callback,
+ callbackData);
+ }
+ };
+ mDeadlines.insert({time, Deadline(wrappedCallback, timer->id)});
+}
+
+void TimerProvider::cancelTimer(GesturesTimer* timer) {
+ int id = timer->id;
+ std::erase_if(mDeadlines, [id](const auto& item) { return item.second.timerId == id; });
+ requestTimeout();
+}
+
+void TimerProvider::freeTimer(GesturesTimer* timer) {
+ cancelTimer(timer);
+ std::erase_if(mTimers, [timer](std::unique_ptr<GesturesTimer>& t) { return t.get() == timer; });
+}
+
+void TimerProvider::requestTimeout() {
+ if (!mDeadlines.empty()) {
+ // Because a std::multimap is sorted by key, we simply use the time for the first entry.
+ mReaderContext.requestTimeoutAtTime(mDeadlines.begin()->first);
+ }
+}
+
+nsecs_t TimerProvider::getCurrentTime() {
+ return systemTime(SYSTEM_TIME_MONOTONIC);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/gestures/TimerProvider.h b/services/inputflinger/reader/mapper/gestures/TimerProvider.h
new file mode 100644
index 0000000..7c870e0
--- /dev/null
+++ b/services/inputflinger/reader/mapper/gestures/TimerProvider.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2023 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 <functional>
+#include <list>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <utils/Timers.h>
+
+#include "InputReaderContext.h"
+#include "NotifyArgs.h"
+#include "include/gestures.h"
+
+namespace android {
+
+extern const GesturesTimerProvider kGestureTimerProvider;
+
+// Implementation of a gestures library timer provider, which allows the library to set and cancel
+// callbacks.
+class TimerProvider {
+public:
+ TimerProvider(InputReaderContext& context);
+ virtual ~TimerProvider() = default;
+
+ // Disable copy and move, since pointers to TimerProvider objects are used in callbacks.
+ TimerProvider(const TimerProvider&) = delete;
+ TimerProvider& operator=(const TimerProvider&) = delete;
+
+ std::string dump();
+ void triggerCallbacks(nsecs_t when);
+
+ // Methods to be called by the gestures library:
+ GesturesTimer* createTimer();
+ void setDeadline(GesturesTimer* timer, nsecs_t delay, GesturesTimerCallback callback,
+ void* callbackData);
+ void cancelTimer(GesturesTimer* timer);
+ void freeTimer(GesturesTimer* timer);
+
+protected:
+ // A wrapper for the system clock, to allow tests to override it.
+ virtual nsecs_t getCurrentTime();
+
+private:
+ void setDeadlineWithoutRequestingTimeout(GesturesTimer* timer, nsecs_t delay,
+ GesturesTimerCallback callback, void* callbackData);
+ // Requests a timeout from the InputReader for the nearest deadline in mDeadlines. Must be
+ // called whenever mDeadlines is modified.
+ void requestTimeout();
+
+ InputReaderContext& mReaderContext;
+ int mNextTimerId = 0;
+ std::vector<std::unique_ptr<GesturesTimer>> mTimers;
+
+ struct Deadline {
+ Deadline(std::function<void(nsecs_t)> callback, int timerId)
+ : callback(callback), timerId(timerId) {}
+ const std::function<void(nsecs_t)> callback;
+ const int timerId;
+ };
+
+ std::multimap<nsecs_t /*time*/, Deadline> mDeadlines;
+};
+
+} // namespace android
+
+// Represents a "timer" registered by the gestures library. In practice, this just means a set of
+// deadlines that can be cancelled as a group. The library's API requires this to be in the
+// top-level namespace.
+struct GesturesTimer {
+ int id = -1;
+};
\ No newline at end of file
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 6410046..d87a5a7 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -63,6 +63,7 @@
"PropertyProvider_test.cpp",
"SlopController_test.cpp",
"SyncQueue_test.cpp",
+ "TimerProvider_test.cpp",
"TestInputListener.cpp",
"TestInputListenerMatchers.cpp",
"TouchpadInputMapper_test.cpp",
diff --git a/services/inputflinger/tests/TimerProvider_test.cpp b/services/inputflinger/tests/TimerProvider_test.cpp
new file mode 100644
index 0000000..cb28823
--- /dev/null
+++ b/services/inputflinger/tests/TimerProvider_test.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2023 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 "gestures/TimerProvider.h"
+
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "InterfaceMocks.h"
+#include "TestConstants.h"
+#include "include/gestures.h"
+
+namespace android {
+
+namespace {
+
+class TestTimerProvider : public TimerProvider {
+public:
+ TestTimerProvider(InputReaderContext& context) : TimerProvider(context) {}
+
+ void setCurrentTime(nsecs_t time) { mCurrentTime = time; }
+
+protected:
+ nsecs_t getCurrentTime() override { return mCurrentTime; }
+
+private:
+ nsecs_t mCurrentTime = 0;
+};
+
+stime_t pushTimeOntoVector(stime_t triggerTime, void* data) {
+ std::vector<stime_t>* times = static_cast<std::vector<stime_t>*>(data);
+ times->push_back(triggerTime);
+ return NO_DEADLINE;
+}
+
+stime_t copyTimeToVariable(stime_t triggerTime, void* data) {
+ stime_t* time = static_cast<stime_t*>(data);
+ *time = triggerTime;
+ return NO_DEADLINE;
+}
+
+stime_t incrementInt(stime_t triggerTime, void* data) {
+ int* count = static_cast<int*>(data);
+ *count += 1;
+ return NO_DEADLINE;
+}
+
+} // namespace
+
+using testing::AtLeast;
+
+class TimerProviderTest : public testing::Test {
+public:
+ TimerProviderTest() : mProvider(mMockContext) {}
+
+protected:
+ void triggerCallbacksWithFakeTime(nsecs_t time) {
+ mProvider.setCurrentTime(time);
+ mProvider.triggerCallbacks(time);
+ }
+
+ MockInputReaderContext mMockContext;
+ TestTimerProvider mProvider;
+};
+
+TEST_F(TimerProviderTest, SingleDeadlineTriggersWhenTimeoutIsExactlyOnTime) {
+ GesturesTimer* timer = mProvider.createTimer();
+ std::vector<stime_t> callTimes;
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(3);
+
+ // Call through kGestureTimerProvider in this test case, so that we cover the stime_t to nsecs_t
+ // conversion code. This is why the delay is 1.0 rather than 1'000'000'000 here.
+ kGestureTimerProvider.set_fn(&mProvider, timer, 1.0, &pushTimeOntoVector, &callTimes);
+
+ triggerCallbacksWithFakeTime(900'000'000);
+ triggerCallbacksWithFakeTime(999'999'999);
+ EXPECT_EQ(0u, callTimes.size());
+ triggerCallbacksWithFakeTime(1'000'000'000);
+ ASSERT_EQ(1u, callTimes.size());
+ EXPECT_NEAR(1.0, callTimes[0], EPSILON);
+
+ // Now that the timer has triggered, it shouldn't trigger again if we get another timeout from
+ // InputReader.
+ triggerCallbacksWithFakeTime(1'300'000'000);
+ EXPECT_EQ(1u, callTimes.size());
+}
+
+TEST_F(TimerProviderTest, SingleDeadlineTriggersWhenTimeoutIsLate) {
+ GesturesTimer* timer = mProvider.createTimer();
+ stime_t callTime = -1.0;
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(1);
+ mProvider.setDeadline(timer, 1'000'000'000, ©TimeToVariable, &callTime);
+
+ triggerCallbacksWithFakeTime(1'010'000'000);
+ EXPECT_NEAR(1.01, callTime, EPSILON);
+}
+
+TEST_F(TimerProviderTest, SingleRescheduledDeadlineTriggers) {
+ GesturesTimer* timer = mProvider.createTimer();
+ std::vector<stime_t> callTimes;
+ auto callback = [](stime_t triggerTime, void* callbackData) {
+ std::vector<stime_t>* times = static_cast<std::vector<stime_t>*>(callbackData);
+ times->push_back(triggerTime);
+ if (times->size() < 2) {
+ return 1.0;
+ } else {
+ return NO_DEADLINE;
+ }
+ };
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(1);
+ // The deadline should be rescheduled for 2.01s, since the first triggerCallbacks call is 0.01s
+ // late.
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(2'010'000'000)).Times(1);
+
+ mProvider.setDeadline(timer, 1'000'000'000, callback, &callTimes);
+
+ triggerCallbacksWithFakeTime(1'010'000'000);
+ ASSERT_EQ(1u, callTimes.size());
+ EXPECT_NEAR(1.01, callTimes[0], EPSILON);
+
+ triggerCallbacksWithFakeTime(2'020'000'000);
+ ASSERT_EQ(2u, callTimes.size());
+ EXPECT_NEAR(1.01, callTimes[0], EPSILON);
+ EXPECT_NEAR(2.02, callTimes[1], EPSILON);
+
+ triggerCallbacksWithFakeTime(3'000'000'000);
+ EXPECT_EQ(2u, callTimes.size());
+}
+
+TEST_F(TimerProviderTest, MultipleDeadlinesTriggerWithMultipleTimeouts) {
+ GesturesTimer* timer = mProvider.createTimer();
+ std::vector<stime_t> callTimes1;
+ std::vector<stime_t> callTimes2;
+
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(AtLeast(1));
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'500'000'000)).Times(1);
+
+ mProvider.setDeadline(timer, 1'000'000'000, &pushTimeOntoVector, &callTimes1);
+ mProvider.setDeadline(timer, 1'500'000'000, &pushTimeOntoVector, &callTimes2);
+
+ EXPECT_EQ(0u, callTimes1.size());
+ EXPECT_EQ(0u, callTimes2.size());
+
+ triggerCallbacksWithFakeTime(1'010'000'000);
+ ASSERT_EQ(1u, callTimes1.size());
+ EXPECT_NEAR(1.01, callTimes1[0], EPSILON);
+ EXPECT_EQ(0u, callTimes2.size());
+
+ triggerCallbacksWithFakeTime(1'500'000'000);
+ EXPECT_EQ(1u, callTimes1.size());
+ ASSERT_EQ(1u, callTimes2.size());
+ EXPECT_NEAR(1.5, callTimes2[0], EPSILON);
+}
+
+TEST_F(TimerProviderTest, MultipleDeadlinesTriggerWithOneLateTimeout) {
+ GesturesTimer* timer = mProvider.createTimer();
+ stime_t callTime1 = -1.0;
+ stime_t callTime2 = -1.0;
+
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(AtLeast(1));
+
+ mProvider.setDeadline(timer, 1'000'000'000, ©TimeToVariable, &callTime1);
+ mProvider.setDeadline(timer, 1'500'000'000, ©TimeToVariable, &callTime2);
+
+ triggerCallbacksWithFakeTime(1'510'000'000);
+ EXPECT_NEAR(1.51, callTime1, EPSILON);
+ EXPECT_NEAR(1.51, callTime2, EPSILON);
+}
+
+TEST_F(TimerProviderTest, MultipleDeadlinesAtSameTimeTriggerTogether) {
+ GesturesTimer* timer = mProvider.createTimer();
+ stime_t callTime1 = -1.0;
+ stime_t callTime2 = -1.0;
+
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(AtLeast(1));
+
+ mProvider.setDeadline(timer, 1'000'000'000, ©TimeToVariable, &callTime1);
+ mProvider.setDeadline(timer, 1'000'000'000, ©TimeToVariable, &callTime2);
+
+ triggerCallbacksWithFakeTime(1'000'000'000);
+ EXPECT_NEAR(1.0, callTime1, EPSILON);
+ EXPECT_NEAR(1.0, callTime2, EPSILON);
+}
+
+TEST_F(TimerProviderTest, MultipleTimersTriggerCorrectly) {
+ GesturesTimer* timer1 = mProvider.createTimer();
+ GesturesTimer* timer2 = mProvider.createTimer();
+ std::vector<stime_t> callTimes1;
+ std::vector<stime_t> callTimes2;
+
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(500'000'000)).Times(AtLeast(1));
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'250'000'000)).Times(1);
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'500'000'000)).Times(1);
+
+ mProvider.setDeadline(timer1, 500'000'000, &pushTimeOntoVector, &callTimes1);
+ mProvider.setDeadline(timer1, 1'250'000'000, &pushTimeOntoVector, &callTimes1);
+ mProvider.setDeadline(timer1, 1'500'000'000, &pushTimeOntoVector, &callTimes1);
+ mProvider.setDeadline(timer2, 750'000'000, &pushTimeOntoVector, &callTimes2);
+ mProvider.setDeadline(timer2, 1'250'000'000, &pushTimeOntoVector, &callTimes2);
+
+ triggerCallbacksWithFakeTime(800'000'000);
+ ASSERT_EQ(1u, callTimes1.size());
+ EXPECT_NEAR(0.8, callTimes1[0], EPSILON);
+ ASSERT_EQ(1u, callTimes2.size());
+ EXPECT_NEAR(0.8, callTimes2[0], EPSILON);
+
+ triggerCallbacksWithFakeTime(1'250'000'000);
+ ASSERT_EQ(2u, callTimes1.size());
+ EXPECT_NEAR(1.25, callTimes1[1], EPSILON);
+ ASSERT_EQ(2u, callTimes2.size());
+ EXPECT_NEAR(1.25, callTimes2[1], EPSILON);
+
+ triggerCallbacksWithFakeTime(1'501'000'000);
+ ASSERT_EQ(3u, callTimes1.size());
+ EXPECT_NEAR(1.501, callTimes1[2], EPSILON);
+ EXPECT_EQ(2u, callTimes2.size());
+}
+
+TEST_F(TimerProviderTest, CancelledTimerDoesntTrigger) {
+ GesturesTimer* timer = mProvider.createTimer();
+ int numCalls = 0;
+
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(500'000'000)).Times(AtLeast(1));
+ mProvider.setDeadline(timer, 500'000'000, &incrementInt, &numCalls);
+ mProvider.setDeadline(timer, 1'000'000'000, &incrementInt, &numCalls);
+ mProvider.cancelTimer(timer);
+
+ triggerCallbacksWithFakeTime(1'100'000'000);
+ EXPECT_EQ(0, numCalls);
+}
+
+TEST_F(TimerProviderTest, CancellingOneTimerDoesntAffectOthers) {
+ GesturesTimer* timer1 = mProvider.createTimer();
+ GesturesTimer* timer2 = mProvider.createTimer();
+ int numCalls1 = 0;
+ int numCalls2 = 0;
+
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(500'000'000)).Times(AtLeast(1));
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(1);
+
+ mProvider.setDeadline(timer1, 500'000'000, &incrementInt, &numCalls1);
+ mProvider.setDeadline(timer2, 500'000'000, &incrementInt, &numCalls2);
+ mProvider.setDeadline(timer2, 1'000'000'000, &incrementInt, &numCalls2);
+ mProvider.cancelTimer(timer1);
+
+ triggerCallbacksWithFakeTime(501'000'000);
+ EXPECT_EQ(0, numCalls1);
+ EXPECT_EQ(1, numCalls2);
+
+ triggerCallbacksWithFakeTime(1'000'000'000);
+ EXPECT_EQ(0, numCalls1);
+ EXPECT_EQ(2, numCalls2);
+}
+
+TEST_F(TimerProviderTest, CancellingOneTimerCausesNewTimeoutRequestForAnother) {
+ GesturesTimer* timer1 = mProvider.createTimer();
+ GesturesTimer* timer2 = mProvider.createTimer();
+ auto callback = [](stime_t, void*) { return NO_DEADLINE; };
+
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(500'000'000)).Times(AtLeast(1));
+
+ mProvider.setDeadline(timer1, 500'000'000, callback, nullptr);
+ mProvider.setDeadline(timer2, 1'000'000'000, callback, nullptr);
+
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(1);
+ mProvider.cancelTimer(timer1);
+}
+
+TEST_F(TimerProviderTest, CancelledTimerCanBeReused) {
+ GesturesTimer* timer = mProvider.createTimer();
+ int numCallsBeforeCancellation = 0;
+ int numCallsAfterCancellation = 0;
+
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(500'000'000)).Times(1);
+ EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(1);
+
+ mProvider.setDeadline(timer, 500'000'000, &incrementInt, &numCallsBeforeCancellation);
+ mProvider.cancelTimer(timer);
+ mProvider.setDeadline(timer, 1'000'000'000, &incrementInt, &numCallsAfterCancellation);
+
+ triggerCallbacksWithFakeTime(1'000'000'000);
+ EXPECT_EQ(0, numCallsBeforeCancellation);
+ EXPECT_EQ(1, numCallsAfterCancellation);
+}
+
+TEST_F(TimerProviderTest, FreeingTimerCancelsFirst) {
+ GesturesTimer* timer = mProvider.createTimer();
+ int numCalls = 0;
+
+ mProvider.setDeadline(timer, 1'000'000'000, &incrementInt, &numCalls);
+ mProvider.freeTimer(timer);
+
+ triggerCallbacksWithFakeTime(1'000'000'000);
+ EXPECT_EQ(0, numCalls);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 06c5e4c..2dc7332 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -148,18 +148,6 @@
"libvulkan",
],
sanitize: {
- // By using the address sanitizer, we not only uncover any issues
- // with the test, but also any issues with the code under test.
- //
- // Note: If you get an runtime link error like:
- //
- // CANNOT LINK EXECUTABLE "/data/local/tmp/libcompositionengine_test": library "libclang_rt.asan-aarch64-android.so" not found
- //
- // it is because the address sanitizer shared objects are not installed
- // by default in the system image.
- //
- // You can either "make dist tests" before flashing, or set this
- // option to false temporarily.
- address: true,
+ hwaddress: true,
},
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1a08244..312a412 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5385,6 +5385,13 @@
// TODO(b/238781169) remove after screenshot refactor, currently screenshots
// requires to read drawing state from binder thread. So we need to fix that
// before removing this.
+ if (what & layer_state_t::eBufferTransformChanged) {
+ if (layer->setTransform(s.bufferTransform)) flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eTransformToDisplayInverseChanged) {
+ if (layer->setTransformToDisplayInverse(s.transformToDisplayInverse))
+ flags |= eTraversalNeeded;
+ }
if (what & layer_state_t::eCropChanged) {
if (layer->setCrop(s.crop)) flags |= eTraversalNeeded;
}