Merge "Refactor obtaining display in SF main thread" into main
diff --git a/cmds/installd/file_parsing.h b/cmds/installd/file_parsing.h
index 88801ca..0ec5abb 100644
--- a/cmds/installd/file_parsing.h
+++ b/cmds/installd/file_parsing.h
@@ -51,7 +51,7 @@
 }
 
 template<typename Func>
-bool ParseFile(std::string_view str_file, Func parse) {
+bool ParseFile(const std::string& str_file, Func parse) {
   std::ifstream ifs(str_file);
   if (!ifs.is_open()) {
     return false;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 7a855e1..6594aa6 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -15,7 +15,6 @@
  */
 
 #define LOG_TAG "BpBinder"
-#define ATRACE_TAG ATRACE_TAG_AIDL
 //#define LOG_NDEBUG 0
 
 #include <binder/BpBinder.h>
@@ -24,15 +23,10 @@
 #include <binder/IResultReceiver.h>
 #include <binder/RpcSession.h>
 #include <binder/Stability.h>
+#include <binder/Trace.h>
 
 #include <stdio.h>
 
-#ifndef __TRUSTY__
-#include <cutils/trace.h>
-#else
-#define ATRACE_INT(...)
-#endif
-
 #include "BuildFlags.h"
 #include "file.h"
 
@@ -216,7 +210,7 @@
         sTrackingMap[trackedUid]++;
     }
     uint32_t numProxies = sBinderProxyCount.fetch_add(1, std::memory_order_relaxed);
-    ATRACE_INT("binder_proxies", numProxies);
+    binder::os::trace_int(ATRACE_TAG_AIDL, "binder_proxies", numProxies);
     uint32_t numLastWarned = sBinderProxyCountWarned.load(std::memory_order_relaxed);
     uint32_t numNextWarn = numLastWarned + kBinderProxyCountWarnInterval;
     if (numProxies >= numNextWarn) {
@@ -640,8 +634,8 @@
             }
         }
     }
-    [[maybe_unused]] uint32_t numProxies = --sBinderProxyCount;
-    ATRACE_INT("binder_proxies", numProxies);
+    uint32_t numProxies = --sBinderProxyCount;
+    binder::os::trace_int(ATRACE_TAG_AIDL, "binder_proxies", numProxies);
     if (ipc) {
         ipc->expungeHandle(binderHandle(), this);
         ipc->decWeakHandle(binderHandle());
diff --git a/libs/binder/OS.h b/libs/binder/OS.h
index 5703eb7..04869a1 100644
--- a/libs/binder/OS.h
+++ b/libs/binder/OS.h
@@ -26,6 +26,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);
 
 status_t setNonBlocking(borrowed_fd fd);
 
diff --git a/libs/binder/OS_android.cpp b/libs/binder/OS_android.cpp
index 1eace85..893ee15 100644
--- a/libs/binder/OS_android.cpp
+++ b/libs/binder/OS_android.cpp
@@ -44,6 +44,10 @@
     atrace_end(tag);
 }
 
+void trace_int(uint64_t tag, const char* name, int32_t value) {
+    atrace_int(tag, name, value);
+}
+
 } // 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 01f3fe0..0c64eb6 100644
--- a/libs/binder/OS_non_android_linux.cpp
+++ b/libs/binder/OS_non_android_linux.cpp
@@ -39,6 +39,8 @@
 
 void trace_end(uint64_t) {}
 
+void trace_int(uint64_t, const char*, int32_t) {}
+
 uint64_t GetThreadId() {
     return syscall(__NR_gettid);
 }
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index 1504715..5b157cc 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -82,13 +82,12 @@
          }                                                               \
     }
 
