Merge "Revert "Allow metaState changes from keys not declared by the keyboard"" into main
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 4e3889a..d427ecf 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -3538,7 +3538,7 @@
             // the dumpstate's own activity which is irrelevant.
             RunCommand(
                 SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
-                CommandOptions::WithTimeout(10).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
+                CommandOptions::WithTimeout(30).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
                 false, outFd);
             // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
             // file in the later stages.
diff --git a/include/input/InputConsumerNoResampling.h b/include/input/InputConsumerNoResampling.h
index c98b9cf..228347d 100644
--- a/include/input/InputConsumerNoResampling.h
+++ b/include/input/InputConsumerNoResampling.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <functional>
 #include <map>
 #include <memory>
 #include <optional>
@@ -75,12 +76,13 @@
      * the event is ready to consume.
      * @param looper needs to be sp and not shared_ptr because it inherits from
      * RefBase
-     * @param resampler the resampling strategy to use. If null, no resampling will be
-     * performed.
+     * @param resamplerCreator callable that returns the resampling strategy to be used. If null, no
+     * resampling will be performed. resamplerCreator must never return nullptr.
      */
-    explicit InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel,
-                                       sp<Looper> looper, InputConsumerCallbacks& callbacks,
-                                       std::unique_ptr<Resampler> resampler);
+    explicit InputConsumerNoResampling(
+            const std::shared_ptr<InputChannel>& channel, sp<Looper> looper,
+            InputConsumerCallbacks& callbacks,
+            std::function<std::unique_ptr<Resampler>()> resamplerCreator);
 
     ~InputConsumerNoResampling();
 
@@ -117,7 +119,13 @@
     std::shared_ptr<InputChannel> mChannel;
     sp<Looper> mLooper;
     InputConsumerCallbacks& mCallbacks;
