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, &copyTimeToVariable, &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, &copyTimeToVariable, &callTime1);
+    mProvider.setDeadline(timer, 1'500'000'000, &copyTimeToVariable, &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, &copyTimeToVariable, &callTime1);
+    mProvider.setDeadline(timer, 1'000'000'000, &copyTimeToVariable, &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;
     }