-#define RETURN_IF_ENTRY_ERASED(map, key)                                 \
-    {                                                                    \
-        size_t num_erased = (map).erase(key);                            \
-        if (num_erased) {                                                \
-            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
-            return num_erased;                                           \
-         }                                                               \
+#define RETURN_IF_ENTRY_ERASED(map, key)      \
+    {                                         \
+        size_t num_erased = (map).erase(key); \
+        if (num_erased) {                     \
+            return num_erased;                \
+        }                                     \
     }
 
 status_t PersistableBundle::writeToParcel(Parcel* parcel) const {
diff --git a/libs/binder/include/binder/Trace.h b/libs/binder/include/binder/Trace.h
index 268157e..2f450cb 100644
--- a/libs/binder/include/binder/Trace.h
+++ b/libs/binder/include/binder/Trace.h
@@ -41,6 +41,7 @@
 // libcutils/libutils
 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);
 } // namespace os
 
 class LIBBINDER_EXPORTED ScopedTrace {
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index bd24a20..8771af5 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -62,6 +62,7 @@
         "binderStatusUnitTest.cpp",
         "binderMemoryHeapBaseUnitTest.cpp",
         "binderRecordedTransactionTest.cpp",
+        "binderPersistableBundleTest.cpp",
     ],
     shared_libs: [
         "libbinder",
@@ -461,6 +462,20 @@
 }
 
 cc_test {
+    name: "binderRpcTestNoKernelAtAll",
+    defaults: [
+        "binderRpcTest_defaults",
+        "binderRpcTest_static_defaults",
+    ],
+    static_libs: [
+        "libbinder_rpc_no_kernel",
+    ],
+    cflags: [
+        "-DBINDER_NO_KERNEL_IPC_TESTING",
+    ],
+}
+
+cc_test {
     name: "binderRpcTestSingleThreaded",
     defaults: [
         "binderRpcTest_defaults",
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 9788d9d..00406ed 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -38,6 +38,7 @@
 #include <binder/IServiceManager.h>
 #include <binder/RpcServer.h>
 #include <binder/RpcSession.h>
+#include <binder/Status.h>
 #include <binder/unique_fd.h>
 #include <utils/Flattenable.h>
 
@@ -57,6 +58,7 @@
 using namespace std::chrono_literals;
 using android::base::testing::HasValue;
 using android::base::testing::Ok;
+using android::binder::Status;
 using android::binder::unique_fd;
 using testing::ExplainMatchResult;
 using testing::Matcher;
@@ -253,7 +255,7 @@
     public:
         virtual void SetUp() {
             m_server = static_cast<BinderLibTestEnv *>(binder_env)->getServer();
-            IPCThreadState::self()->restoreCallingWorkSource(0); 
+            IPCThreadState::self()->restoreCallingWorkSource(0);
         }
         virtual void TearDown() {
         }
@@ -461,6 +463,35 @@
     EXPECT_EQ(NO_ERROR, sm->addService(String16("binderLibTest-manager"), binder));
 }
 
+TEST_F(BinderLibTest, RegisterForNotificationsFailure) {
+    auto sm = defaultServiceManager();
+    using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback;
+    class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback {
+        void onServiceRegistration(const String16&, const sp<IBinder>&) override {}
+        virtual ~LocalRegistrationCallbackImpl() {}
+    };
+    sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make();
+
+    EXPECT_EQ(BAD_VALUE, sm->registerForNotifications(String16("ValidName"), nullptr));
+    EXPECT_EQ(UNKNOWN_ERROR, sm->registerForNotifications(String16("InvalidName!$"), cb));
+}
+
+TEST_F(BinderLibTest, UnregisterForNotificationsFailure) {
+    auto sm = defaultServiceManager();
+    using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback;
+    class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback {
+        void onServiceRegistration(const String16&, const sp<IBinder>&) override {}
+        virtual ~LocalRegistrationCallbackImpl() {}
+    };
+    sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make();
+
+    EXPECT_EQ(OK, sm->registerForNotifications(String16("ValidName"), cb));
+
+    EXPECT_EQ(BAD_VALUE, sm->unregisterForNotifications(String16("ValidName"), nullptr));
+    EXPECT_EQ(BAD_VALUE, sm->unregisterForNotifications(String16("AnotherValidName"), cb));
+    EXPECT_EQ(BAD_VALUE, sm->unregisterForNotifications(String16("InvalidName!!!"), cb));
+}
+
 TEST_F(BinderLibTest, WasParceled) {
     auto binder = sp<BBinder>::make();
     EXPECT_FALSE(binder->wasParceled());
diff --git a/libs/binder/tests/binderPersistableBundleTest.cpp b/libs/binder/tests/binderPersistableBundleTest.cpp
new file mode 100644
index 0000000..392e018
--- /dev/null
+++ b/libs/binder/tests/binderPersistableBundleTest.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/Parcel.h>
+#include <binder/PersistableBundle.h>
+#include <gtest/gtest.h>
+#include <numeric>
+
+using android::OK;
+using android::Parcel;
+using android::status_t;
+using android::String16;
+using android::String8;
+using android::os::PersistableBundle;
+
+namespace android {
+
+inline std::string to_string(String16 const& str) {
+    return String8{str}.c_str();
+}
+
+namespace os {
+
+template <typename T>
+inline std::ostream& operator<<(std::ostream& out, std::vector<T> const& vec) {
+    using std::to_string;
+    auto str =
+            std::accumulate(vec.begin(), vec.end(), std::string{},
+                            [](std::string const& a, auto const& b) { return a + to_string(b); });
+    return out << str;
+}
+
+inline std::ostream& operator<<(std::ostream& out, PersistableBundle const& pb) {
+#define PRINT(TYPENAME, TYPE)                                \
+    for (auto const& key : pb.get##TYPENAME##Keys()) {       \
+        TYPE val{};                                          \
+        pb.get##TYPENAME(key, &val);                         \
+        out << #TYPE " " << key << ": " << val << std::endl; \
+    }
+
+    out << "size: " << pb.size() << std::endl;
+    PRINT(Boolean, bool);
+    PRINT(Int, int);
+    PRINT(Long, int64_t);
+    PRINT(Double, double);
+    PRINT(String, String16);
+    PRINT(BooleanVector, std::vector<bool>);
+    PRINT(IntVector, std::vector<int32_t>);
+    PRINT(LongVector, std::vector<int64_t>);
+    PRINT(DoubleVector, std::vector<double>);
+    PRINT(StringVector, std::vector<String16>);
+    PRINT(PersistableBundle, PersistableBundle);
+
+#undef PRINT
+
+    return out;
+}
+
+} // namespace os
+} // namespace android
+
+static const String16 kKey{"key"};
+
+static PersistableBundle createSimplePersistableBundle() {
+    PersistableBundle pb{};
+    pb.putInt(kKey, 64);
+    return pb;
+}
+
+#define TEST_PUT_AND_GET(TYPENAME, TYPE, ...)              \
+    TEST(PersistableBundle, PutAndGet##TYPENAME) {         \
+        TYPE const expected{__VA_ARGS__};                  \
+        PersistableBundle pb{};                            \
+                                                           \
+        pb.put##TYPENAME(kKey, expected);                  \
+                                                           \
+        std::set<String16> expectedKeys{kKey};             \
+        EXPECT_EQ(pb.get##TYPENAME##Keys(), expectedKeys); \
+                                                           \
+        TYPE val{};                                        \
+        EXPECT_TRUE(pb.get##TYPENAME(kKey, &val));         \
+        EXPECT_EQ(val, expected);                          \
+    }
+
+TEST_PUT_AND_GET(Boolean, bool, true);
+TEST_PUT_AND_GET(Int, int, 64);
+TEST_PUT_AND_GET(Long, int64_t, 42);
+TEST_PUT_AND_GET(Double, double, 42.64);
+TEST_PUT_AND_GET(String, String16, String16{"foo"});
+TEST_PUT_AND_GET(BooleanVector, std::vector<bool>, true, true);
+TEST_PUT_AND_GET(IntVector, std::vector<int32_t>, 1, 2);
+TEST_PUT_AND_GET(LongVector, std::vector<int64_t>, 1, 2);
+TEST_PUT_AND_GET(DoubleVector, std::vector<double>, 4.2, 5.9);
+TEST_PUT_AND_GET(StringVector, std::vector<String16>, String16{"foo"}, String16{"bar"});
+TEST_PUT_AND_GET(PersistableBundle, PersistableBundle, createSimplePersistableBundle());
+
+TEST(PersistableBundle, ParcelAndUnparcel) {
+    PersistableBundle expected = createSimplePersistableBundle();
+    PersistableBundle out{};
+
+    Parcel p{};
+    EXPECT_EQ(expected.writeToParcel(&p), 0);
+    p.setDataPosition(0);
+    EXPECT_EQ(out.readFromParcel(&p), 0);
+
+    EXPECT_EQ(expected, out);
+}
+
+TEST(PersistableBundle, OverwriteKey) {
+    PersistableBundle pb{};
+
+    pb.putInt(kKey, 64);
+    pb.putDouble(kKey, 0.5);
+
+    EXPECT_EQ(pb.getIntKeys().size(), 0);
+    EXPECT_EQ(pb.getDoubleKeys().size(), 1);
+
+    double out;
+    EXPECT_TRUE(pb.getDouble(kKey, &out));
+    EXPECT_EQ(out, 0.5);
+}
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index c044d39..19882ea 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1278,7 +1278,7 @@
                 for (const auto& clientVersion : testVersions()) {
                     for (const auto& serverVersion : testVersions()) {
                         for (bool singleThreaded : {false, true}) {
-                            for (bool noKernel : {false, true}) {
+                            for (bool noKernel : noKernelValues()) {
                                 ret.push_back(BinderRpc::ParamType{
                                         .type = type,
                                         .security = security,
@@ -1299,7 +1299,7 @@
                     .clientVersion = RPC_WIRE_PROTOCOL_VERSION,
                     .serverVersion = RPC_WIRE_PROTOCOL_VERSION,
                     .singleThreaded = false,
-                    .noKernel = false,
+                    .noKernel = !kEnableKernelIpcTesting,
             });
         }
     }
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index acc0373..dc22647 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -64,6 +64,12 @@
 
 namespace android {
 
+#ifdef BINDER_NO_KERNEL_IPC_TESTING
+constexpr bool kEnableKernelIpcTesting = false;
+#else
+constexpr bool kEnableKernelIpcTesting = true;
+#endif
+
 constexpr char kLocalInetAddress[] = "127.0.0.1";
 
 enum class RpcSecurity { RAW, TLS };
@@ -72,6 +78,14 @@
     return {RpcSecurity::RAW, RpcSecurity::TLS};
 }
 
+static inline std::vector<bool> noKernelValues() {
+    std::vector<bool> values = {true};
+    if (kEnableKernelIpcTesting) {
+        values.push_back(false);
+    }
+    return values;
+}
+
 static inline bool hasExperimentalRpc() {
 #ifdef BINDER_RPC_TO_TRUSTY_TEST
     // Trusty services do not support the experimental version,
diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp
index 09db326..157ab3c 100644
--- a/libs/binder/trusty/OS.cpp
+++ b/libs/binder/trusty/OS.cpp
@@ -40,6 +40,8 @@
 
 void trace_end(uint64_t) {}
 
+void trace_int(uint64_t, const char*, int32_t) {}
+
 uint64_t GetThreadId() {
     return 0;
 }
diff --git a/libs/input/InputConsumer.cpp b/libs/input/InputConsumer.cpp
index abc0392..fcf490d 100644
--- a/libs/input/InputConsumer.cpp
+++ b/libs/input/InputConsumer.cpp
@@ -181,7 +181,8 @@
 }
 
 bool shouldResampleTool(ToolType toolType) {
-    return toolType == ToolType::FINGER || toolType == ToolType::UNKNOWN;
+    return toolType == ToolType::FINGER || toolType == ToolType::MOUSE ||
+            toolType == ToolType::STYLUS || toolType == ToolType::UNKNOWN;
 }
 
 } // namespace
@@ -592,6 +593,11 @@
             ALOGD_IF(debugResampling(), "Not resampled, missing id %d", id);
             return;
         }
+        if (!shouldResampleTool(event->getToolType(i))) {
+            ALOGD_IF(debugResampling(),
+                     "Not resampled, containing unsupported tool type at pointer %d", id);
+            return;
+        }
     }
 
     // Find the data to use for resampling.
@@ -639,10 +645,18 @@
     }
 
     if (current->eventTime == sampleTime) {
-        // Prevents having 2 events with identical times and coordinates.
+        ALOGD_IF(debugResampling(), "Not resampled, 2 events with identical times.");
         return;
     }
 
+    for (size_t i = 0; i < pointerCount; i++) {
+        uint32_t id = event->getPointerId(i);
+        if (!other->idBits.hasBit(id)) {
+            ALOGD_IF(debugResampling(), "Not resampled, the other doesn't have pointer id %d.", id);
+            return;
+        }
+    }
+
     // Resample touch coordinates.
     History oldLastResample;
     oldLastResample.initializeFrom(touchState.lastResample);
@@ -670,22 +684,16 @@
         const PointerCoords& currentCoords = current->getPointerById(id);
         resampledCoords = currentCoords;
         resampledCoords.isResampled = true;
-        if (other->idBits.hasBit(id) && shouldResampleTool(event->getToolType(i))) {
-            const PointerCoords& otherCoords = other->getPointerById(id);
-            resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
-                                         lerp(currentCoords.getX(), otherCoords.getX(), alpha));
-            resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
-                                         lerp(currentCoords.getY(), otherCoords.getY(), alpha));
-            ALOGD_IF(debugResampling(),
-                     "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
-                     "other (%0.3f, %0.3f), alpha %0.3f",
-                     id, resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
-                     currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha);
-        } else {
-            ALOGD_IF(debugResampling(), "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f)", id,
-                     resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
-                     currentCoords.getY());
-        }
+        const PointerCoords& otherCoords = other->getPointerById(id);
+        resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
+                                     lerp(currentCoords.getX(), otherCoords.getX(), alpha));
+        resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
+                                     lerp(currentCoords.getY(), otherCoords.getY(), alpha));
+        ALOGD_IF(debugResampling(),
+                 "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
+                 "other (%0.3f, %0.3f), alpha %0.3f",
+                 id, resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
+                 currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha);
     }
 
     event->addSample(sampleTime, touchState.lastResample.pointers);