-    std::unique_ptr<Resampler> mResampler;
+    const std::function<std::unique_ptr<Resampler>()> mResamplerCreator;
+
+    /**
+     * A map to manage multidevice resampling. Each contained resampler is never null. This map is
+     * only modified by handleMessages.
+     */
+    std::map<DeviceId, std::unique_ptr<Resampler>> mResamplers;
 
     // Looper-related infrastructure
     /**
@@ -190,7 +198,10 @@
     /**
      * Batch messages that can be batched. When an unbatchable message is encountered, send it
      * to the InputConsumerCallbacks immediately. If there are batches remaining,
-     * notify InputConsumerCallbacks.
+     * notify InputConsumerCallbacks. If a resampleable ACTION_DOWN message is received, then a
+     * resampler is inserted for that deviceId in mResamplers. If a resampleable ACTION_UP or
+     * ACTION_CANCEL message is received then the resampler associated to that deviceId is erased
+     * from mResamplers.
      */
     void handleMessages(std::vector<InputMessage>&& messages);
     /**
diff --git a/include/input/Resampler.h b/include/input/Resampler.h
index dcb25b7..4aaeddd 100644
--- a/include/input/Resampler.h
+++ b/include/input/Resampler.h
@@ -92,12 +92,6 @@
     };
 
     /**
-     * Keeps track of the previous MotionEvent deviceId to enable comparison between the previous
-     * and the current deviceId.
-     */
-    std::optional<DeviceId> mPreviousDeviceId;
-
-    /**
      * Up to two latest samples from MotionEvent. Updated every time resampleMotionEvent is called.
      * Note: We store up to two samples in order to simplify the implementation. Although,
      * calculations are possible with only one previous sample.
diff --git a/libs/binder/OS.h b/libs/binder/OS.h
index 04869a1..64b1fd4 100644
--- a/libs/binder/OS.h
+++ b/libs/binder/OS.h
@@ -27,6 +27,7 @@
 LIBBINDER_EXPORTED void trace_begin(uint64_t tag, const char* name);
 LIBBINDER_EXPORTED void trace_end(uint64_t tag);
 LIBBINDER_EXPORTED void trace_int(uint64_t tag, const char* name, int32_t value);
+LIBBINDER_EXPORTED uint64_t get_trace_enabled_tags();
 
 status_t setNonBlocking(borrowed_fd fd);
 
diff --git a/libs/binder/OS_android.cpp b/libs/binder/OS_android.cpp
index 893ee15..4e9230c 100644
--- a/libs/binder/OS_android.cpp
+++ b/libs/binder/OS_android.cpp
@@ -48,6 +48,10 @@
     atrace_int(tag, name, value);
 }
 
+uint64_t get_trace_enabled_tags() {
+    return atrace_enabled_tags;
+}
+
 } // namespace os
 
 // Legacy trace symbol. To be removed once all of downstream rebuilds.
diff --git a/libs/binder/OS_non_android_linux.cpp b/libs/binder/OS_non_android_linux.cpp
index 0c64eb6..6bba823 100644
--- a/libs/binder/OS_non_android_linux.cpp
+++ b/libs/binder/OS_non_android_linux.cpp
@@ -41,6 +41,10 @@
 
 void trace_int(uint64_t, const char*, int32_t) {}
 
+uint64_t get_trace_enabled_tags() {
+    return 0;
+}
+
 uint64_t GetThreadId() {
     return syscall(__NR_gettid);
 }
diff --git a/libs/binder/include/binder/Trace.h b/libs/binder/include/binder/Trace.h
index 2f450cb..a3e6c8a 100644
--- a/libs/binder/include/binder/Trace.h
+++ b/libs/binder/include/binder/Trace.h
@@ -42,6 +42,7 @@
 void trace_begin(uint64_t tag, const char* name);
 void trace_end(uint64_t tag);
 void trace_int(uint64_t tag, const char* name, int32_t value);
+uint64_t get_trace_enabled_tags();
 } // namespace os
 
 class LIBBINDER_EXPORTED ScopedTrace {
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index af280d3..ff31dd0 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -18,8 +18,10 @@
 #include <android/binder_ibinder_platform.h>
 #include <android/binder_stability.h>
 #include <android/binder_status.h>
+#include <binder/Functional.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IResultReceiver.h>
+#include <binder/Trace.h>
 #if __has_include(<private/android_filesystem_config.h>)
 #include <private/android_filesystem_config.h>
 #endif
@@ -40,6 +42,23 @@
 using ::android::String16;
 using ::android::String8;
 using ::android::wp;
+using ::android::binder::impl::make_scope_guard;
+using ::android::binder::impl::scope_guard;
+using ::android::binder::os::get_trace_enabled_tags;
+using ::android::binder::os::trace_begin;
+using ::android::binder::os::trace_end;
+
+// transaction codes for getInterfaceHash and getInterfaceVersion are defined
+// in file : system/tools/aidl/aidl.cpp
+static constexpr int kGetInterfaceVersionId = 0x00fffffe;
+static const char* kInterfaceVersion = "getInterfaceVersion";
+static constexpr int kGetInterfaceHashId = 0x00fffffd;
+static const char* kInterfaceHash = "getInterfaceHash";
+static const char* kNdkTrace = "AIDL::ndk::";
+static const char* kServerTrace = "::server";
+static const char* kClientTrace = "::client";
+static const char* kSeparator = "::";
+static const char* kUnknownCode = "Unknown_Transaction_Code:";
 
 namespace ABBinderTag {
 
@@ -90,6 +109,51 @@
     return sanitized;
 }
 
+const std::string getMethodName(const AIBinder_Class* clazz, transaction_code_t code) {
+    // TODO(b/150155678) - Move getInterfaceHash and getInterfaceVersion to libbinder and remove
+    // hardcoded cases.
+    if (code <= clazz->getTransactionCodeToFunctionLength() && code >= FIRST_CALL_TRANSACTION) {
+        // Codes have FIRST_CALL_TRANSACTION as added offset. Subtract to access function name
+        return clazz->getFunctionName(code);
+    } else if (code == kGetInterfaceVersionId) {
+        return kInterfaceVersion;
+    } else if (code == kGetInterfaceHashId) {
+        return kInterfaceHash;
+    }
+    return kUnknownCode + std::to_string(code);
+}
+
+const std::string getTraceSectionName(const AIBinder_Class* clazz, transaction_code_t code,
+                                      bool isServer) {
+    if (clazz == nullptr) {
+        ALOGE("class associated with binder is null. Class is needed to add trace with interface "
+              "name and function name");
+        return kNdkTrace;
+    }
+
+    const std::string descriptor = clazz->getInterfaceDescriptorUtf8();
+    const std::string methodName = getMethodName(clazz, code);
+
+    size_t traceSize =
+            strlen(kNdkTrace) + descriptor.size() + strlen(kSeparator) + methodName.size();
+    traceSize += isServer ? strlen(kServerTrace) : strlen(kClientTrace);
+
+    std::string trace;
+    // reserve to avoid repeated allocations
+    trace.reserve(traceSize);
+
+    trace += kNdkTrace;
+    trace += clazz->getInterfaceDescriptorUtf8();
+    trace += kSeparator;
+    trace += methodName;
+    trace += isServer ? kServerTrace : kClientTrace;
+
+    LOG_ALWAYS_FATAL_IF(trace.size() != traceSize, "Trace size mismatch. Expected %zu, got %zu",
+                        traceSize, trace.size());
+
+    return trace;
+}
+
 bool AIBinder::associateClass(const AIBinder_Class* clazz) {
     if (clazz == nullptr) return false;
 
@@ -203,6 +267,17 @@
 
 status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply,
                               binder_flags_t flags) {
+    std::string sectionName;
+    bool tracingEnabled = get_trace_enabled_tags() & ATRACE_TAG_AIDL;
+    if (tracingEnabled) {
+        sectionName = getTraceSectionName(getClass(), code, true /*isServer*/);
+        trace_begin(ATRACE_TAG_AIDL, sectionName.c_str());
+    }
+
+    scope_guard guard = make_scope_guard([&]() {
+        if (tracingEnabled) trace_end(ATRACE_TAG_AIDL);
+    });
+
     if (isUserCommand(code)) {
         if (getClass()->writeHeader && !data.checkInterface(this)) {
             return STATUS_BAD_TYPE;
@@ -385,6 +460,31 @@
       mInterfaceDescriptor(interfaceDescriptor),
       mWideInterfaceDescriptor(interfaceDescriptor) {}
 
+bool AIBinder_Class::setTransactionCodeMap(const char** transactionCodeMap, size_t length) {
+    if (mTransactionCodeToFunction != nullptr) {
+        ALOGE("mTransactionCodeToFunction is already set!");
+        return false;
+    }
+    mTransactionCodeToFunction = transactionCodeMap;
+    mTransactionCodeToFunctionLength = length;
+    return true;
+}
+
+const char* AIBinder_Class::getFunctionName(transaction_code_t code) const {
+    if (mTransactionCodeToFunction == nullptr) {
+        ALOGE("mTransactionCodeToFunction is not set!");
+        return nullptr;
+    }
+
+    if (code < FIRST_CALL_TRANSACTION ||
+        code - FIRST_CALL_TRANSACTION >= mTransactionCodeToFunctionLength) {
+        ALOGE("Function name for requested code not found!");
+        return nullptr;
+    }
+
+    return mTransactionCodeToFunction[code - FIRST_CALL_TRANSACTION];
+}
+
 AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
                                       AIBinder_Class_onCreate onCreate,
                                       AIBinder_Class_onDestroy onDestroy,
@@ -404,6 +504,24 @@
     clazz->onDump = onDump;
 }
 
+void AIBinder_Class_setTransactionCodeToFunctionNameMap(AIBinder_Class* clazz,
+                                                        const char** transactionCodeToFunction,
+                                                        size_t length) {
+    LOG_ALWAYS_FATAL_IF(clazz == nullptr || transactionCodeToFunction == nullptr,
+                        "Valid clazz and transactionCodeToFunction are needed to set code to "
+                        "function mapping.");
+    LOG_ALWAYS_FATAL_IF(!clazz->setTransactionCodeMap(transactionCodeToFunction, length),
+                        "Failed to set transactionCodeToFunction to clazz! Is "
+                        "transactionCodeToFunction already set?");
+}
+
+const char* AIBinder_Class_getFunctionName(AIBinder_Class* clazz, transaction_code_t code) {
+    LOG_ALWAYS_FATAL_IF(
+            clazz == nullptr,
+            "Valid clazz is needed to get function name for requested transaction code");
+    return clazz->getFunctionName(code);
+}
+
 void AIBinder_Class_disableInterfaceTokenHeader(AIBinder_Class* clazz) {
     LOG_ALWAYS_FATAL_IF(clazz == nullptr, "disableInterfaceTokenHeader requires non-null clazz");
 
@@ -734,6 +852,19 @@
 
 binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
                                   AParcel** out, binder_flags_t flags) {
+    const AIBinder_Class* clazz = binder ? binder->getClass() : nullptr;
+
+    std::string sectionName;
+    bool tracingEnabled = get_trace_enabled_tags() & ATRACE_TAG_AIDL;
+    if (tracingEnabled) {
+        sectionName = getTraceSectionName(clazz, code, false /*isServer*/);
+        trace_begin(ATRACE_TAG_AIDL, sectionName.c_str());
+    }
+
+    scope_guard guard = make_scope_guard([&]() {
+        if (tracingEnabled) trace_end(ATRACE_TAG_AIDL);
+    });
+
     if (in == nullptr) {
         ALOGE("%s: requires non-null in parameter", __func__);
         return STATUS_UNEXPECTED_NULL;
@@ -872,4 +1003,4 @@
                         "AIBinder_setInheritRt must be called on a local binder");
 
     localBinder->setInheritRt(inheritRt);
-}
+}
\ No newline at end of file
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index f5b738c..a93dc1f 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -132,6 +132,9 @@
 
     const ::android::String16& getInterfaceDescriptor() const { return mWideInterfaceDescriptor; }
     const char* getInterfaceDescriptorUtf8() const { return mInterfaceDescriptor.c_str(); }
+    bool setTransactionCodeMap(const char** transactionCodeMap, size_t transactionCodeMapSize);
+    const char* getFunctionName(transaction_code_t code) const;
+    size_t getTransactionCodeToFunctionLength() const { return mTransactionCodeToFunctionLength; }
 
     // whether a transaction header should be written
     bool writeHeader = true;
@@ -151,6 +154,10 @@
     // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
     // one.
     const ::android::String16 mWideInterfaceDescriptor;
+    // Array which holds names of the functions
+    const char** mTransactionCodeToFunction = nullptr;
+    // length of mmTransactionCodeToFunctionLength array
+    size_t mTransactionCodeToFunctionLength = 0;
 };
 
 // Ownership is like this (when linked to death):
diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
index af56bf0..8296356 100644
--- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
@@ -30,6 +30,17 @@
 #include <android/binder_auto_utils.h>
 #include <android/binder_ibinder.h>
 
+#if defined(__ANDROID_VENDOR__)
+#include <android/llndk-versioning.h>
+#elif !defined(API_LEVEL_AT_LEAST)
+#if defined(__BIONIC__)
+#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) \
+    (__builtin_available(android sdk_api_level, *))
+#else
+#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (true)
+#endif  // __BIONIC__
+#endif  // __ANDROID_VENDOR__
+
 #if __has_include(<android/binder_shell.h>)
 #include <android/binder_shell.h>
 #define HAS_BINDER_SHELL_COMMAND
@@ -164,6 +175,10 @@
      * Helper method to create a class
      */
     static inline AIBinder_Class* defineClass(const char* interfaceDescriptor,
+                                              AIBinder_Class_onTransact onTransact,
+                                              const char** codeToFunction, size_t functionCount);
+
+    static inline AIBinder_Class* defineClass(const char* interfaceDescriptor,
                                               AIBinder_Class_onTransact onTransact);
 
    private:
@@ -256,6 +271,13 @@
 
 AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor,
                                          AIBinder_Class_onTransact onTransact) {
+
+    return defineClass(interfaceDescriptor, onTransact, nullptr, 0);
+}
+
+AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor,
+                                         AIBinder_Class_onTransact onTransact,
+                                         const char** codeToFunction, size_t functionCount) {
     AIBinder_Class* clazz = AIBinder_Class_define(interfaceDescriptor, ICInterfaceData::onCreate,
                                                   ICInterfaceData::onDestroy, onTransact);
     if (clazz == nullptr) {
@@ -274,6 +296,20 @@
         AIBinder_Class_setHandleShellCommand(clazz, ICInterfaceData::handleShellCommand);
     }
 #endif
+
+// TODO(b/368559337): fix versioning on product partition
+#if !defined(__ANDROID_PRODUCT__) && \
+        (defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__) || __ANDROID_API__ >= 36)
+    if API_LEVEL_AT_LEAST (36, 202504) {
+        if (codeToFunction != nullptr) {
+            AIBinder_Class_setTransactionCodeToFunctionNameMap(clazz, codeToFunction,
+                                                               functionCount);
+        }
+    }
+#else
+    (void)codeToFunction;
+    (void)functionCount;
+#endif  // defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__) || __ANDROID_API__ >= 36
     return clazz;
 }
 
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 72d255e..2f6c4e3 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -219,6 +219,50 @@
 void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __INTRODUCED_IN(29);
 
 /**
+ * Associates a mapping of transaction codes(transaction_code_t) to function names for the given
+ * class.
+ *
+ * Trace messages will use the provided names instead of bare integer codes when set. If not set by
+ * this function, trace messages will only be identified by the bare code. This should be called one
+ * time during clazz initialization. clazz and transactionCodeToFunctionMap should have same
+ * lifetime. Resetting/clearing the transactionCodeToFunctionMap is not allowed.
+ *
+ * Available since API level 36.
+ *
+ * \param clazz class which should use this transaction to code function map.
+ * \param transactionCodeToFunctionMap array of function names indexed by transaction code.
+ * Transaction codes start from 1, functions with transaction code 1 will correspond to index 0 in
+ * transactionCodeToFunctionMap. When defining methods, transaction codes are expected to be
+ * contiguous, and this is required for maximum memory efficiency.
+ * You can use nullptr if certain transaction codes are not used. Lifetime should be same as clazz.
+ * \param length number of elements in the transactionCodeToFunctionMap
+ *
+ * \return true if setting codeToFunction to clazz is successful. return false if clazz or
+ * codeToFunction is nullptr.
+ */
+void AIBinder_Class_setTransactionCodeToFunctionNameMap(AIBinder_Class* clazz,
+                                                        const char** transactionCodeToFunctionMap,
+                                                        size_t length) __INTRODUCED_IN(36);
+
+/**
+ * Get function name associated with transaction code for given class
+ *
+ * This function returns function name associated with provided transaction code for given class.
+ * AIBinder_Class_setTransactionCodeToFunctionNameMap should be called first to associate function
+ * to transaction code mapping.
+ *
+ * Available since API level 36.
+ *
+ * \param clazz class for which function name is requested
+ * \param transactionCode transaction_code_t for which function name is requested.
+ *
+ * \return function name in form of const char* if transaction code is valid for given class.
+ * if transaction code is invalid or transactionCodeToFunctionMap is not set, nullptr is returned
+ */
+const char* AIBinder_Class_getFunctionName(AIBinder_Class* clazz, transaction_code_t code)
+        __INTRODUCED_IN(36);
+
+/**
  * This tells users of this class not to use a transaction header. By default, libbinder_ndk users
  * read/write transaction headers implicitly (in the SDK, this must be manually written by
  * android.os.Parcel#writeInterfaceToken, and it is read/checked with
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index c9e669e..c885816 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -250,6 +250,10 @@
 
 LIBBINDER_NDK36 { # introduced=36
   global:
+    AIBinder_Class_setTransactionCodeToFunctionNameMap;
+    AIBinder_Class_setTransactionCodeToFunctionNameMap; # llndk=202504
+    AIBinder_Class_getFunctionName;
+    AIBinder_Class_getFunctionName; # llndk=202504
     ABinderRpc_registerAccessorProvider; # systemapi
     ABinderRpc_unregisterAccessorProvider; # systemapi
     ABinderRpc_Accessor_new; # systemapi
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 3cd2b9a..e5a3da4 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -1108,6 +1108,37 @@
     EXPECT_EQ(deleteCount, 0);
 }
 
+void* EmptyOnCreate(void* args) {
+    return args;
+}
+void EmptyOnDestroy(void* /*userData*/) {}
+binder_status_t EmptyOnTransact(AIBinder* /*binder*/, transaction_code_t /*code*/,
+                                const AParcel* /*in*/, AParcel* /*out*/) {
+    return STATUS_OK;
+}
+
+TEST(NdkBinder_DeathTest, SetCodeMapTwice) {
+    const char* codeToFunction1[] = {"function-1", "function-2", "function-3"};
+    const char* codeToFunction2[] = {"function-4", "function-5"};
+    const char* interfaceName = "interface_descriptor";
+    AIBinder_Class* clazz =
+            AIBinder_Class_define(interfaceName, EmptyOnCreate, EmptyOnDestroy, EmptyOnTransact);
+    AIBinder_Class_setTransactionCodeToFunctionNameMap(clazz, codeToFunction1, 3);
+    // Reset/clear is not allowed
+    EXPECT_DEATH(AIBinder_Class_setTransactionCodeToFunctionNameMap(clazz, codeToFunction2, 2), "");
+}
+
+TEST(NdkBinder_DeathTest, SetNullCodeMap) {
+    const char* codeToFunction[] = {"function-1", "function-2", "function-3"};
+    const char* interfaceName = "interface_descriptor";
+    AIBinder_Class* clazz =
+            AIBinder_Class_define(interfaceName, EmptyOnCreate, EmptyOnDestroy, EmptyOnTransact);
+    EXPECT_DEATH(AIBinder_Class_setTransactionCodeToFunctionNameMap(nullptr, codeToFunction, 3),
+                 "");
+    EXPECT_DEATH(AIBinder_Class_setTransactionCodeToFunctionNameMap(clazz, nullptr, 0), "");
+    EXPECT_DEATH(AIBinder_Class_setTransactionCodeToFunctionNameMap(nullptr, nullptr, 0), "");
+}
+
 int main(int argc, char* argv[]) {
     ::testing::InitGoogleTest(&argc, argv);
 
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 11150bc..077a33a 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1544,15 +1544,6 @@
     ABinderRpc_Accessor_delete(accessor);
 }
 