diff --git a/libs/input/tests/TouchResampling_test.cpp b/libs/input/tests/TouchResampling_test.cpp
index 2dc9fdb..8d8b530 100644
--- a/libs/input/tests/TouchResampling_test.cpp
+++ b/libs/input/tests/TouchResampling_test.cpp
@@ -297,10 +297,9 @@
 }
 
 /**
- * Stylus pointer coordinates are not resampled, but an event is still generated for the batch with
- * a resampled timestamp and should be marked as such.
+ * Stylus pointer coordinates are resampled.
  */
-TEST_F(TouchResamplingTest, StylusCoordinatesNotResampledFor) {
+TEST_F(TouchResamplingTest, StylusEventIsResampled) {
     std::chrono::nanoseconds frameTime;
     std::vector<InputEventEntry> entries, expectedEntries;
 
@@ -330,15 +329,91 @@
             //      id  x   y
             {10ms, {{0, 20, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE},
             {20ms, {{0, 30, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE},
-            // A resampled event is generated, but the stylus coordinates are not resampled.
             {25ms,
-             {{0, 30, 30, .toolType = ToolType::STYLUS, .isResampled = true}},
+             {{0, 35, 30, .toolType = ToolType::STYLUS, .isResampled = true}},
              AMOTION_EVENT_ACTION_MOVE},
     };
     consumeInputEventEntries(expectedEntries, frameTime);
 }
 
 /**
+ * Mouse pointer coordinates are resampled.
+ */
+TEST_F(TouchResamplingTest, MouseEventIsResampled) {
+    std::chrono::nanoseconds frameTime;
+    std::vector<InputEventEntry> entries, expectedEntries;
+
+    // Initial ACTION_DOWN should be separate, because the first consume event will only return
+    // InputEvent with a single action.
+    entries = {
+            //      id  x   y
+            {0ms, {{0, 10, 20, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_DOWN},
+    };
+    publishInputEventEntries(entries);
+    frameTime = 5ms;
+    expectedEntries = {
+            //      id  x   y
+            {0ms, {{0, 10, 20, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_DOWN},
+    };
+    consumeInputEventEntries(expectedEntries, frameTime);
+
+    // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
+    entries = {
+            //      id  x   y
+            {10ms, {{0, 20, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
+            {20ms, {{0, 30, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
+    };
+    publishInputEventEntries(entries);
+    frameTime = 35ms;
+    expectedEntries = {
+            //      id  x   y
+            {10ms, {{0, 20, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
+            {20ms, {{0, 30, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
+            {25ms,
+             {{0, 35, 30, .toolType = ToolType::MOUSE, .isResampled = true}},
+             AMOTION_EVENT_ACTION_MOVE},
+    };
+    consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+/**
+ * Motion events with palm tool type are not resampled.
+ */
+TEST_F(TouchResamplingTest, PalmEventIsNotResampled) {
+    std::chrono::nanoseconds frameTime;
+    std::vector<InputEventEntry> entries, expectedEntries;
+
+    // Initial ACTION_DOWN should be separate, because the first consume event will only return
+    // InputEvent with a single action.
+    entries = {
+            //      id  x   y
+            {0ms, {{0, 10, 20, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_DOWN},
+    };
+    publishInputEventEntries(entries);
+    frameTime = 5ms;
+    expectedEntries = {
+            //      id  x   y
+            {0ms, {{0, 10, 20, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_DOWN},
+    };
+    consumeInputEventEntries(expectedEntries, frameTime);
+
+    // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
+    entries = {
+            //      id  x   y
+            {10ms, {{0, 20, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
+            {20ms, {{0, 30, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
+    };
+    publishInputEventEntries(entries);
+    frameTime = 35ms;
+    expectedEntries = {
+            //      id  x   y
+            {10ms, {{0, 20, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
+            {20ms, {{0, 30, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
+    };
+    consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+/**
  * Event should not be resampled when sample time is equal to event time.
  */
 TEST_F(TouchResamplingTest, SampleTimeEqualsEventTime) {
diff --git a/libs/renderengine/skia/VulkanInterface.cpp b/libs/renderengine/skia/VulkanInterface.cpp
index fc16c56..5e756b0 100644
--- a/libs/renderengine/skia/VulkanInterface.cpp
+++ b/libs/renderengine/skia/VulkanInterface.cpp
@@ -197,7 +197,9 @@
     LOG_ALWAYS_FATAL("%s", crashMsg.str().c_str());
 };
 
-static GrVkGetProc sGetProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
+static skgpu::VulkanGetProc sGetProc = [](const char* proc_name,
+                                          VkInstance instance,
+                                          VkDevice device) {
     if (device != VK_NULL_HANDLE) {
         return vkGetDeviceProcAddr(device, proc_name);
     }
@@ -604,7 +606,7 @@
     mQueue = VK_NULL_HANDLE;          // Implicitly destroyed by destroying mDevice.
     mQueueIndex = 0;
     mApiVersion = 0;
-    mGrExtensions = GrVkExtensions();
+    mGrExtensions = skgpu::VulkanExtensions();
     mGrGetProc = nullptr;
     mIsProtected = false;
     mIsRealtimePriority = false;
diff --git a/libs/renderengine/skia/VulkanInterface.h b/libs/renderengine/skia/VulkanInterface.h
index af0489a..f20b002 100644
--- a/libs/renderengine/skia/VulkanInterface.h
+++ b/libs/renderengine/skia/VulkanInterface.h
@@ -17,7 +17,8 @@
 #pragma once
 
 #include <include/gpu/vk/GrVkBackendContext.h>
-#include <include/gpu/vk/GrVkExtensions.h>
+#include <include/gpu/vk/VulkanExtensions.h>
+#include <include/gpu/vk/VulkanTypes.h>
 
 #include <vulkan/vulkan.h>
 
@@ -85,12 +86,12 @@
     VkQueue mQueue = VK_NULL_HANDLE;
     int mQueueIndex = 0;
     uint32_t mApiVersion = 0;
-    GrVkExtensions mGrExtensions;
+    skgpu::VulkanExtensions mGrExtensions;
     VkPhysicalDeviceFeatures2* mPhysicalDeviceFeatures2 = nullptr;
     VkPhysicalDeviceSamplerYcbcrConversionFeatures* mSamplerYcbcrConversionFeatures = nullptr;
     VkPhysicalDeviceProtectedMemoryFeatures* mProtectedMemoryFeatures = nullptr;
     VkPhysicalDeviceFaultFeaturesEXT* mDeviceFaultFeatures = nullptr;
-    GrVkGetProc mGrGetProc = nullptr;
+    skgpu::VulkanGetProc mGrGetProc = nullptr;
     bool mIsProtected = false;
     bool mIsRealtimePriority = false;
 
diff --git a/services/inputflinger/reader/controller/PeripheralController.cpp b/services/inputflinger/reader/controller/PeripheralController.cpp
index 27b9d23..49ad8b5 100644
--- a/services/inputflinger/reader/controller/PeripheralController.cpp
+++ b/services/inputflinger/reader/controller/PeripheralController.cpp
@@ -418,7 +418,11 @@
         }
         rawInfos.insert_or_assign(rawId, rawInfo.value());
         // Check if this is a group LEDs for player ID
-        std::regex lightPattern("([a-z]+)([0-9]+)");
+        // The name for the light has already been parsed and is the `function`
+        // value; for player ID lights the function is expected to be `player-#`.
+        // However, the Sony driver will use `sony#` instead on SIXAXIS
+        // gamepads.
+        std::regex lightPattern("(player|sony)-?([0-9]+)");
         std::smatch results;
         if (std::regex_match(rawInfo->name, results, lightPattern)) {
             std::string commonName = results[1].str();
diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
index 09a5f08..90685de 100644
--- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
+++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
@@ -155,8 +155,8 @@
         mMotionAccumulator.finishSync();
     }
 
-    mCursorButtonAccumulator.process(&rawEvent);
-    mMotionAccumulator.process(&rawEvent);
+    mCursorButtonAccumulator.process(rawEvent);
+    mMotionAccumulator.process(rawEvent);
     return out;
 }
 
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index c67314d..90de745 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -55,14 +55,14 @@
     mRelY = 0;
 }
 
-void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_REL) {
-        switch (rawEvent->code) {
+void CursorMotionAccumulator::process(const RawEvent& rawEvent) {
+    if (rawEvent.type == EV_REL) {
+        switch (rawEvent.code) {
             case REL_X:
-                mRelX = rawEvent->value;
+                mRelX = rawEvent.value;
                 break;
             case REL_Y:
-                mRelY = rawEvent->value;
+                mRelY = rawEvent.value;
                 break;
         }
     }
@@ -217,9 +217,9 @@
 
 std::list<NotifyArgs> CursorInputMapper::process(const RawEvent* rawEvent) {
     std::list<NotifyArgs> out;
-    mCursorButtonAccumulator.process(rawEvent);
-    mCursorMotionAccumulator.process(rawEvent);
-    mCursorScrollAccumulator.process(rawEvent);
+    mCursorButtonAccumulator.process(*rawEvent);
+    mCursorMotionAccumulator.process(*rawEvent);
+    mCursorScrollAccumulator.process(*rawEvent);
 
     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
         const auto [eventTime, readTime] =
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index 75ca9c0..5bde32b 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -34,7 +34,7 @@
     CursorMotionAccumulator();
     void reset(InputDeviceContext& deviceContext);
 
-    void process(const RawEvent* rawEvent);
+    void process(const RawEvent& rawEvent);
     void finishSync();
 
     inline int32_t getRelativeX() const { return mRelX; }
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
index 987d2d0..7f7e0dd 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
@@ -63,8 +63,8 @@
 
 std::list<NotifyArgs> ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
     std::list<NotifyArgs> out;
-    mSingleTouchMotionAccumulator.process(rawEvent);
-    mTouchButtonAccumulator.process(rawEvent);
+    mSingleTouchMotionAccumulator.process(*rawEvent);
+    mTouchButtonAccumulator.process(*rawEvent);
 
     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
         out += sync(rawEvent->when);
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index bca9d91..05ffa4d 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -43,7 +43,7 @@
 std::list<NotifyArgs> MultiTouchInputMapper::process(const RawEvent* rawEvent) {
     std::list<NotifyArgs> out = TouchInputMapper::process(rawEvent);
 
-    mMultiTouchMotionAccumulator.process(rawEvent);
+    mMultiTouchMotionAccumulator.process(*rawEvent);
     return out;
 }
 
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index 0ddbc06..182e1b7 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -103,7 +103,7 @@
 
 std::list<NotifyArgs> RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
     std::list<NotifyArgs> out;
-    mRotaryEncoderScrollAccumulator.process(rawEvent);
+    mRotaryEncoderScrollAccumulator.process(*rawEvent);
 
     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
         out += sync(rawEvent->when, rawEvent->readTime);
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
index ed0e270..b7365d3 100644
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp
@@ -33,7 +33,7 @@
 std::list<NotifyArgs> SingleTouchInputMapper::process(const RawEvent* rawEvent) {
     std::list<NotifyArgs> out = TouchInputMapper::process(rawEvent);
 
-    mSingleTouchMotionAccumulator.process(rawEvent);
+    mSingleTouchMotionAccumulator.process(*rawEvent);
     return out;
 }
 
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 62d7841..abe75b2 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -1404,9 +1404,9 @@
 }
 
 std::list<NotifyArgs> TouchInputMapper::process(const RawEvent* rawEvent) {
-    mCursorButtonAccumulator.process(rawEvent);
-    mCursorScrollAccumulator.process(rawEvent);
-    mTouchButtonAccumulator.process(rawEvent);
+    mCursorButtonAccumulator.process(*rawEvent);
+    mCursorScrollAccumulator.process(*rawEvent);
+    mTouchButtonAccumulator.process(*rawEvent);
 
     std::list<NotifyArgs> out;
     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index daf99da..a97d646 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -424,7 +424,7 @@
     if (mMotionAccumulator.getActiveSlotsCount() == 0) {
         mGestureStartTime = rawEvent->when;
     }
-    std::optional<SelfContainedHardwareState> state = mStateConverter.processRawEvent(rawEvent);
+    std::optional<SelfContainedHardwareState> state = mStateConverter.processRawEvent(*rawEvent);
     if (state) {
         updatePalmDetectionMetrics();
         return sendHardwareState(rawEvent->when, rawEvent->readTime, *state);
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp
index 153236c..9e722d4 100644
--- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.cpp
@@ -47,32 +47,32 @@
     mBtnTask = 0;
 }
 
-void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_KEY) {
-        switch (rawEvent->code) {
+void CursorButtonAccumulator::process(const RawEvent& rawEvent) {
+    if (rawEvent.type == EV_KEY) {
+        switch (rawEvent.code) {
             case BTN_LEFT:
-                mBtnLeft = rawEvent->value;
+                mBtnLeft = rawEvent.value;
                 break;
             case BTN_RIGHT:
-                mBtnRight = rawEvent->value;
+                mBtnRight = rawEvent.value;
                 break;
             case BTN_MIDDLE:
-                mBtnMiddle = rawEvent->value;
+                mBtnMiddle = rawEvent.value;
                 break;
             case BTN_BACK:
-                mBtnBack = rawEvent->value;
+                mBtnBack = rawEvent.value;
                 break;
             case BTN_SIDE:
-                mBtnSide = rawEvent->value;
+                mBtnSide = rawEvent.value;
                 break;
             case BTN_FORWARD:
-                mBtnForward = rawEvent->value;
+                mBtnForward = rawEvent.value;
                 break;
             case BTN_EXTRA:
-                mBtnExtra = rawEvent->value;
+                mBtnExtra = rawEvent.value;
                 break;
             case BTN_TASK:
-                mBtnTask = rawEvent->value;
+                mBtnTask = rawEvent.value;
                 break;
         }
     }
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
index 6960644..256b2bb 100644
--- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
@@ -29,7 +29,7 @@
     CursorButtonAccumulator();
     void reset(const InputDeviceContext& deviceContext);
 
-    void process(const RawEvent* rawEvent);
+    void process(const RawEvent& rawEvent);
 
     uint32_t getButtonState() const;
     inline bool isLeftPressed() const { return mBtnLeft; }
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp
index 0714694..f85cab2 100644
--- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp
@@ -39,14 +39,14 @@
     mRelHWheel = 0;
 }
 
-void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_REL) {
-        switch (rawEvent->code) {
+void CursorScrollAccumulator::process(const RawEvent& rawEvent) {
+    if (rawEvent.type == EV_REL) {
+        switch (rawEvent.code) {
             case REL_WHEEL:
-                mRelWheel = rawEvent->value;
+                mRelWheel = rawEvent.value;
                 break;
             case REL_HWHEEL:
-                mRelHWheel = rawEvent->value;
+                mRelHWheel = rawEvent.value;
                 break;
         }
     }
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h
index ae1b7a3..e563620 100644
--- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h
@@ -31,7 +31,7 @@
     void configure(InputDeviceContext& deviceContext);
     void reset(InputDeviceContext& deviceContext);
 
-    void process(const RawEvent* rawEvent);
+    void process(const RawEvent& rawEvent);
     void finishSync();
 
     inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
index b3f1700..4919068 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
@@ -45,12 +45,12 @@
     mCurrentSlot = -1;
 }
 
-void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_ABS) {
+void MultiTouchMotionAccumulator::process(const RawEvent& rawEvent) {
+    if (rawEvent.type == EV_ABS) {
         bool newSlot = false;
         if (mUsingSlotsProtocol) {
-            if (rawEvent->code == ABS_MT_SLOT) {
-                mCurrentSlot = rawEvent->value;
+            if (rawEvent.code == ABS_MT_SLOT) {
+                mCurrentSlot = rawEvent.value;
                 newSlot = true;
             }
         } else if (mCurrentSlot < 0) {
@@ -72,12 +72,12 @@
             if (!mUsingSlotsProtocol) {
                 slot.mInUse = true;
             }
-            if (rawEvent->code == ABS_MT_POSITION_X || rawEvent->code == ABS_MT_POSITION_Y) {
-                warnIfNotInUse(*rawEvent, slot);
+            if (rawEvent.code == ABS_MT_POSITION_X || rawEvent.code == ABS_MT_POSITION_Y) {
+                warnIfNotInUse(rawEvent, slot);
             }
-            slot.populateAxisValue(rawEvent->code, rawEvent->value);
+            slot.populateAxisValue(rawEvent.code, rawEvent.value);
         }
-    } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
+    } else if (rawEvent.type == EV_SYN && rawEvent.code == SYN_MT_REPORT) {
         // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
         mCurrentSlot += 1;
     }
diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
index a0f2147..388ed82 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
@@ -76,7 +76,7 @@
     void configure(const InputDeviceContext& deviceContext, size_t slotCount,
                    bool usingSlotsProtocol);
     void reset(const InputDeviceContext& deviceContext);
-    void process(const RawEvent* rawEvent);
+    void process(const RawEvent& rawEvent);
     void finishSync();
 
     size_t getActiveSlotsCount() const;
diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
index 27b8e40..2b82ddf 100644
--- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp
@@ -45,29 +45,29 @@
     mAbsTiltY = 0;
 }
 
-void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
-    if (rawEvent->type == EV_ABS) {
-        switch (rawEvent->code) {
+void SingleTouchMotionAccumulator::process(const RawEvent& rawEvent) {
+    if (rawEvent.type == EV_ABS) {
+        switch (rawEvent.code) {
             case ABS_X:
-                mAbsX = rawEvent->value;
+                mAbsX = rawEvent.value;
                 break;
             case ABS_Y:
-                mAbsY = rawEvent->value;
+                mAbsY = rawEvent.value;
                 break;
             case ABS_PRESSURE:
-                mAbsPressure = rawEvent->value;
+                mAbsPressure = rawEvent.value;
                 break;
             case ABS_TOOL_WIDTH:
-                mAbsToolWidth = rawEvent->value;
+                mAbsToolWidth = rawEvent.value;
                 break;
             case ABS_DISTANCE:
-                mAbsDistance = rawEvent->value;
+                mAbsDistance = rawEvent.value;
                 break;
             case ABS_TILT_X:
-                mAbsTiltX = rawEvent->value;
+                mAbsTiltX = rawEvent.value;
                 break;
             case ABS_TILT_Y:
-                mAbsTiltY = rawEvent->value;
+                mAbsTiltY = rawEvent.value;
                 break;
         }
     }
diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h
index 93056f0..fb74bca 100644
--- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.h
@@ -28,7 +28,7 @@
 public:
     SingleTouchMotionAccumulator();
 
-    void process(const RawEvent* rawEvent);
+    void process(const RawEvent& rawEvent);
     void reset(InputDeviceContext& deviceContext);
 
     inline int32_t getAbsoluteX() const { return mAbsX; }
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
index 8c4bed3..ba8577e 100644
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
@@ -52,60 +52,60 @@
     mHidUsageAccumulator.reset();
 }
 
-void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
-    mHidUsageAccumulator.process(*rawEvent);
+void TouchButtonAccumulator::process(const RawEvent& rawEvent) {
+    mHidUsageAccumulator.process(rawEvent);
 
-    if (rawEvent->type == EV_KEY) {
-        switch (rawEvent->code) {
+    if (rawEvent.type == EV_KEY) {
+        switch (rawEvent.code) {
             case BTN_TOUCH:
-                mBtnTouch = rawEvent->value;
+                mBtnTouch = rawEvent.value;
                 break;
             case BTN_STYLUS:
-                mBtnStylus = rawEvent->value;
+                mBtnStylus = rawEvent.value;
                 break;
             case BTN_STYLUS2:
             case BTN_0: // BTN_0 is what gets mapped for the HID usage
                         // Digitizers.SecondaryBarrelSwitch
-                mBtnStylus2 = rawEvent->value;
+                mBtnStylus2 = rawEvent.value;
                 break;
             case BTN_TOOL_FINGER:
-                mBtnToolFinger = rawEvent->value;
+                mBtnToolFinger = rawEvent.value;
                 break;
             case BTN_TOOL_PEN:
-                mBtnToolPen = rawEvent->value;
+                mBtnToolPen = rawEvent.value;
                 break;
             case BTN_TOOL_RUBBER:
-                mBtnToolRubber = rawEvent->value;
+                mBtnToolRubber = rawEvent.value;
                 break;
             case BTN_TOOL_BRUSH:
-                mBtnToolBrush = rawEvent->value;
+                mBtnToolBrush = rawEvent.value;
                 break;
             case BTN_TOOL_PENCIL:
-                mBtnToolPencil = rawEvent->value;
+                mBtnToolPencil = rawEvent.value;
                 break;
             case BTN_TOOL_AIRBRUSH:
-                mBtnToolAirbrush = rawEvent->value;
+                mBtnToolAirbrush = rawEvent.value;
                 break;
             case BTN_TOOL_MOUSE:
-                mBtnToolMouse = rawEvent->value;
+                mBtnToolMouse = rawEvent.value;
                 break;
             case BTN_TOOL_LENS:
-                mBtnToolLens = rawEvent->value;
+                mBtnToolLens = rawEvent.value;
                 break;
             case BTN_TOOL_DOUBLETAP:
-                mBtnToolDoubleTap = rawEvent->value;
+                mBtnToolDoubleTap = rawEvent.value;
                 break;
             case BTN_TOOL_TRIPLETAP:
-                mBtnToolTripleTap = rawEvent->value;
+                mBtnToolTripleTap = rawEvent.value;
                 break;
             case BTN_TOOL_QUADTAP:
-                mBtnToolQuadTap = rawEvent->value;
+                mBtnToolQuadTap = rawEvent.value;
                 break;
             case BTN_TOOL_QUINTTAP:
-                mBtnToolQuintTap = rawEvent->value;
+                mBtnToolQuintTap = rawEvent.value;
                 break;
             default:
-                processMappedKey(rawEvent->code, rawEvent->value);
+                processMappedKey(rawEvent.code, rawEvent.value);
         }
         return;
     }
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
index e829692..c7adf84 100644
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
@@ -33,7 +33,7 @@
     void configure();
     void reset();
 
-    void process(const RawEvent* rawEvent);
+    void process(const RawEvent& rawEvent);
 
     uint32_t getButtonState() const;
     ToolType getToolType() const;
diff --git a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
index b89b7f3..6885adb 100644
--- a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
@@ -40,15 +40,15 @@
 }
 
 std::optional<SelfContainedHardwareState> HardwareStateConverter::processRawEvent(
-        const RawEvent* rawEvent) {
+        const RawEvent& rawEvent) {
     std::optional<SelfContainedHardwareState> out;
-    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
-        out = produceHardwareState(rawEvent->when);
+    if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) {
+        out = produceHardwareState(rawEvent.when);
         mMotionAccumulator.finishSync();
         mMscTimestamp = 0;
     }
-    if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
-        mMscTimestamp = rawEvent->value;
+    if (rawEvent.type == EV_MSC && rawEvent.code == MSC_TIMESTAMP) {
+        mMscTimestamp = rawEvent.value;
     }
     mCursorButtonAccumulator.process(rawEvent);
     mMotionAccumulator.process(rawEvent);
diff --git a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h
index 633448e..07e62c6 100644
--- a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h
+++ b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.h
@@ -44,7 +44,7 @@
     HardwareStateConverter(const InputDeviceContext& deviceContext,
                            MultiTouchMotionAccumulator& motionAccumulator);
 
-    std::optional<SelfContainedHardwareState> processRawEvent(const RawEvent* event);
+    std::optional<SelfContainedHardwareState> processRawEvent(const RawEvent& event);
     void reset();
 
 private:
diff --git a/services/inputflinger/tests/HardwareStateConverter_test.cpp b/services/inputflinger/tests/HardwareStateConverter_test.cpp
index ff9bd9e..34c81fc 100644
--- a/services/inputflinger/tests/HardwareStateConverter_test.cpp
+++ b/services/inputflinger/tests/HardwareStateConverter_test.cpp
@@ -81,7 +81,7 @@
         event.type = type;
         event.code = code;
         event.value = value;
-        std::optional<SelfContainedHardwareState> schs = mConverter->processRawEvent(&event);
+        std::optional<SelfContainedHardwareState> schs = mConverter->processRawEvent(event);
         EXPECT_FALSE(schs.has_value());
     }
 
@@ -93,7 +93,7 @@
         event.type = EV_SYN;
         event.code = SYN_REPORT;
         event.value = 0;
-        return mConverter->processRawEvent(&event);
+        return mConverter->processRawEvent(event);
     }
 
     std::shared_ptr<FakeEventHub> mFakeEventHub;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 8536ff0..9960292 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -10595,24 +10595,24 @@
     ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
 }
 
-TEST_F(LightControllerTest, PlayerIdLight) {
+TEST_F(LightControllerTest, SonyPlayerIdLight) {
     RawLightInfo info1 = {.id = 1,
-                          .name = "player1",
+                          .name = "sony1",
                           .maxBrightness = 255,
                           .flags = InputLightClass::BRIGHTNESS,
                           .path = ""};
     RawLightInfo info2 = {.id = 2,
-                          .name = "player2",
+                          .name = "sony2",
                           .maxBrightness = 255,
                           .flags = InputLightClass::BRIGHTNESS,
                           .path = ""};
     RawLightInfo info3 = {.id = 3,
-                          .name = "player3",
+                          .name = "sony3",
                           .maxBrightness = 255,
                           .flags = InputLightClass::BRIGHTNESS,
                           .path = ""};
     RawLightInfo info4 = {.id = 4,
-                          .name = "player4",
+                          .name = "sony4",
                           .maxBrightness = 255,
                           .flags = InputLightClass::BRIGHTNESS,
                           .path = ""};
@@ -10626,6 +10626,49 @@
     controller.populateDeviceInfo(&info);
     std::vector<InputDeviceLightInfo> lights = info.getLights();
     ASSERT_EQ(1U, lights.size());
+    ASSERT_STREQ("sony", lights[0].name.c_str());
+    ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
+    ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
+    ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
+
+    ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
+    ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
+    ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
+    ASSERT_STREQ("sony", lights[0].name.c_str());
+}
+
+TEST_F(LightControllerTest, PlayerIdLight) {
+    RawLightInfo info1 = {.id = 1,
+                          .name = "player-1",
+                          .maxBrightness = 255,
+                          .flags = InputLightClass::BRIGHTNESS,
+                          .path = ""};
+    RawLightInfo info2 = {.id = 2,
+                          .name = "player-2",
+                          .maxBrightness = 255,
+                          .flags = InputLightClass::BRIGHTNESS,
+                          .path = ""};
+    RawLightInfo info3 = {.id = 3,
+                          .name = "player-3",
+                          .maxBrightness = 255,
+                          .flags = InputLightClass::BRIGHTNESS,
+                          .path = ""};
+    RawLightInfo info4 = {.id = 4,
+                          .name = "player-4",
+                          .maxBrightness = 255,
+                          .flags = InputLightClass::BRIGHTNESS,
+                          .path = ""};
+    mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
+    mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
+    mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
+    mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
+
+    PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
+    InputDeviceInfo info;
+    controller.populateDeviceInfo(&info);
+    std::vector<InputDeviceLightInfo> lights = info.getLights();
+    ASSERT_EQ(1U, lights.size());
+    ASSERT_STREQ("player", lights[0].name.c_str());
     ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
     ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
     ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
diff --git a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp
index 5e67506..b441a23 100644
--- a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp
+++ b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp
@@ -38,7 +38,7 @@
         event.type = type;
         event.code = code;
         event.value = value;
-        mMotionAccumulator.process(&event);
+        mMotionAccumulator.process(event);
     }
 };
 
diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp
index b517928..3f2d6ec 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -113,17 +113,31 @@
                     windowInfoListener = nullptr;
                 }) {}
 
-class PointerChoreographerTest : public testing::Test, public PointerChoreographerPolicyInterface {
+class PointerChoreographerTest : public testing::Test {
 protected:
     TestInputListener mTestListener;
     sp<gui::WindowInfosListener> mRegisteredWindowInfoListener;
     std::vector<gui::WindowInfo> mInjectedInitialWindowInfos;
-    TestPointerChoreographer mChoreographer{mTestListener, *this, mRegisteredWindowInfoListener,
+    testing::NiceMock<MockPointerChoreographerPolicyInterface> mMockPolicy;
+    TestPointerChoreographer mChoreographer{mTestListener, mMockPolicy,
+                                            mRegisteredWindowInfoListener,
                                             mInjectedInitialWindowInfos};
 
     void SetUp() override {
         // flag overrides
         input_flags::hide_pointer_indicators_for_secure_windows(true);
+
+        ON_CALL(mMockPolicy, createPointerController).WillByDefault([this](ControllerType type) {
+            std::shared_ptr<FakePointerController> pc = std::make_shared<FakePointerController>();
+            EXPECT_FALSE(pc->isPointerShown());
+            mCreatedControllers.emplace_back(type, pc);
+            return pc;
+        });
+
+        ON_CALL(mMockPolicy, notifyPointerDisplayIdChanged)
+                .WillByDefault([this](ui::LogicalDisplayId displayId, const FloatPoint& position) {
+                    mPointerDisplayIdNotified = displayId;
+                });
     }
 
     std::shared_ptr<FakePointerController> assertPointerControllerCreated(
@@ -177,19 +191,6 @@
     std::deque<std::pair<ControllerType, std::shared_ptr<FakePointerController>>>
             mCreatedControllers;
     std::optional<ui::LogicalDisplayId> mPointerDisplayIdNotified;
-
-    std::shared_ptr<PointerControllerInterface> createPointerController(
-            ControllerType type) override {
-        std::shared_ptr<FakePointerController> pc = std::make_shared<FakePointerController>();
-        EXPECT_FALSE(pc->isPointerShown());
-        mCreatedControllers.emplace_back(type, pc);
-        return pc;
-    }
-
-    void notifyPointerDisplayIdChanged(ui::LogicalDisplayId displayId,
-                                       const FloatPoint& position) override {
-        mPointerDisplayIdNotified = displayId;
-    }
 };
 
 TEST_F(PointerChoreographerTest, ForwardsArgsToInnerListener) {
diff --git a/services/sensorservice/senserservice_flags.aconfig b/services/sensorservice/senserservice_flags.aconfig
index 5b499a8..4c1d314 100644
--- a/services/sensorservice/senserservice_flags.aconfig
+++ b/services/sensorservice/senserservice_flags.aconfig
@@ -27,4 +27,11 @@
   namespace: "sensors"
   description: "When this flag is enabled, sensor service will only erase dynamic sensor data at the end of the threadLoop to prevent race condition."
   bug: "329020894"
+}
+
+flag {
+  name: "sensor_service_report_sensor_usage_in_tracing"
+  namespace: "sensors"
+  description: "When this flag is enabled, sensor service will report sensor usage when system trace is enabled."
+  bug: "333132224"
 }
\ No newline at end of file
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index 2b20de3..39a6b77 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -260,27 +260,36 @@
     hierarchy->mParent->updateChild(hierarchy, LayerHierarchy::Variant::Attached);
 }
 
-void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) {
-    if (root->mLayer) {
-        attachToRelativeParent(root);
-    }
-    for (auto& [child, childVariant] : root->mChildren) {
-        if (childVariant == LayerHierarchy::Variant::Detached ||
-            childVariant == LayerHierarchy::Variant::Attached) {
-            attachHierarchyToRelativeParent(child);
+std::vector<LayerHierarchy*> LayerHierarchyBuilder::getDescendants(LayerHierarchy* root) {
+    std::vector<LayerHierarchy*> hierarchies;
+    hierarchies.push_back(root);
+    std::vector<LayerHierarchy*> descendants;
+    for (size_t i = 0; i < hierarchies.size(); i++) {
+        LayerHierarchy* hierarchy = hierarchies[i];
+        if (hierarchy->mLayer) {
+            descendants.push_back(hierarchy);
         }
+        for (auto& [child, childVariant] : hierarchy->mChildren) {
+            if (childVariant == LayerHierarchy::Variant::Detached ||
+                childVariant == LayerHierarchy::Variant::Attached) {
+                hierarchies.push_back(child);
+            }
+        }
+    }
+    return descendants;
+}
+
+void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) {
+    std::vector<LayerHierarchy*> hierarchiesToAttach = getDescendants(root);
+    for (LayerHierarchy* hierarchy : hierarchiesToAttach) {
+        attachToRelativeParent(hierarchy);
     }
 }
 
 void LayerHierarchyBuilder::detachHierarchyFromRelativeParent(LayerHierarchy* root) {
-    if (root->mLayer) {
-        detachFromRelativeParent(root);
-    }
-    for (auto& [child, childVariant] : root->mChildren) {
-        if (childVariant == LayerHierarchy::Variant::Detached ||
-            childVariant == LayerHierarchy::Variant::Attached) {
-            detachHierarchyFromRelativeParent(child);
-        }
+    std::vector<LayerHierarchy*> hierarchiesToDetach = getDescendants(root);
+    for (LayerHierarchy* hierarchy : hierarchiesToDetach) {
+        detachFromRelativeParent(hierarchy);
     }
 }
 
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index 69710be..d023f9e 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -218,6 +218,7 @@
     void detachFromParent(LayerHierarchy*);
     void attachToRelativeParent(LayerHierarchy*);
     void detachFromRelativeParent(LayerHierarchy*);
+    std::vector<LayerHierarchy*> getDescendants(LayerHierarchy*);
     void attachHierarchyToRelativeParent(LayerHierarchy*);
     void detachHierarchyFromRelativeParent(LayerHierarchy*);
     void init(const std::vector<std::unique_ptr<RequestedLayerState>>&);
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
index 4b0618e..dd5e8bd 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -152,6 +152,10 @@
             if (swapErase(linkedLayer->mirrorIds, layer.id)) {
                 linkedLayer->changes |= RequestedLayerState::Changes::Mirror;
             }
+            if (linkedLayer->layerIdToMirror == layer.id) {
+                linkedLayer->layerIdToMirror = UNASSIGNED_LAYER_ID;
+                linkedLayer->changes |= RequestedLayerState::Changes::Mirror;
+            }
             if (linkedLayer->touchCropId == layer.id) {
                 linkedLayer->touchCropId = UNASSIGNED_LAYER_ID;
             }
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
index 2b333f4..b79bdb4 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
@@ -777,4 +777,28 @@
     EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expected);
 }
 
+// (b/343901186)
+TEST_F(LayerHierarchyTest, cleanUpDanglingMirrorLayer) {
+    LayerHierarchyBuilder hierarchyBuilder;
+    hierarchyBuilder.update(mLifecycleManager);
+    mirrorLayer(/*layer*/ 14, /*parent*/ 1, /*layerToMirror*/ 2);
+    UPDATE_AND_VERIFY(hierarchyBuilder);
+
+    std::vector<uint32_t> expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 14, 2, 2};
+    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+    EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+    expectedTraversalPath = {};
+    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+
+    // destroy layer handle
+    reparentLayer(2, UNASSIGNED_LAYER_ID);
+    destroyLayerHandle(2);
+    UPDATE_AND_VERIFY(hierarchyBuilder);
+    expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 14};
+    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+    EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+    expectedTraversalPath = {};
+    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+}
+
 } // namespace android::surfaceflinger::frontend