-TEST_F(BinderARpcNdk, ARpcDoubleRemoveProvider) {
-    ABinderRpc_AccessorProvider* provider =
-            ABinderRpc_registerAccessorProvider(getAccessor, kARpcSupportedServices,
-                                                kARpcNumSupportedServices, nullptr, nullptr);
-    ASSERT_NE(nullptr, provider);
-    ABinderRpc_unregisterAccessorProvider(provider);
-    EXPECT_DEATH(ABinderRpc_unregisterAccessorProvider(provider), " was already unregistered");
-}
-
 TEST_F(BinderARpcNdk, ARpcNullArgs_ConnectionInfo_new) {
     sockaddr_storage addr;
     EXPECT_EQ(nullptr, ABinderRpc_ConnectionInfo_new(reinterpret_cast<const sockaddr*>(&addr), 0));
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index 3a1471e..e3a3371 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -49,7 +49,8 @@
     return STATUS_UNKNOWN_TRANSACTION;
 }
 
-static AIBinder_Class* g_class = ::ndk::ICInterface::defineClass("ISomeInterface", onTransact);
+static AIBinder_Class* g_class =
+        ::ndk::ICInterface::defineClass("ISomeInterface", onTransact, nullptr, 0);
 
 class BpSomeInterface : public ::ndk::BpCInterface<ISomeInterface> {
 public:
diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp
index 157ab3c..ba9e457 100644
--- a/libs/binder/trusty/OS.cpp
+++ b/libs/binder/trusty/OS.cpp
@@ -42,6 +42,10 @@
 
 void trace_int(uint64_t, const char*, int32_t) {}
 
+uint64_t get_trace_enabled_tags() {
+    return 0;
+}
+
 uint64_t GetThreadId() {
     return 0;
 }
diff --git a/libs/binder/trusty/ndk/include/android/llndk-versioning.h b/libs/binder/trusty/ndk/include/android/llndk-versioning.h
new file mode 100644
index 0000000..e955a34
--- /dev/null
+++ b/libs/binder/trusty/ndk/include/android/llndk-versioning.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+// TODO(b/349936395): set to true for Trusty
+#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (false)
diff --git a/libs/debugstore/rust/Android.bp b/libs/debugstore/rust/Android.bp
index 55ba3c3..9475333 100644
--- a/libs/debugstore/rust/Android.bp
+++ b/libs/debugstore/rust/Android.bp
@@ -23,7 +23,6 @@
     rustlibs: [
         "libcrossbeam_queue",
         "libparking_lot",
-        "libonce_cell",
         "libcxx",
     ],
     shared_libs: ["libutils"],
diff --git a/libs/debugstore/rust/src/core.rs b/libs/debugstore/rust/src/core.rs
index 1dfa512..6bf79d4 100644
--- a/libs/debugstore/rust/src/core.rs
+++ b/libs/debugstore/rust/src/core.rs
@@ -17,12 +17,14 @@
 use super::event_type::EventType;
 use super::storage::Storage;
 use crate::cxxffi::uptimeMillis;
-use once_cell::sync::Lazy;
 use std::fmt;
-use std::sync::atomic::{AtomicU64, Ordering};
+use std::sync::{
+    atomic::{AtomicU64, Ordering},
+    LazyLock,
+};
 
 //  Lazily initialized static instance of DebugStore.
-static INSTANCE: Lazy<DebugStore> = Lazy::new(DebugStore::new);
+static INSTANCE: LazyLock<DebugStore> = LazyLock::new(DebugStore::new);
 
 /// The `DebugStore` struct is responsible for managing debug events and data.
 pub struct DebugStore {
diff --git a/libs/input/InputConsumerNoResampling.cpp b/libs/input/InputConsumerNoResampling.cpp
index cdbc186..ce8bb43 100644
--- a/libs/input/InputConsumerNoResampling.cpp
+++ b/libs/input/InputConsumerNoResampling.cpp
@@ -17,8 +17,6 @@
 #define LOG_TAG "InputConsumerNoResampling"
 #define ATRACE_TAG ATRACE_TAG_INPUT
 
-#include <chrono>
-
 #include <inttypes.h>
 
 #include <android-base/logging.h>
@@ -39,6 +37,8 @@
 
 using std::chrono::nanoseconds;
 
+using android::base::Result;
+
 /**
  * Log debug messages relating to the consumer end of the transport channel.
  * Enable this via "adb shell setprop log.tag.InputTransportConsumer DEBUG" (requires restart)
@@ -169,24 +169,18 @@
     msg.body.timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = presentTime;
     return msg;
 }
-
-bool isPointerEvent(const MotionEvent& motionEvent) {
-    return (motionEvent.getSource() & AINPUT_SOURCE_CLASS_POINTER) == AINPUT_SOURCE_CLASS_POINTER;
-}
 } // namespace
 
-using android::base::Result;
-
 // --- InputConsumerNoResampling ---
 
-InputConsumerNoResampling::InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel,
-                                                     sp<Looper> looper,
-                                                     InputConsumerCallbacks& callbacks,
-                                                     std::unique_ptr<Resampler> resampler)
+InputConsumerNoResampling::InputConsumerNoResampling(
+        const std::shared_ptr<InputChannel>& channel, sp<Looper> looper,
+        InputConsumerCallbacks& callbacks,
+        std::function<std::unique_ptr<Resampler>()> resamplerCreator)
       : mChannel{channel},
         mLooper{looper},
         mCallbacks{callbacks},
-        mResampler{std::move(resampler)},
+        mResamplerCreator{std::move(resamplerCreator)},
         mFdEvents(0) {
     LOG_ALWAYS_FATAL_IF(mLooper == nullptr);
     mCallback = sp<LooperEventCallback>::make(
@@ -319,7 +313,6 @@
 }
 
 void InputConsumerNoResampling::handleMessages(std::vector<InputMessage>&& messages) {
-    // TODO(b/297226446) : add resampling
     for (const InputMessage& msg : messages) {
         if (msg.header.type == InputMessage::Type::MOTION) {
             const int32_t action = msg.body.motion.action;
@@ -329,12 +322,31 @@
                                          action == AMOTION_EVENT_ACTION_HOVER_MOVE) &&
                     (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER) ||
                      isFromSource(source, AINPUT_SOURCE_CLASS_JOYSTICK));
+
+            const bool canResample = (mResamplerCreator != nullptr) &&
+                    (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER));
+            if (canResample) {
+                if (action == AMOTION_EVENT_ACTION_DOWN) {
+                    if (std::unique_ptr<Resampler> resampler = mResamplerCreator();
+                        resampler != nullptr) {
+                        const auto [_, inserted] =
+                                mResamplers.insert(std::pair(deviceId, std::move(resampler)));
+                        LOG_IF(WARNING, !inserted) << deviceId << "already exists in mResamplers";
+                    }
+                }
+            }
+
             if (batchableEvent) {
                 // add it to batch
                 mBatches[deviceId].emplace(msg);
             } else {
                 // consume all pending batches for this device immediately
                 consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/std::nullopt);
+                if (canResample &&
+                    (action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL)) {
+                    LOG_IF(INFO, mResamplers.erase(deviceId) == 0)
+                            << deviceId << "does not exist in mResamplers";
+                }
                 handleMessage(msg);
             }
         } else {
@@ -456,8 +468,13 @@
                                                     std::queue<InputMessage>& messages) {
     std::unique_ptr<MotionEvent> motionEvent;
     std::optional<uint32_t> firstSeqForBatch;
-    const nanoseconds resampleLatency =
-            (mResampler != nullptr) ? mResampler->getResampleLatency() : nanoseconds{0};
+
+    LOG_IF(FATAL, messages.empty()) << "messages queue is empty!";
+    const DeviceId deviceId = messages.front().body.motion.deviceId;
+    const auto resampler = mResamplers.find(deviceId);
+    const nanoseconds resampleLatency = (resampler != mResamplers.cend())
+            ? resampler->second->getResampleLatency()
+            : nanoseconds{0};
     const nanoseconds adjustedFrameTime = nanoseconds{requestedFrameTime} - resampleLatency;
 
     while (!messages.empty() &&
@@ -474,15 +491,17 @@
         }
         messages.pop();
     }
+
     // Check if resampling should be performed.
-    if (motionEvent != nullptr && isPointerEvent(*motionEvent) && mResampler != nullptr) {
-        InputMessage* futureSample = nullptr;
-        if (!messages.empty()) {
-            futureSample = &messages.front();
-        }
-        mResampler->resampleMotionEvent(nanoseconds{requestedFrameTime}, *motionEvent,
-                                        futureSample);
+    InputMessage* futureSample = nullptr;
+    if (!messages.empty()) {
+        futureSample = &messages.front();
     }
+    if ((motionEvent != nullptr) && (resampler != mResamplers.cend())) {
+        resampler->second->resampleMotionEvent(nanoseconds{requestedFrameTime}, *motionEvent,
+                                               futureSample);
+    }
+
     return std::make_pair(std::move(motionEvent), firstSeqForBatch);
 }
 
diff --git a/libs/input/Resampler.cpp b/libs/input/Resampler.cpp
index 51fadf8..328fa68 100644
--- a/libs/input/Resampler.cpp
+++ b/libs/input/Resampler.cpp
@@ -247,11 +247,6 @@
 
 void LegacyResampler::resampleMotionEvent(nanoseconds frameTime, MotionEvent& motionEvent,
                                           const InputMessage* futureSample) {
-    if (mPreviousDeviceId && *mPreviousDeviceId != motionEvent.getDeviceId()) {
-        mLatestSamples.clear();
-    }
-    mPreviousDeviceId = motionEvent.getDeviceId();
-
     const nanoseconds resampleTime = frameTime - RESAMPLE_LATENCY;
 
     updateLatestSamples(motionEvent);
diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl
index e23fc94..31592cd 100644
--- a/libs/input/android/os/IInputConstants.aidl
+++ b/libs/input/android/os/IInputConstants.aidl
@@ -49,6 +49,12 @@
     const int POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000;
 
     /**
+     * The key event triggered a key gesture. Used in policy flag to notify that a key gesture was
+     * triggered using the event.
+     */
+    const int POLICY_FLAG_KEY_GESTURE_TRIGGERED = 0x40000;
+
+    /**
      * Common input event flag used for both motion and key events for a gesture or pointer being
      * canceled.
      */
diff --git a/libs/input/tests/InputConsumer_test.cpp b/libs/input/tests/InputConsumer_test.cpp
index d708316..cbb332e 100644
--- a/libs/input/tests/InputConsumer_test.cpp
+++ b/libs/input/tests/InputConsumer_test.cpp
@@ -16,6 +16,9 @@
 
 #include <input/InputConsumerNoResampling.h>
 
+#include <gtest/gtest.h>
+
+#include <chrono>
 #include <memory>
 #include <optional>
 
@@ -25,7 +28,9 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <input/BlockingQueue.h>
+#include <input/Input.h>
 #include <input/InputEventBuilders.h>
+#include <input/Resampler.h>
 #include <utils/Looper.h>
 #include <utils/StrongPointer.h>
 
@@ -37,8 +42,18 @@
 
 using ::testing::AllOf;
 using ::testing::Matcher;
-using ::testing::Not;
 
+struct Pointer {
+    int32_t id{0};
+    ToolType toolType{ToolType::FINGER};
+    float x{0.0f};
+    float y{0.0f};
+    bool isResampled{false};
+
+    PointerBuilder asPointerBuilder() const {
+        return PointerBuilder{id, toolType}.x(x).y(y).isResampled(isResampled);
+    }
+};
 } // namespace
 
 class InputConsumerTest : public testing::Test, public InputConsumerCallbacks {
@@ -47,9 +62,9 @@
           : mClientTestChannel{std::make_shared<TestInputChannel>("TestChannel")},
             mLooper{sp<Looper>::make(/*allowNonCallbacks=*/false)} {
         Looper::setForThread(mLooper);
-        mConsumer =
-                std::make_unique<InputConsumerNoResampling>(mClientTestChannel, mLooper, *this,
-                                                            std::make_unique<LegacyResampler>());
+        mConsumer = std::make_unique<
+                InputConsumerNoResampling>(mClientTestChannel, mLooper, *this,
+                                           []() { return std::make_unique<LegacyResampler>(); });
     }
 
     void invokeLooperCallback() const {
@@ -71,6 +86,9 @@
         EXPECT_THAT(*motionEvent, matcher);
     }
 
+    InputMessage nextPointerMessage(std::chrono::nanoseconds eventTime, DeviceId deviceId,
+                                    int32_t action, const Pointer& pointer);
+
     std::shared_ptr<TestInputChannel> mClientTestChannel;
     sp<Looper> mLooper;
     std::unique_ptr<InputConsumerNoResampling> mConsumer;
@@ -83,6 +101,7 @@
     BlockingQueue<std::unique_ptr<TouchModeEvent>> mTouchModeEvents;
 
 private:
+    uint32_t mLastSeq{0};
     size_t mOnBatchedInputEventPendingInvocationCount{0};
 
     // InputConsumerCallbacks interface
@@ -118,6 +137,19 @@
     };
 };
 
+InputMessage InputConsumerTest::nextPointerMessage(std::chrono::nanoseconds eventTime,
+                                                   DeviceId deviceId, int32_t action,
+                                                   const Pointer& pointer) {
+    ++mLastSeq;
+    return InputMessageBuilder{InputMessage::Type::MOTION, mLastSeq}
+            .eventTime(eventTime.count())
+            .deviceId(deviceId)
+            .source(AINPUT_SOURCE_TOUCHSCREEN)
+            .action(action)
+            .pointer(pointer.asPointerBuilder())
+            .build();
+}
+
 TEST_F(InputConsumerTest, MessageStreamBatchedInMotionEvent) {
     mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
                                                .eventTime(nanoseconds{0ms}.count())
@@ -235,8 +267,7 @@
                                                .build());
 
     invokeLooperCallback();
-    assertReceivedMotionEvent(AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
-                                    Not(MotionEventIsResampled())));
+    assertReceivedMotionEvent(AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
 
     mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
     mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
@@ -244,4 +275,121 @@
     mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
     mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
 }
+
+/**
+ * The test supposes a 60Hz Vsync rate and a 200Hz input rate. The InputMessages are intertwined as
+ * in a real use cases. The test's two devices should be resampled independently. Moreover, the
+ * InputMessage stream layout for the test is:
+ *
+ * DOWN(0, 0ms)
+ * MOVE(0, 5ms)
+ * MOVE(0, 10ms)
+ * DOWN(1, 15ms)
+ *
+ * CONSUME(16ms)
+ *
+ * MOVE(1, 20ms)
+ * MOVE(1, 25ms)
+ * MOVE(0, 30ms)
+ *
+ * CONSUME(32ms)
+ *
+ * MOVE(0, 35ms)
+ * UP(1, 40ms)
+ * UP(0, 45ms)
+ *
+ * CONSUME(48ms)
+ *
+ * The first field is device ID, and the second field is event time.
+ */
+TEST_F(InputConsumerTest, MultiDeviceResampling) {
+    mClientTestChannel->enqueueMessage(nextPointerMessage(0ms, /*deviceId=*/0,
+                                                          AMOTION_EVENT_ACTION_DOWN,
+                                                          Pointer{.x = 0, .y = 0}));
+
+    mClientTestChannel->assertNoSentMessages();
+
+    invokeLooperCallback();
+    assertReceivedMotionEvent(AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
+                                    WithSampleCount(1)));
+
+    mClientTestChannel->enqueueMessage(nextPointerMessage(5ms, /*deviceId=*/0,
+                                                          AMOTION_EVENT_ACTION_MOVE,
+                                                          Pointer{.x = 1.0f, .y = 2.0f}));
+    mClientTestChannel->enqueueMessage(nextPointerMessage(10ms, /*deviceId=*/0,
+                                                          AMOTION_EVENT_ACTION_MOVE,
+                                                          Pointer{.x = 2.0f, .y = 4.0f}));
+    mClientTestChannel->enqueueMessage(nextPointerMessage(15ms, /*deviceId=*/1,
+                                                          AMOTION_EVENT_ACTION_DOWN,
+                                                          Pointer{.x = 10.0f, .y = 10.0f}));
+
+    invokeLooperCallback();
+    mConsumer->consumeBatchedInputEvents(16'000'000 /*ns*/);
+
+    assertReceivedMotionEvent(AllOf(WithDeviceId(1), WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
+                                    WithSampleCount(1)));
+    assertReceivedMotionEvent(
+            AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithSampleCount(3),
+                  WithSample(/*sampleIndex=*/2,
+                             Sample{11ms,
+                                    {PointerArgs{.x = 2.2f, .y = 4.4f, .isResampled = true}}})));
+
+    mClientTestChannel->enqueueMessage(nextPointerMessage(20ms, /*deviceId=*/1,
+                                                          AMOTION_EVENT_ACTION_MOVE,
+                                                          Pointer{.x = 11.0f, .y = 12.0f}));
+    mClientTestChannel->enqueueMessage(nextPointerMessage(25ms, /*deviceId=*/1,
+                                                          AMOTION_EVENT_ACTION_MOVE,
+                                                          Pointer{.x = 12.0f, .y = 14.0f}));
+    mClientTestChannel->enqueueMessage(nextPointerMessage(30ms, /*deviceId=*/0,
+                                                          AMOTION_EVENT_ACTION_MOVE,
+                                                          Pointer{.x = 5.0f, .y = 6.0f}));
+
+    invokeLooperCallback();
+    assertOnBatchedInputEventPendingWasCalled();
+    mConsumer->consumeBatchedInputEvents(32'000'000 /*ns*/);
+
+    assertReceivedMotionEvent(
+            AllOf(WithDeviceId(1), WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithSampleCount(3),
+                  WithSample(/*sampleIndex=*/2,
+                             Sample{27ms,
+                                    {PointerArgs{.x = 12.4f, .y = 14.8f, .isResampled = true}}})));
+
+    mClientTestChannel->enqueueMessage(nextPointerMessage(35ms, /*deviceId=*/0,
+                                                          AMOTION_EVENT_ACTION_MOVE,
+                                                          Pointer{.x = 8.0f, .y = 9.0f}));
+    mClientTestChannel->enqueueMessage(nextPointerMessage(40ms, /*deviceId=*/1,
+                                                          AMOTION_EVENT_ACTION_UP,
+                                                          Pointer{.x = 12.0f, .y = 14.0f}));
+    mClientTestChannel->enqueueMessage(nextPointerMessage(45ms, /*deviceId=*/0,
+                                                          AMOTION_EVENT_ACTION_UP,
+                                                          Pointer{.x = 8.0f, .y = 9.0f}));
+
+    invokeLooperCallback();
+    mConsumer->consumeBatchedInputEvents(48'000'000 /*ns*/);
+
+    assertReceivedMotionEvent(
+            AllOf(WithDeviceId(1), WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSampleCount(1)));
+
+    assertReceivedMotionEvent(
+            AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithSampleCount(3),
+                  WithSample(/*sampleIndex=*/2,
+                             Sample{37'500'000ns,
+                                    {PointerArgs{.x = 9.5f, .y = 10.5f, .isResampled = true}}})));
+
+    assertReceivedMotionEvent(
+            AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSampleCount(1)));
+
+    // The sequence order is based on the expected consumption. Each sequence number corresponds to
+    // one of the previously enqueued messages.
+    mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
+    mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
+    mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
+    mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
+    mClientTestChannel->assertFinishMessage(/*seq=*/5, /*handled=*/true);
+    mClientTestChannel->assertFinishMessage(/*seq=*/6, /*handled=*/true);
+    mClientTestChannel->assertFinishMessage(/*seq=*/9, /*handled=*/true);
+    mClientTestChannel->assertFinishMessage(/*seq=*/7, /*handled=*/true);
+    mClientTestChannel->assertFinishMessage(/*seq=*/8, /*handled=*/true);
+    mClientTestChannel->assertFinishMessage(/*seq=*/10, /*handled=*/true);
+}
 } // namespace android
diff --git a/libs/input/tests/Resampler_test.cpp b/libs/input/tests/Resampler_test.cpp
index 26dee39..fae8518 100644
--- a/libs/input/tests/Resampler_test.cpp
+++ b/libs/input/tests/Resampler_test.cpp
@@ -87,7 +87,6 @@
 struct InputStream {
     std::vector<InputSample> samples{};
     int32_t action{0};
-    DeviceId deviceId{0};
     /**
      * Converts from InputStream to MotionEvent. Enables calling LegacyResampler methods only with
      * the relevant data for tests.
@@ -100,8 +99,8 @@
     MotionEventBuilder motionEventBuilder =
             MotionEventBuilder(action, AINPUT_SOURCE_CLASS_POINTER)
                     .downTime(0)
-                    .eventTime(static_cast<std::chrono::nanoseconds>(firstSample.eventTime).count())
-                    .deviceId(deviceId);
+                    .eventTime(
+                            static_cast<std::chrono::nanoseconds>(firstSample.eventTime).count());
     for (const Pointer& pointer : firstSample.pointers) {
         const PointerBuilder pointerBuilder =
                 PointerBuilder(pointer.id, pointer.toolType).x(pointer.x).y(pointer.y);
@@ -289,28 +288,6 @@
     assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
 }
 
-TEST_F(ResamplerTest, SinglePointerDifferentDeviceIdBetweenMotionEvents) {
-    MotionEvent motionFromFirstDevice =
-            InputStream{{InputSample{4ms, {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false}}},
-                         InputSample{8ms, {{.id = 0, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
-                        AMOTION_EVENT_ACTION_MOVE,
-                        .deviceId = 0};
-
-    mResampler->resampleMotionEvent(10ms, motionFromFirstDevice, nullptr);
-
-    MotionEvent motionFromSecondDevice =
-            InputStream{{InputSample{11ms,
-                                     {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false}}}},
-                        AMOTION_EVENT_ACTION_MOVE,
-                        .deviceId = 1};
-    const MotionEvent originalMotionEvent = motionFromSecondDevice;
-
-    mResampler->resampleMotionEvent(12ms, motionFromSecondDevice, nullptr);
-    // The MotionEvent should not be resampled because the second event came from a different device
-    // than the previous event.
-    assertMotionEventIsNotResampled(originalMotionEvent, motionFromSecondDevice);
-}
-
 TEST_F(ResamplerTest, SinglePointerSingleSampleInterpolation) {
     MotionEvent motionEvent =
             InputStream{{InputSample{10ms,
diff --git a/libs/input/tests/TestEventMatchers.h b/libs/input/tests/TestEventMatchers.h
index dd2e40c..3589de5 100644
--- a/libs/input/tests/TestEventMatchers.h
+++ b/libs/input/tests/TestEventMatchers.h
@@ -16,18 +16,39 @@
 
 #pragma once
 
+#include <chrono>
 #include <ostream>
+#include <vector>
 
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
 #include <input/Input.h>
 
 namespace android {
 
+namespace {
+
+using ::testing::Matcher;
+
+} // namespace
+
 /**
  * This file contains a copy of Matchers from .../inputflinger/tests/TestEventMatchers.h. Ideally,
  * implementations must not be duplicated.
  * TODO(b/365606513): Find a way to share TestEventMatchers.h between inputflinger and libinput.
  */
 
+struct PointerArgs {
+    float x{0.0f};
+    float y{0.0f};
+    bool isResampled{false};
+};
+
+struct Sample {
+    std::chrono::nanoseconds eventTime{0};
+    std::vector<PointerArgs> pointers{};
+};
+
 class WithDeviceIdMatcher {
 public:
     using is_gtest_matcher = void;
@@ -79,32 +100,88 @@
     return WithMotionActionMatcher(action);
 }
 
-class MotionEventIsResampledMatcher {
+class WithSampleCountMatcher {
 public:
     using is_gtest_matcher = void;
+    explicit WithSampleCountMatcher(size_t sampleCount) : mExpectedSampleCount{sampleCount} {}
 
     bool MatchAndExplain(const MotionEvent& motionEvent, std::ostream*) const {
-        const size_t numSamples = motionEvent.getHistorySize() + 1;
-        const size_t numPointers = motionEvent.getPointerCount();
-        if (numPointers <= 0 || numSamples <= 0) {
+        return (motionEvent.getHistorySize() + 1) == mExpectedSampleCount;
+    }
+
+    void DescribeTo(std::ostream* os) const { *os << "sample count " << mExpectedSampleCount; }
+
+    void DescribeNegationTo(std::ostream* os) const { *os << "different sample count"; }
+
+private:
+    const size_t mExpectedSampleCount;
+};
+
+inline WithSampleCountMatcher WithSampleCount(size_t sampleCount) {
+    return WithSampleCountMatcher(sampleCount);
+}
+
+class WithSampleMatcher {
+public:
+    using is_gtest_matcher = void;
+    explicit WithSampleMatcher(size_t sampleIndex, const Sample& sample)
+          : mSampleIndex{sampleIndex}, mSample{sample} {}
+
+    bool MatchAndExplain(const MotionEvent& motionEvent, std::ostream* os) const {
+        if (motionEvent.getHistorySize() < mSampleIndex) {
+            *os << "sample index out of bounds";
             return false;
         }
-        for (size_t i = 0; i < numPointers; ++i) {
+
+        if (motionEvent.getHistoricalEventTime(mSampleIndex) != mSample.eventTime.count()) {
+            *os << "event time mismatch. sample: "
+                << motionEvent.getHistoricalEventTime(mSampleIndex)
+                << " expected: " << mSample.eventTime.count();
+            return false;
+        }
+
+        if (motionEvent.getPointerCount() != mSample.pointers.size()) {
+            *os << "pointer count mismatch. sample: " << motionEvent.getPointerCount()
+                << " expected: " << mSample.pointers.size();
+            return false;
+        }
+
+        for (size_t pointerIndex = 0; pointerIndex < motionEvent.getPointerCount();
+             ++pointerIndex) {
             const PointerCoords& pointerCoords =
-                    motionEvent.getSamplePointerCoords()[numSamples * numPointers + i];
-            if (!pointerCoords.isResampled) {
+                    *(motionEvent.getHistoricalRawPointerCoords(pointerIndex, mSampleIndex));
+            if ((pointerCoords.getX() != mSample.pointers[pointerIndex].x) ||
+                (pointerCoords.getY() != mSample.pointers[pointerIndex].y)) {
+                *os << "sample coordinates mismatch at pointer index " << pointerIndex
+                    << ". sample: (" << pointerCoords.getX() << ", " << pointerCoords.getY()
+                    << ") expected: (" << mSample.pointers[pointerIndex].x << ", "
+                    << mSample.pointers[pointerIndex].y << ")";
+                return false;
+            }
+            if (motionEvent.isResampled(pointerIndex, mSampleIndex) !=
+                mSample.pointers[pointerIndex].isResampled) {
+                *os << "resampling flag mismatch. sample: "
+                    << motionEvent.isResampled(pointerIndex, mSampleIndex)
+                    << " expected: " << mSample.pointers[pointerIndex].isResampled;
                 return false;
             }
         }
         return true;
     }
 
-    void DescribeTo(std::ostream* os) const { *os << "MotionEvent is resampled."; }
+    void DescribeTo(std::ostream* os) const { *os << "motion event sample properties match."; }
 
-    void DescribeNegationTo(std::ostream* os) const { *os << "MotionEvent is not resampled."; }
+    void DescribeNegationTo(std::ostream* os) const {
+        *os << "motion event sample properties do not match expected properties.";
+    }
+
+private:
+    const size_t mSampleIndex;
+    const Sample mSample;
 };
 
-inline MotionEventIsResampledMatcher MotionEventIsResampled() {
-    return MotionEventIsResampledMatcher();
+inline WithSampleMatcher WithSample(size_t sampleIndex, const Sample& sample) {
+    return WithSampleMatcher(sampleIndex, sample);
 }
+
 } // namespace android
diff --git a/libs/renderengine/benchmark/RenderEngineBench.cpp b/libs/renderengine/benchmark/RenderEngineBench.cpp
index a9264b3..595573d 100644
--- a/libs/renderengine/benchmark/RenderEngineBench.cpp
+++ b/libs/renderengine/benchmark/RenderEngineBench.cpp
@@ -17,6 +17,7 @@
 #include <RenderEngineBench.h>
 #include <android-base/file.h>
 #include <benchmark/benchmark.h>
+#include <com_android_graphics_libgui_flags.h>
 #include <gui/SurfaceComposerClient.h>
 #include <log/log.h>
 #include <renderengine/ExternalTexture.h>
@@ -321,5 +322,7 @@
 BENCHMARK_CAPTURE(BM_homescreen, SkiaGLThreaded, RenderEngine::Threaded::YES,
                   RenderEngine::GraphicsApi::GL);
 
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS_EDGE_EXTENSION_SHADER
 BENCHMARK_CAPTURE(BM_homescreen_edgeExtension, SkiaGLThreaded, RenderEngine::Threaded::YES,
                   RenderEngine::GraphicsApi::GL);
+#endif
diff --git a/libs/vibrator/TEST_MAPPING b/libs/vibrator/TEST_MAPPING
index d782b43..e206761 100644
--- a/libs/vibrator/TEST_MAPPING
+++ b/libs/vibrator/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "postsubmit": [
+  "presubmit": [
     {
       "name": "libvibrator_test"
     }
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 6e35041..6713a5c 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -2141,6 +2141,10 @@
     }
 
     egl_surface_t const* const s = get_surface(surface);
+    if (!s->getNativeWindow()) {
+        setError(EGL_BAD_SURFACE, EGL_FALSE);
+        return EGL_FALSE;
+    }
     native_window_set_buffers_timestamp(s->getNativeWindow(), time);
 
     return EGL_TRUE;
@@ -2405,7 +2409,7 @@
         case 0:
             return EGL_TRUE;
         case -ENOENT:
-            return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
+            return setErrorQuiet(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
         case -ENOSYS:
             return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
         case -EINVAL:
diff --git a/services/vibratorservice/TEST_MAPPING b/services/vibratorservice/TEST_MAPPING
index af48673..1eb3a58 100644
--- a/services/vibratorservice/TEST_MAPPING
+++ b/services/vibratorservice/TEST_MAPPING
@@ -4,11 +4,6 @@
       "name": "libvibratorservice_test"
     }
   ],
-  "postsubmit": [
-    {
-      "name": "libvibratorservice_test"
-    }
-  ],
   "imports": [
     {
       "path": "cts/tests/vibrator"