Merge "Don't store a pointer to internal SensorManager"
diff --git a/include/input/Input.h b/include/input/Input.h
index 30b0d6a..7573282 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -529,7 +529,7 @@
     inline nsecs_t getEventTime() const { return mEventTime; }
 
     static const char* getLabel(int32_t keyCode);
-    static int32_t getKeyCodeFromLabel(const char* label);
+    static std::optional<int> getKeyCodeFromLabel(const char* label);
 
     void initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
                     std::array<uint8_t, 32> hmac, int32_t action, int32_t flags, int32_t keyCode,
@@ -842,7 +842,7 @@
     }
 
     static const char* getLabel(int32_t axis);
-    static int32_t getAxisFromLabel(const char* label);
+    static std::optional<int> getAxisFromLabel(const char* label);
 
     static std::string actionToString(int32_t action);
 
diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h
index b4374ac..4668fce 100644
--- a/include/input/InputEventLabels.h
+++ b/include/input/InputEventLabels.h
@@ -35,22 +35,22 @@
 
 class InputEventLookup {
 public:
-    static int lookupValueByLabel(const std::unordered_map<std::string, int>& map,
-                                  const char* literal);
+    static std::optional<int> lookupValueByLabel(const std::unordered_map<std::string, int>& map,
+                                                 const char* literal);
 
     static const char* lookupLabelByValue(const std::vector<InputEventLabel>& vec, int value);
 
-    static int32_t getKeyCodeByLabel(const char* label);
+    static std::optional<int> getKeyCodeByLabel(const char* label);
 
     static const char* getLabelByKeyCode(int32_t keyCode);
 
-    static uint32_t getKeyFlagByLabel(const char* label);
+    static std::optional<int> getKeyFlagByLabel(const char* label);
 
-    static int32_t getAxisByLabel(const char* label);
+    static std::optional<int> getAxisByLabel(const char* label);
 
     static const char* getAxisLabel(int32_t axisId);
 
-    static int32_t getLedByLabel(const char* label);
+    static std::optional<int> getLedByLabel(const char* label);
 
 private:
     static const std::unordered_map<std::string, int> KEYCODES;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 44ff62b..0aca163 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -375,6 +375,10 @@
     return (mDataSize > mDataPos ? mDataSize : mDataPos);
 }
 
+size_t Parcel::dataBufferSize() const {
+    return mDataSize;
+}
+
 size_t Parcel::dataAvail() const
 {
     size_t result = dataSize() - dataPosition();
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 180c67c..04cb61f 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -99,5 +99,19 @@
     {
       "name": "binderLibTest"
     }
+  ],
+  "kernel-presubmit": [
+    {
+      "name": "binderDriverInterfaceTest"
+    },
+    {
+      "name": "binderLibTest"
+    },
+    {
+      "name": "binderSafeInterfaceTest"
+    },
+    {
+      "name": "memunreachable_binder_test"
+    }
   ]
 }
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index f730acb..162cd40 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -75,6 +75,7 @@
     size_t              dataAvail() const;
     size_t              dataPosition() const;
     size_t              dataCapacity() const;
+    size_t dataBufferSize() const;
 
     status_t            setDataSize(size_t size);
 
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 94f72d9..b5a2e2f 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -695,7 +695,10 @@
     if (parcel->get()->objectsCount()) {
         return STATUS_INVALID_OPERATION;
     }
-    int32_t dataSize = AParcel_getDataSize(parcel);
+    // b/264739302 - getDataSize will return dataPos if it is greater than dataSize
+    // which will cause crashes in memcpy at later point. Instead compare with
+    // actual length of internal buffer
+    int32_t dataSize = parcel->get()->dataBufferSize();
     if (len > static_cast<size_t>(dataSize) || start > static_cast<size_t>(dataSize) - len) {
         return STATUS_BAD_VALUE;
     }
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a77ca04..cefb9a7 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -63,7 +63,8 @@
                                  Vector<ComposerState>& state, const Vector<DisplayState>& displays,
                                  uint32_t flags, const sp<IBinder>& applyToken,
                                  const InputWindowCommands& commands, int64_t desiredPresentTime,
-                                 bool isAutoTimestamp, const client_cache_t& uncacheBuffer,
+                                 bool isAutoTimestamp,
+                                 const std::vector<client_cache_t>& uncacheBuffers,
                                  bool hasListenerCallbacks,
                                  const std::vector<ListenerCallbacks>& listenerCallbacks,
                                  uint64_t transactionId) override {
@@ -87,8 +88,11 @@
         SAFE_PARCEL(commands.write, data);
         SAFE_PARCEL(data.writeInt64, desiredPresentTime);
         SAFE_PARCEL(data.writeBool, isAutoTimestamp);
-        SAFE_PARCEL(data.writeStrongBinder, uncacheBuffer.token.promote());
-        SAFE_PARCEL(data.writeUint64, uncacheBuffer.id);
+        SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(uncacheBuffers.size()));
+        for (const client_cache_t& uncacheBuffer : uncacheBuffers) {
+            SAFE_PARCEL(data.writeStrongBinder, uncacheBuffer.token.promote());
+            SAFE_PARCEL(data.writeUint64, uncacheBuffer.id);
+        }
         SAFE_PARCEL(data.writeBool, hasListenerCallbacks);
 
         SAFE_PARCEL(data.writeVectorSize, listenerCallbacks);
@@ -158,11 +162,14 @@
             SAFE_PARCEL(data.readInt64, &desiredPresentTime);
             SAFE_PARCEL(data.readBool, &isAutoTimestamp);
 
-            client_cache_t uncachedBuffer;
+            SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize());
+            std::vector<client_cache_t> uncacheBuffers(count);
             sp<IBinder> tmpBinder;
-            SAFE_PARCEL(data.readNullableStrongBinder, &tmpBinder);
-            uncachedBuffer.token = tmpBinder;
-            SAFE_PARCEL(data.readUint64, &uncachedBuffer.id);
+            for (size_t i = 0; i < count; i++) {
+                SAFE_PARCEL(data.readNullableStrongBinder, &tmpBinder);
+                uncacheBuffers[i].token = tmpBinder;
+                SAFE_PARCEL(data.readUint64, &uncacheBuffers[i].id);
+            }
 
             bool hasListenerCallbacks = false;
             SAFE_PARCEL(data.readBool, &hasListenerCallbacks);
@@ -182,7 +189,7 @@
 
             return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken,
                                        inputWindowCommands, desiredPresentTime, isAutoTimestamp,
-                                       uncachedBuffer, hasListenerCallbacks, listenerCallbacks,
+                                       uncacheBuffers, hasListenerCallbacks, listenerCallbacks,
                                        transactionId);
         }
         default: {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 92125ea..21a7f78 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -565,11 +565,13 @@
         return NO_ERROR;
     }
 
-    uint64_t cache(const sp<GraphicBuffer>& buffer) {
+    uint64_t cache(const sp<GraphicBuffer>& buffer,
+                   std::optional<client_cache_t>& outUncacheBuffer) {
         std::lock_guard<std::mutex> lock(mMutex);
 
         if (mBuffers.size() >= BUFFER_CACHE_MAX_SIZE) {
-            evictLeastRecentlyUsedBuffer();
+            outUncacheBuffer = findLeastRecentlyUsedBuffer();
+            mBuffers.erase(outUncacheBuffer->id);
         }
 
         buffer->addDeathCallback(removeDeadBufferCallback, nullptr);
@@ -580,16 +582,13 @@
 
     void uncache(uint64_t cacheId) {
         std::lock_guard<std::mutex> lock(mMutex);
-        uncacheLocked(cacheId);
-    }
-
-    void uncacheLocked(uint64_t cacheId) REQUIRES(mMutex) {
-        mBuffers.erase(cacheId);
-        SurfaceComposerClient::doUncacheBufferTransaction(cacheId);
+        if (mBuffers.erase(cacheId)) {
+            SurfaceComposerClient::doUncacheBufferTransaction(cacheId);
+        }
     }
 
 private:
-    void evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) {
+    client_cache_t findLeastRecentlyUsedBuffer() REQUIRES(mMutex) {
         auto itr = mBuffers.begin();
         uint64_t minCounter = itr->second;
         auto minBuffer = itr;
@@ -603,7 +602,8 @@
             }
             itr++;
         }
-        uncacheLocked(minBuffer->first);
+
+        return {.token = getToken(), .id = minBuffer->first};
     }
 
     uint64_t getCounter() REQUIRES(mMutex) {
@@ -741,6 +741,18 @@
     InputWindowCommands inputWindowCommands;
     inputWindowCommands.read(*parcel);
 
+    count = static_cast<size_t>(parcel->readUint32());
+    if (count > parcel->dataSize()) {
+        return BAD_VALUE;
+    }
+    std::vector<client_cache_t> uncacheBuffers(count);
+    for (size_t i = 0; i < count; i++) {
+        sp<IBinder> tmpBinder;
+        SAFE_PARCEL(parcel->readStrongBinder, &tmpBinder);
+        uncacheBuffers[i].token = tmpBinder;
+        SAFE_PARCEL(parcel->readUint64, &uncacheBuffers[i].id);
+    }
+
     // Parsing was successful. Update the object.
     mId = transactionId;
     mTransactionNestCount = transactionNestCount;
@@ -755,6 +767,7 @@
     mComposerStates = composerStates;
     mInputWindowCommands = inputWindowCommands;
     mApplyToken = applyToken;
+    mUncacheBuffers = std::move(uncacheBuffers);
     return NO_ERROR;
 }
 
@@ -806,6 +819,13 @@
     }
 
     mInputWindowCommands.write(*parcel);
+
+    SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mUncacheBuffers.size()));
+    for (const client_cache_t& uncacheBuffer : mUncacheBuffers) {
+        SAFE_PARCEL(parcel->writeStrongBinder, uncacheBuffer.token.promote());
+        SAFE_PARCEL(parcel->writeUint64, uncacheBuffer.id);
+    }
+
     return NO_ERROR;
 }
 
@@ -873,6 +893,10 @@
         }
     }
 
+    for (const auto& cacheId : other.mUncacheBuffers) {
+        mUncacheBuffers.push_back(cacheId);
+    }
+
     mInputWindowCommands.merge(other.mInputWindowCommands);
 
     mMayContainBuffer |= other.mMayContainBuffer;
@@ -891,6 +915,7 @@
     mDisplayStates.clear();
     mListenerCallbacks.clear();
     mInputWindowCommands.clear();
+    mUncacheBuffers.clear();
     mMayContainBuffer = false;
     mTransactionNestCount = 0;
     mAnimation = false;
@@ -913,10 +938,10 @@
     uncacheBuffer.token = BufferCache::getInstance().getToken();
     uncacheBuffer.id = cacheId;
     Vector<ComposerState> composerStates;
-    status_t status =
-            sf->setTransactionState(FrameTimelineInfo{}, composerStates, {},
-                                    ISurfaceComposer::eOneWay, Transaction::getDefaultApplyToken(),
-                                    {}, systemTime(), true, uncacheBuffer, false, {}, generateId());
+    status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, {},
+                                              ISurfaceComposer::eOneWay,
+                                              Transaction::getDefaultApplyToken(), {}, systemTime(),
+                                              true, {uncacheBuffer}, false, {}, generateId());
     if (status != NO_ERROR) {
         ALOGE_AND_TRACE("SurfaceComposerClient::doUncacheBufferTransaction - %s",
                         strerror(-status));
@@ -954,7 +979,11 @@
             s->bufferData->buffer = nullptr;
         } else {
             // Cache-miss. Include the buffer and send the new cacheId.
-            cacheId = BufferCache::getInstance().cache(s->bufferData->buffer);
+            std::optional<client_cache_t> uncacheBuffer;
+            cacheId = BufferCache::getInstance().cache(s->bufferData->buffer, uncacheBuffer);
+            if (uncacheBuffer) {
+                mUncacheBuffers.push_back(*uncacheBuffer);
+            }
         }
         s->bufferData->flags |= BufferData::BufferDataChange::cachedBufferChanged;
         s->bufferData->cachedBuffer.token = BufferCache::getInstance().getToken();
@@ -1087,8 +1116,7 @@
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
                             mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
-                            {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/,
-                            hasListenerCallbacks, listenerCallbacks, mId);
+                            mUncacheBuffers, hasListenerCallbacks, listenerCallbacks, mId);
     mId = generateId();
 
     // Clear the current states and flags
diff --git a/libs/gui/aidl/android/gui/OverlayProperties.aidl b/libs/gui/aidl/android/gui/OverlayProperties.aidl
index 1af5746..5fb1a83 100644
--- a/libs/gui/aidl/android/gui/OverlayProperties.aidl
+++ b/libs/gui/aidl/android/gui/OverlayProperties.aidl
@@ -20,7 +20,9 @@
 parcelable OverlayProperties {
     parcelable SupportedBufferCombinations {
         int[] pixelFormats;
-        int[] dataspaces;
+        int[] standards;
+        int[] transfers;
+        int[] ranges;
     }
     SupportedBufferCombinations[] combinations;
 
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 045cc2a..ae56f9f 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -113,8 +113,9 @@
             const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state,
             const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
             const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
-            bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
-            const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) = 0;
+            bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffer,
+            bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
+            uint64_t transactionId) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 2458a40..0e51dcf 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -402,6 +402,7 @@
         SortedVector<DisplayState> mDisplayStates;
         std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash>
                 mListenerCallbacks;
+        std::vector<client_cache_t> mUncacheBuffers;
 
         uint64_t mId;
 
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3014804..32d60cd 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -701,7 +701,7 @@
                                  const sp<IBinder>& /*applyToken*/,
                                  const InputWindowCommands& /*inputWindowCommands*/,
                                  int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/,
-                                 const client_cache_t& /*cachedBuffer*/,
+                                 const std::vector<client_cache_t>& /*cachedBuffer*/,
                                  bool /*hasListenerCallbacks*/,
                                  const std::vector<ListenerCallbacks>& /*listenerCallbacks*/,
                                  uint64_t /*transactionId*/) override {
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index c356c2e..133b260 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -299,7 +299,7 @@
     return InputEventLookup::getLabelByKeyCode(keyCode);
 }
 
-int32_t KeyEvent::getKeyCodeFromLabel(const char* label) {
+std::optional<int> KeyEvent::getKeyCodeFromLabel(const char* label) {
     return InputEventLookup::getKeyCodeByLabel(label);
 }
 
@@ -891,7 +891,7 @@
     return InputEventLookup::getAxisLabel(axis);
 }
 
-int32_t MotionEvent::getAxisFromLabel(const char* label) {
+std::optional<int> MotionEvent::getAxisFromLabel(const char* label) {
     return InputEventLookup::getAxisByLabel(label);
 }
 
diff --git a/libs/input/InputEventLabels.cpp b/libs/input/InputEventLabels.cpp
index 7159e27..d97c1bb 100644
--- a/libs/input/InputEventLabels.cpp
+++ b/libs/input/InputEventLabels.cpp
@@ -438,11 +438,11 @@
 
 const std::unordered_map<std::string, int> InputEventLookup::FLAGS = {FLAGS_SEQUENCE};
 
-int InputEventLookup::lookupValueByLabel(const std::unordered_map<std::string, int>& map,
-                                         const char* literal) {
+std::optional<int> InputEventLookup::lookupValueByLabel(
+        const std::unordered_map<std::string, int>& map, const char* literal) {
     std::string str(literal);
     auto it = map.find(str);
-    return it != map.end() ? it->second : 0;
+    return it != map.end() ? std::make_optional(it->second) : std::nullopt;
 }
 
 const char* InputEventLookup::lookupLabelByValue(const std::vector<InputEventLabel>& vec,
@@ -453,8 +453,8 @@
     return nullptr;
 }
 
-int32_t InputEventLookup::getKeyCodeByLabel(const char* label) {
-    return int32_t(lookupValueByLabel(KEYCODES, label));
+std::optional<int> InputEventLookup::getKeyCodeByLabel(const char* label) {
+    return lookupValueByLabel(KEYCODES, label);
 }
 
 const char* InputEventLookup::getLabelByKeyCode(int32_t keyCode) {
@@ -464,20 +464,20 @@
     return nullptr;
 }
 
-uint32_t InputEventLookup::getKeyFlagByLabel(const char* label) {
-    return uint32_t(lookupValueByLabel(FLAGS, label));
+std::optional<int> InputEventLookup::getKeyFlagByLabel(const char* label) {
+    return lookupValueByLabel(FLAGS, label);
 }
 
-int32_t InputEventLookup::getAxisByLabel(const char* label) {
-    return int32_t(lookupValueByLabel(AXES, label));
+std::optional<int> InputEventLookup::getAxisByLabel(const char* label) {
+    return lookupValueByLabel(AXES, label);
 }
 
 const char* InputEventLookup::getAxisLabel(int32_t axisId) {
     return lookupLabelByValue(AXES_NAMES, axisId);
 }
 
-int32_t InputEventLookup::getLedByLabel(const char* label) {
-    return int32_t(lookupValueByLabel(LEDS, label));
+std::optional<int> InputEventLookup::getLedByLabel(const char* label) {
+    return lookupValueByLabel(LEDS, label);
 }
 
 } // namespace android
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 6bfac40..737bd15 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -999,7 +999,7 @@
 
     mTokenizer->skipDelimiters(WHITESPACE);
     String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
-    int32_t keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
+    std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
     if (!keyCode) {
         ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
                 keyCodeToken.string());
@@ -1010,19 +1010,19 @@
     ALOGD("Parsed map key %s: code=%d, keyCode=%d.",
             mapUsage ? "usage" : "scan code", code, keyCode);
 #endif
-    map.insert_or_assign(code, keyCode);
+    map.insert_or_assign(code, *keyCode);
     return NO_ERROR;
 }
 
 status_t KeyCharacterMap::Parser::parseKey() {
     String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
-    int32_t keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
+    std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
     if (!keyCode) {
         ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
                 keyCodeToken.string());
         return BAD_VALUE;
     }
-    if (mMap->mKeys.indexOfKey(keyCode) >= 0) {
+    if (mMap->mKeys.indexOfKey(*keyCode) >= 0) {
         ALOGE("%s: Duplicate entry for key code '%s'.", mTokenizer->getLocation().string(),
                 keyCodeToken.string());
         return BAD_VALUE;
@@ -1036,11 +1036,9 @@
         return BAD_VALUE;
     }
 
-#if DEBUG_PARSER
-    ALOGD("Parsed beginning of key: keyCode=%d.", keyCode);
-#endif
-    mKeyCode = keyCode;
-    mMap->mKeys.add(keyCode, new Key());
+    ALOGD_IF(DEBUG_PARSER, "Parsed beginning of key: keyCode=%d.", *keyCode);
+    mKeyCode = *keyCode;
+    mMap->mKeys.add(*keyCode, new Key());
     mState = STATE_KEY;
     return NO_ERROR;
 }
@@ -1136,7 +1134,7 @@
             } else if (token == "fallback") {
                 mTokenizer->skipDelimiters(WHITESPACE);
                 token = mTokenizer->nextToken(WHITESPACE);
-                int32_t keyCode = InputEventLookup::getKeyCodeByLabel(token.string());
+                std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(token.string());
                 if (!keyCode) {
                     ALOGE("%s: Invalid key code label for fallback behavior, got '%s'.",
                             mTokenizer->getLocation().string(),
@@ -1148,12 +1146,12 @@
                             mTokenizer->getLocation().string());
                     return BAD_VALUE;
                 }
-                behavior.fallbackKeyCode = keyCode;
+                behavior.fallbackKeyCode = *keyCode;
                 haveFallback = true;
             } else if (token == "replace") {
                 mTokenizer->skipDelimiters(WHITESPACE);
                 token = mTokenizer->nextToken(WHITESPACE);
-                int32_t keyCode = InputEventLookup::getKeyCodeByLabel(token.string());
+                std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(token.string());
                 if (!keyCode) {
                     ALOGE("%s: Invalid key code label for replace, got '%s'.",
                             mTokenizer->getLocation().string(),
@@ -1170,7 +1168,7 @@
                             mTokenizer->getLocation().string());
                     return BAD_VALUE;
                 }
-                behavior.replacementKeyCode = keyCode;
+                behavior.replacementKeyCode = *keyCode;
                 haveReplacement = true;
 
             } else {
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index 7371033..a2649f6 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "KeyLayoutMap"
 
+#include <android-base/logging.h>
 #include <android/keycodes.h>
 #include <ftl/enum.h>
 #include <input/InputEventLabels.h>
@@ -54,6 +55,21 @@
 namespace android {
 namespace {
 
+std::optional<int> parseInt(const char* str) {
+    char* end;
+    errno = 0;
+    const int value = strtol(str, &end, 0);
+    if (end == str) {
+        LOG(ERROR) << "Could not parse " << str;
+        return {};
+    }
+    if (errno == ERANGE) {
+        LOG(ERROR) << "Out of bounds: " << str;
+        return {};
+    }
+    return value;
+}
+
 constexpr const char* WHITESPACE = " \t\r";
 
 template <InputDeviceSensorType S>
@@ -336,16 +352,15 @@
         codeToken = mTokenizer->nextToken(WHITESPACE);
     }
 
-    char* end;
-    int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
-    if (*end) {
+    std::optional<int> code = parseInt(codeToken.string());
+    if (!code) {
         ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
                 mapUsage ? "usage" : "scan code", codeToken.string());
         return BAD_VALUE;
     }
     std::unordered_map<int32_t, Key>& map =
             mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
-    if (map.find(code) != map.end()) {
+    if (map.find(*code) != map.end()) {
         ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
                 mapUsage ? "usage" : "scan code", codeToken.string());
         return BAD_VALUE;
@@ -353,7 +368,7 @@
 
     mTokenizer->skipDelimiters(WHITESPACE);
     String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
-    int32_t keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
+    std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
     if (!keyCode) {
         ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
                 keyCodeToken.string());
@@ -366,40 +381,39 @@
         if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') break;
 
         String8 flagToken = mTokenizer->nextToken(WHITESPACE);
-        uint32_t flag = InputEventLookup::getKeyFlagByLabel(flagToken.string());
+        std::optional<int> flag = InputEventLookup::getKeyFlagByLabel(flagToken.string());
         if (!flag) {
             ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(),
                     flagToken.string());
             return BAD_VALUE;
         }
-        if (flags & flag) {
+        if (flags & *flag) {
             ALOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(),
                     flagToken.string());
             return BAD_VALUE;
         }
-        flags |= flag;
+        flags |= *flag;
     }
 
     ALOGD_IF(DEBUG_PARSER, "Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.",
-             mapUsage ? "usage" : "scan code", code, keyCode, flags);
+             mapUsage ? "usage" : "scan code", *code, *keyCode, flags);
 
     Key key;
-    key.keyCode = keyCode;
+    key.keyCode = *keyCode;
     key.flags = flags;
-    map.insert({code, key});
+    map.insert({*code, key});
     return NO_ERROR;
 }
 
 status_t KeyLayoutMap::Parser::parseAxis() {
     String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE);
-    char* end;
-    int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0));
-    if (*end) {
+    std::optional<int> scanCode = parseInt(scanCodeToken.string());
+    if (!scanCode) {
         ALOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().string(),
                 scanCodeToken.string());
         return BAD_VALUE;
     }
-    if (mMap->mAxes.find(scanCode) != mMap->mAxes.end()) {
+    if (mMap->mAxes.find(*scanCode) != mMap->mAxes.end()) {
         ALOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().string(),
                 scanCodeToken.string());
         return BAD_VALUE;
@@ -414,48 +428,53 @@
 
         mTokenizer->skipDelimiters(WHITESPACE);
         String8 axisToken = mTokenizer->nextToken(WHITESPACE);
-        axisInfo.axis = InputEventLookup::getAxisByLabel(axisToken.string());
-        if (axisInfo.axis < 0) {
+        std::optional<int> axis = InputEventLookup::getAxisByLabel(axisToken.string());
+        if (!axis) {
             ALOGE("%s: Expected inverted axis label, got '%s'.",
                     mTokenizer->getLocation().string(), axisToken.string());
             return BAD_VALUE;
         }
+        axisInfo.axis = *axis;
     } else if (token == "split") {
         axisInfo.mode = AxisInfo::MODE_SPLIT;
 
         mTokenizer->skipDelimiters(WHITESPACE);
         String8 splitToken = mTokenizer->nextToken(WHITESPACE);
-        axisInfo.splitValue = int32_t(strtol(splitToken.string(), &end, 0));
-        if (*end) {
+        std::optional<int> splitValue = parseInt(splitToken.string());
+        if (!splitValue) {
             ALOGE("%s: Expected split value, got '%s'.",
                     mTokenizer->getLocation().string(), splitToken.string());
             return BAD_VALUE;
         }
+        axisInfo.splitValue = *splitValue;
 
         mTokenizer->skipDelimiters(WHITESPACE);
         String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE);
-        axisInfo.axis = InputEventLookup::getAxisByLabel(lowAxisToken.string());
-        if (axisInfo.axis < 0) {
+        std::optional<int> axis = InputEventLookup::getAxisByLabel(lowAxisToken.string());
+        if (!axis) {
             ALOGE("%s: Expected low axis label, got '%s'.",
                     mTokenizer->getLocation().string(), lowAxisToken.string());
             return BAD_VALUE;
         }
+        axisInfo.axis = *axis;
 
         mTokenizer->skipDelimiters(WHITESPACE);
         String8 highAxisToken = mTokenizer->nextToken(WHITESPACE);
-        axisInfo.highAxis = InputEventLookup::getAxisByLabel(highAxisToken.string());
-        if (axisInfo.highAxis < 0) {
+        std::optional<int> highAxis = InputEventLookup::getAxisByLabel(highAxisToken.string());
+        if (!highAxis) {
             ALOGE("%s: Expected high axis label, got '%s'.",
                     mTokenizer->getLocation().string(), highAxisToken.string());
             return BAD_VALUE;
         }
+        axisInfo.highAxis = *highAxis;
     } else {
-        axisInfo.axis = InputEventLookup::getAxisByLabel(token.string());
-        if (axisInfo.axis < 0) {
+        std::optional<int> axis = InputEventLookup::getAxisByLabel(token.string());
+        if (!axis) {
             ALOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.",
                     mTokenizer->getLocation().string(), token.string());
             return BAD_VALUE;
         }
+        axisInfo.axis = *axis;
     }
 
     for (;;) {
@@ -467,12 +486,13 @@
         if (keywordToken == "flat") {
             mTokenizer->skipDelimiters(WHITESPACE);
             String8 flatToken = mTokenizer->nextToken(WHITESPACE);
-            axisInfo.flatOverride = int32_t(strtol(flatToken.string(), &end, 0));
-            if (*end) {
+            std::optional<int> flatOverride = parseInt(flatToken.string());
+            if (!flatOverride) {
                 ALOGE("%s: Expected flat value, got '%s'.",
                         mTokenizer->getLocation().string(), flatToken.string());
                 return BAD_VALUE;
             }
+            axisInfo.flatOverride = *flatOverride;
         } else {
             ALOGE("%s: Expected keyword 'flat', got '%s'.",
                     mTokenizer->getLocation().string(), keywordToken.string());
@@ -483,9 +503,9 @@
     ALOGD_IF(DEBUG_PARSER,
              "Parsed axis: scanCode=%d, mode=%d, axis=%d, highAxis=%d, "
              "splitValue=%d, flatOverride=%d.",
-             scanCode, axisInfo.mode, axisInfo.axis, axisInfo.highAxis, axisInfo.splitValue,
+             *scanCode, axisInfo.mode, axisInfo.axis, axisInfo.highAxis, axisInfo.splitValue,
              axisInfo.flatOverride);
-    mMap->mAxes.insert({scanCode, axisInfo});
+    mMap->mAxes.insert({*scanCode, axisInfo});
     return NO_ERROR;
 }
 
@@ -497,9 +517,8 @@
         mTokenizer->skipDelimiters(WHITESPACE);
         codeToken = mTokenizer->nextToken(WHITESPACE);
     }
-    char* end;
-    int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
-    if (*end) {
+    std::optional<int> code = parseInt(codeToken.string());
+    if (!code) {
         ALOGE("%s: Expected led %s number, got '%s'.", mTokenizer->getLocation().string(),
                 mapUsage ? "usage" : "scan code", codeToken.string());
         return BAD_VALUE;
@@ -507,7 +526,7 @@
 
     std::unordered_map<int32_t, Led>& map =
             mapUsage ? mMap->mLedsByUsageCode : mMap->mLedsByScanCode;
-    if (map.find(code) != map.end()) {
+    if (map.find(*code) != map.end()) {
         ALOGE("%s: Duplicate entry for led %s '%s'.", mTokenizer->getLocation().string(),
                 mapUsage ? "usage" : "scan code", codeToken.string());
         return BAD_VALUE;
@@ -515,19 +534,19 @@
 
     mTokenizer->skipDelimiters(WHITESPACE);
     String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE);
-    int32_t ledCode = InputEventLookup::getLedByLabel(ledCodeToken.string());
-    if (ledCode < 0) {
+    std::optional<int> ledCode = InputEventLookup::getLedByLabel(ledCodeToken.string());
+    if (!ledCode) {
         ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(),
                 ledCodeToken.string());
         return BAD_VALUE;
     }
 
     ALOGD_IF(DEBUG_PARSER, "Parsed led %s: code=%d, ledCode=%d.", mapUsage ? "usage" : "scan code",
-             code, ledCode);
+             *code, *ledCode);
 
     Led led;
-    led.ledCode = ledCode;
-    map.insert({code, led});
+    led.ledCode = *ledCode;
+    map.insert({*code, led});
     return NO_ERROR;
 }
 
@@ -565,16 +584,15 @@
 // sensor 0x05 GYROSCOPE Z
 status_t KeyLayoutMap::Parser::parseSensor() {
     String8 codeToken = mTokenizer->nextToken(WHITESPACE);
-    char* end;
-    int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
-    if (*end) {
+    std::optional<int> code = parseInt(codeToken.string());
+    if (!code) {
         ALOGE("%s: Expected sensor %s number, got '%s'.", mTokenizer->getLocation().string(),
               "abs code", codeToken.string());
         return BAD_VALUE;
     }
 
     std::unordered_map<int32_t, Sensor>& map = mMap->mSensorsByAbsCode;
-    if (map.find(code) != map.end()) {
+    if (map.find(*code) != map.end()) {
         ALOGE("%s: Duplicate entry for sensor %s '%s'.", mTokenizer->getLocation().string(),
               "abs code", codeToken.string());
         return BAD_VALUE;
@@ -599,13 +617,13 @@
     }
     int32_t sensorDataIndex = indexOpt.value();
 
-    ALOGD_IF(DEBUG_PARSER, "Parsed sensor: abs code=%d, sensorType=%s, sensorDataIndex=%d.", code,
+    ALOGD_IF(DEBUG_PARSER, "Parsed sensor: abs code=%d, sensorType=%s, sensorDataIndex=%d.", *code,
              ftl::enum_string(sensorType).c_str(), sensorDataIndex);
 
     Sensor sensor;
     sensor.sensorType = sensorType;
     sensor.sensorDataIndex = sensorDataIndex;
-    map.emplace(code, sensor);
+    map.emplace(*code, sensor);
     return NO_ERROR;
 }
 
diff --git a/libs/input/tests/InputDevice_test.cpp b/libs/input/tests/InputDevice_test.cpp
index 2344463..ee961f0 100644
--- a/libs/input/tests/InputDevice_test.cpp
+++ b/libs/input/tests/InputDevice_test.cpp
@@ -133,6 +133,20 @@
     ASSERT_EQ(*mKeyMap.keyCharacterMap, *frenchOverlaidKeyCharacterMap);
 }
 
+TEST_F(InputDeviceKeyMapTest, keyCharacteMapBadAxisLabel) {
+    std::string klPath = base::GetExecutableDirectory() + "/data/bad_axis_label.kl";
+
+    base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(klPath);
+    ASSERT_FALSE(ret.ok()) << "Should not be able to load KeyLayout at " << klPath;
+}
+
+TEST_F(InputDeviceKeyMapTest, keyCharacteMapBadLedLabel) {
+    std::string klPath = base::GetExecutableDirectory() + "/data/bad_led_label.kl";
+
+    base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(klPath);
+    ASSERT_FALSE(ret.ok()) << "Should not be able to load KeyLayout at " << klPath;
+}
+
 TEST(InputDeviceKeyLayoutTest, DoesNotLoadWhenRequiredKernelConfigIsMissing) {
 #if !defined(__ANDROID__)
     GTEST_SKIP() << "Can't check kernel configs on host";
diff --git a/libs/input/tests/data/bad_axis_label.kl b/libs/input/tests/data/bad_axis_label.kl
new file mode 100644
index 0000000..6897380
--- /dev/null
+++ b/libs/input/tests/data/bad_axis_label.kl
@@ -0,0 +1,17 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This KL should not be loaded because the axis label is not valid
+
+axis 0 DEFINITELY_NOT_AXIS_LABEL
diff --git a/libs/input/tests/data/bad_led_label.kl b/libs/input/tests/data/bad_led_label.kl
new file mode 100644
index 0000000..293c0d2
--- /dev/null
+++ b/libs/input/tests/data/bad_led_label.kl
@@ -0,0 +1,17 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This KL should not be loaded because the led label is invalid
+
+led 0 ABSOLUTELY_NOT_LED_LABEL
diff --git a/services/batteryservice/include/batteryservice/BatteryService.h b/services/batteryservice/include/batteryservice/BatteryService.h
index 178bc29..a2e4115 100644
--- a/services/batteryservice/include/batteryservice/BatteryService.h
+++ b/services/batteryservice/include/batteryservice/BatteryService.h
@@ -34,6 +34,9 @@
     BATTERY_PROP_CAPACITY = 4, // equals BATTERY_PROPERTY_CAPACITY
     BATTERY_PROP_ENERGY_COUNTER = 5, // equals BATTERY_PROPERTY_ENERGY_COUNTER
     BATTERY_PROP_BATTERY_STATUS = 6, // equals BATTERY_PROPERTY_BATTERY_STATUS
+    BATTERY_PROP_CHARGING_POLICY = 7, // equals BATTERY_PROPERTY_CHARGING_POLICY
+    BATTERY_PROP_MANUFACTURING_DATE = 8, // equals BATTERY_PROPERTY_MANUFACTURING_DATE
+    BATTERY_PROP_FIRST_USAGE_DATE = 9, // equals BATTERY_PROPERTY_FIRST_USAGE_DATE
 };
 
 struct BatteryProperties {
diff --git a/services/batteryservice/include/batteryservice/BatteryServiceConstants.h b/services/batteryservice/include/batteryservice/BatteryServiceConstants.h
index 8a90a12..2d7072d 100644
--- a/services/batteryservice/include/batteryservice/BatteryServiceConstants.h
+++ b/services/batteryservice/include/batteryservice/BatteryServiceConstants.h
@@ -1,7 +1,5 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
-
-#ifndef HIDL_GENERATED_android_hardware_health_V1_0_EXPORTED_CONSTANTS_H_
-#define HIDL_GENERATED_android_hardware_health_V1_0_EXPORTED_CONSTANTS_H_
+#ifndef AIDL_android_hardware_health_V2_EXPORTED_CONSTANTS_H_
+#define AIDL_android_hardware_health_V2_EXPORTED_CONSTANTS_H_
 
 #ifdef __cplusplus
 extern "C" {
@@ -15,6 +13,8 @@
     BATTERY_STATUS_FULL = 5,
 };
 
+// must be kept in sync with definitions in
+// hardware/interfaces/health/aidl/android/hardware/health/BatteryHealth.aidl
 enum {
     BATTERY_HEALTH_UNKNOWN = 1,
     BATTERY_HEALTH_GOOD = 2,
@@ -23,10 +23,23 @@
     BATTERY_HEALTH_OVER_VOLTAGE = 5,
     BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6,
     BATTERY_HEALTH_COLD = 7,
+    BATTERY_HEALTH_FAIR = 8,
+    BATTERY_HEALTH_NOT_AVAILABLE = 11,
+    BATTERY_HEALTH_INCONSISTENT = 12,
+};
+
+// must be kept in sync with definitions in
+// hardware/interfaces/health/aidl/android/hardware/health/BatteryChargingState.aidl
+enum {
+    BATTERY_STATUS_NORMAL = 1,
+    BATTERY_STATUS_TOO_COLD = 2,
+    BATTERY_STATUS_TOO_HOT = 3,
+    BATTERY_STATUS_LONG_LIFE = 4,
+    BATTERY_STATUS_ADAPTIVE = 5,
 };
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif  // HIDL_GENERATED_android_hardware_health_V1_0_EXPORTED_CONSTANTS_H_
+#endif  // AIDL_android_hardware_health_V2_EXPORTED_CONSTANTS_H_
diff --git a/services/inputflinger/TEST_MAPPING b/services/inputflinger/TEST_MAPPING
index 3d7242e..cacf30b 100644
--- a/services/inputflinger/TEST_MAPPING
+++ b/services/inputflinger/TEST_MAPPING
@@ -61,6 +61,7 @@
       "name": "FrameworksCoreTests",
       "options": [
         {
+          "include-filter": "android.hardware.input",
           "include-filter": "android.view.VerifiedKeyEventTest",
           "include-filter": "android.view.VerifiedMotionEventTest"
         }
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 204fff4..7974b2c 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -617,6 +617,12 @@
     return out;
 }
 
+template <typename T>
+std::vector<T>& operator+=(std::vector<T>& left, const std::vector<T>& right) {
+    left.insert(left.end(), right.begin(), right.end());
+    return left;
+}
+
 } // namespace
 
 // --- InputDispatcher ---
@@ -1019,8 +1025,7 @@
         const auto [x, y] = resolveTouchedPosition(motionEntry);
         const bool isStylus = isPointerFromStylus(motionEntry, 0 /*pointerIndex*/);
 
-        sp<WindowInfoHandle> touchedWindowHandle =
-                findTouchedWindowAtLocked(displayId, x, y, nullptr, isStylus);
+        auto [touchedWindowHandle, _] = findTouchedWindowAtLocked(displayId, x, y, isStylus);
         if (touchedWindowHandle != nullptr &&
             touchedWindowHandle->getApplicationToken() !=
                     mAwaitedFocusedApplication->getApplicationToken()) {
@@ -1143,15 +1148,11 @@
     }
 }
 
-sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x,
-                                                                int32_t y, TouchState* touchState,
-                                                                bool isStylus,
-                                                                bool addOutsideTargets,
-                                                                bool ignoreDragWindow) const {
-    if (addOutsideTargets && touchState == nullptr) {
-        LOG_ALWAYS_FATAL("Must provide a valid touch state if adding outside targets");
-    }
+std::pair<sp<WindowInfoHandle>, std::vector<InputTarget>>
+InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y, bool isStylus,
+                                           bool ignoreDragWindow) const {
     // Traverse windows from front to back to find touched window.
+    std::vector<InputTarget> outsideTargets;
     const auto& windowHandles = getWindowHandlesLocked(displayId);
     for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
         if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) {
@@ -1160,16 +1161,16 @@
 
         const WindowInfo& info = *windowHandle->getInfo();
         if (!info.isSpy() && windowAcceptsTouchAt(info, displayId, x, y, isStylus)) {
-            return windowHandle;
+            return {windowHandle, outsideTargets};
         }
 
-        if (addOutsideTargets &&
-            info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
-            touchState->addOrUpdateWindow(windowHandle, InputTarget::Flags::DISPATCH_AS_OUTSIDE,
-                                          BitSet32(0));
+        if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
+            addWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_OUTSIDE,
+                                  BitSet32(0), /*firstDownTimeInTarget=*/std::nullopt,
+                                  outsideTargets);
         }
     }
-    return nullptr;
+    return {nullptr, {}};
 }
 
 std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAtLocked(
@@ -1757,15 +1758,12 @@
             pilferPointersLocked(mDragState->dragWindow->getToken());
         }
 
-        std::vector<TouchedWindow> touchedWindows =
+        inputTargets =
                 findTouchedWindowTargetsLocked(currentTime, *entry, &conflictingPointerActions,
                                                /*byref*/ injectionResult);
-        for (const TouchedWindow& touchedWindow : touchedWindows) {
-            LOG_ALWAYS_FATAL_IF(injectionResult != InputEventInjectionResult::SUCCEEDED,
-                                "Shouldn't be adding window if the injection didn't succeed.");
-            addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
-                                  touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
-                                  inputTargets);
+        if (injectionResult != InputEventInjectionResult::SUCCEEDED) {
+            // No events should be dispatched if the injection didn't succeed
+            inputTargets = {};
         }
     } else {
         // Non touch event.  (eg. trackball)
@@ -2138,12 +2136,12 @@
     return true;
 }
 
-std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked(
+std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
         nsecs_t currentTime, const MotionEntry& entry, bool* outConflictingPointerActions,
         InputEventInjectionResult& outInjectionResult) {
     ATRACE_CALL();
 
-    std::vector<TouchedWindow> touchedWindows;
+    std::vector<InputTarget> targets;
     // For security reasons, we defer updating the touch state until we are sure that
     // event injection will be allowed.
     const int32_t displayId = entry.displayId;
@@ -2170,8 +2168,12 @@
     const bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
                                 maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
                                 maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
-    const bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
-                             maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction);
+    // A DOWN could be generated from POINTER_DOWN if the initial pointers did not land into any
+    // touchable windows.
+    const bool wasDown = oldState != nullptr && oldState->isDown();
+    const bool isDown = (maskedAction == AMOTION_EVENT_ACTION_DOWN) ||
+            (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN && !wasDown);
+    const bool newGesture = isDown || maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction;
     const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);
 
     if (newGesture) {
@@ -2182,7 +2184,7 @@
                   displayId);
             // TODO: test multiple simultaneous input streams.
             outInjectionResult = InputEventInjectionResult::FAILED;
-            return touchedWindows; // wrong device
+            return targets; // wrong device
         }
         tempTouchState.clearWindowsWithoutPointers();
         tempTouchState.deviceId = entry.deviceId;
@@ -2194,7 +2196,7 @@
               displayId);
         // TODO: test multiple simultaneous input streams.
         outInjectionResult = InputEventInjectionResult::FAILED;
-        return touchedWindows; // wrong device
+        return targets; // wrong device
     }
 
     if (isHoverAction) {
@@ -2207,12 +2209,15 @@
         /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
         const auto [x, y] = resolveTouchedPosition(entry);
         const int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-        const bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN;
+        // Outside targets should be added upon first dispatched DOWN event. That means, this should
+        // be a pointer that would generate ACTION_DOWN, *and* touch should not already be down.
         const bool isStylus = isPointerFromStylus(entry, pointerIndex);
-        sp<WindowInfoHandle> newTouchedWindowHandle =
-                findTouchedWindowAtLocked(displayId, x, y, &tempTouchState, isStylus,
-                                          isDown /*addOutsideTargets*/);
+        auto [newTouchedWindowHandle, outsideTargets] =
+                findTouchedWindowAtLocked(displayId, x, y, isStylus);
 
+        if (isDown) {
+            targets += outsideTargets;
+        }
         // Handle the case where we did not find a window.
         if (newTouchedWindowHandle == nullptr) {
             ALOGD("No new touched window at (%" PRId32 ", %" PRId32 ") in display %" PRId32, x, y,
@@ -2360,14 +2365,12 @@
             const bool isStylus = isPointerFromStylus(entry, 0 /*pointerIndex*/);
             sp<WindowInfoHandle> oldTouchedWindowHandle =
                     tempTouchState.getFirstForegroundWindowHandle();
-            sp<WindowInfoHandle> newTouchedWindowHandle =
-                    findTouchedWindowAtLocked(displayId, x, y, &tempTouchState, isStylus);
+            auto [newTouchedWindowHandle, _] = findTouchedWindowAtLocked(displayId, x, y, isStylus);
 
             // Verify targeted injection.
             if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
                 ALOGW("Dropping injected event: %s", (*err).c_str());
                 outInjectionResult = os::InputEventInjectionResult::TARGET_MISMATCH;
-                newTouchedWindowHandle = nullptr;
                 goto Failed;
             }
 
@@ -2385,9 +2388,15 @@
                           newTouchedWindowHandle->getName().c_str(), displayId);
                 }
                 // Make a slippery exit from the old window.
-                tempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
-                                                 InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT,
-                                                 BitSet32(0));
+                BitSet32 pointerIds;
+                const int32_t pointerId = entry.pointerProperties[0].id;
+                pointerIds.markBit(pointerId);
+
+                const TouchedWindow& touchedWindow =
+                        tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
+                addWindowTargetLocked(oldTouchedWindowHandle,
+                                      InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT, pointerIds,
+                                      touchedWindow.firstDownTimeInTarget, targets);
 
                 // Make a slippery entrance into the new window.
                 if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
@@ -2408,14 +2417,13 @@
                     targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
                 }
 
-                BitSet32 pointerIds;
-                pointerIds.markBit(entry.pointerProperties[0].id);
                 tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds,
                                                  entry.eventTime);
 
                 // Check if the wallpaper window should deliver the corresponding event.
                 slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
-                                   tempTouchState, pointerIds);
+                                   tempTouchState, pointerId, targets);
+                tempTouchState.removeTouchedPointerFromWindow(pointerId, oldTouchedWindowHandle);
             }
         }
 
@@ -2438,7 +2446,11 @@
     {
         std::vector<TouchedWindow> hoveringWindows =
                 getHoveringWindowsLocked(oldState, tempTouchState, entry);
-        touchedWindows.insert(touchedWindows.end(), hoveringWindows.begin(), hoveringWindows.end());
+        for (const TouchedWindow& touchedWindow : hoveringWindows) {
+            addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
+                                  touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
+                                  targets);
+        }
     }
     // Ensure that we have at least one foreground window or at least one window that cannot be a
     // foreground target. If we only have windows that are not receiving foreground touches (e.g. we
@@ -2477,30 +2489,31 @@
         }
     }
 
-    // Check whether windows listening for outside touches are owned by the same UID. If it is
-    // set the policy flag that we will not reveal coordinate information to this window.
+    // Check whether windows listening for outside touches are owned by the same UID. If the owner
+    // has a different UID, then we will not reveal coordinate information to this window.
     if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
         sp<WindowInfoHandle> foregroundWindowHandle =
                 tempTouchState.getFirstForegroundWindowHandle();
         if (foregroundWindowHandle) {
             const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
-            for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
-                if (touchedWindow.targetFlags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
-                    sp<WindowInfoHandle> windowInfoHandle = touchedWindow.windowHandle;
-                    if (windowInfoHandle->getInfo()->ownerUid != foregroundWindowUid) {
-                        tempTouchState.addOrUpdateWindow(windowInfoHandle,
-                                                         InputTarget::Flags::ZERO_COORDS,
-                                                         BitSet32(0));
+            for (InputTarget& target : targets) {
+                if (target.flags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
+                    sp<WindowInfoHandle> targetWindow =
+                            getWindowHandleLocked(target.inputChannel->getConnectionToken());
+                    if (targetWindow->getInfo()->ownerUid != foregroundWindowUid) {
+                        target.flags |= InputTarget::Flags::ZERO_COORDS;
                     }
                 }
             }
         }
     }
 
-    // Success!  Output targets for everything except hovers.
-    if (!isHoverAction) {
-        touchedWindows.insert(touchedWindows.end(), tempTouchState.windows.begin(),
-                              tempTouchState.windows.end());
+    // Success!  Output targets from the touch state.
+    tempTouchState.clearWindowsWithoutPointers();
+    for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
+        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
+                              touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
+                              targets);
     }
 
     outInjectionResult = InputEventInjectionResult::SUCCEEDED;
@@ -2572,7 +2585,7 @@
         mTouchStatesByDisplay.erase(displayId);
     }
 
-    return touchedWindows;
+    return targets;
 }
 
 void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) {
@@ -2580,9 +2593,8 @@
     // have an explicit reason to support it.
     constexpr bool isStylus = false;
 
-    const sp<WindowInfoHandle> dropWindow =
-            findTouchedWindowAtLocked(displayId, x, y, nullptr /*touchState*/, isStylus,
-                                      false /*addOutsideTargets*/, true /*ignoreDragWindow*/);
+    auto [dropWindow, _] =
+            findTouchedWindowAtLocked(displayId, x, y, isStylus, true /*ignoreDragWindow*/);
     if (dropWindow) {
         vec2 local = dropWindow->getInfo()->transform.transform(x, y);
         sendDropWindowCommandLocked(dropWindow->getToken(), local.x, local.y);
@@ -2638,10 +2650,8 @@
             // until we have an explicit reason to support it.
             constexpr bool isStylus = false;
 
-            const sp<WindowInfoHandle> hoverWindowHandle =
-                    findTouchedWindowAtLocked(entry.displayId, x, y, nullptr /*touchState*/,
-                                              isStylus, false /*addOutsideTargets*/,
-                                              true /*ignoreDragWindow*/);
+            auto [hoverWindowHandle, _] = findTouchedWindowAtLocked(entry.displayId, x, y, isStylus,
+                                                                    true /*ignoreDragWindow*/);
             // enqueue drag exit if needed.
             if (hoverWindowHandle != mDragState->dragHoverWindowHandle &&
                 !haveSameToken(hoverWindowHandle, mDragState->dragHoverWindowHandle)) {
@@ -6535,7 +6545,10 @@
 void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
                                          const sp<WindowInfoHandle>& oldWindowHandle,
                                          const sp<WindowInfoHandle>& newWindowHandle,
-                                         TouchState& state, const BitSet32& pointerIds) {
+                                         TouchState& state, int32_t pointerId,
+                                         std::vector<InputTarget>& targets) {
+    BitSet32 pointerIds;
+    pointerIds.markBit(pointerId);
     const bool oldHasWallpaper = oldWindowHandle->getInfo()->inputConfig.test(
             gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
     const bool newHasWallpaper = targetFlags.test(InputTarget::Flags::FOREGROUND) &&
@@ -6550,8 +6563,12 @@
     }
 
     if (oldWallpaper != nullptr) {
-        state.addOrUpdateWindow(oldWallpaper, InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT,
-                                BitSet32(0));
+        const TouchedWindow& oldTouchedWindow = state.getTouchedWindow(oldWallpaper);
+        addWindowTargetLocked(oldWallpaper,
+                              oldTouchedWindow.targetFlags |
+                                      InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT,
+                              pointerIds, oldTouchedWindow.firstDownTimeInTarget, targets);
+        state.removeTouchedPointerFromWindow(pointerId, oldWallpaper);
     }
 
     if (newWallpaper != nullptr) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 91ca2db..81f8de8 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -237,9 +237,9 @@
     // to transfer focus to a new application.
     std::shared_ptr<EventEntry> mNextUnblockedEvent GUARDED_BY(mLock);
 
-    sp<android::gui::WindowInfoHandle> findTouchedWindowAtLocked(
-            int32_t displayId, int32_t x, int32_t y, TouchState* touchState, bool isStylus = false,
-            bool addOutsideTargets = false, bool ignoreDragWindow = false) const REQUIRES(mLock);
+    std::pair<sp<android::gui::WindowInfoHandle>, std::vector<InputTarget>>
+    findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y, bool isStylus = false,
+                              bool ignoreDragWindow = false) const REQUIRES(mLock);
 
     std::vector<sp<android::gui::WindowInfoHandle>> findTouchedSpyWindowsAtLocked(
             int32_t displayId, int32_t x, int32_t y, bool isStylus) const REQUIRES(mLock);
@@ -543,7 +543,7 @@
     sp<android::gui::WindowInfoHandle> findFocusedWindowTargetLocked(
             nsecs_t currentTime, const EventEntry& entry, nsecs_t* nextWakeupTime,
             android::os::InputEventInjectionResult& outInjectionResult) REQUIRES(mLock);
-    std::vector<TouchedWindow> findTouchedWindowTargetsLocked(
+    std::vector<InputTarget> findTouchedWindowTargetsLocked(
             nsecs_t currentTime, const MotionEntry& entry, bool* outConflictingPointerActions,
             android::os::InputEventInjectionResult& outInjectionResult) REQUIRES(mLock);
     std::vector<Monitor> selectResponsiveMonitorsLocked(
@@ -697,7 +697,8 @@
     void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
                             const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
                             const sp<android::gui::WindowInfoHandle>& newWindowHandle,
-                            TouchState& state, const BitSet32& pointerIds) REQUIRES(mLock);
+                            TouchState& state, int32_t pointerId, std::vector<InputTarget>& targets)
+            REQUIRES(mLock);
     void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
                                 ftl::Flags<InputTarget::Flags> newTargetFlags,
                                 const sp<android::gui::WindowInfoHandle> fromWindowHandle,
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index f120fc9..ad37d02 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -37,6 +37,16 @@
     }
 }
 
+void TouchState::removeTouchedPointerFromWindow(
+        int32_t pointerId, const sp<android::gui::WindowInfoHandle>& windowHandle) {
+    for (TouchedWindow& touchedWindow : windows) {
+        if (touchedWindow.windowHandle == windowHandle) {
+            touchedWindow.pointerIds.clearBit(pointerId);
+            return;
+        }
+    }
+}
+
 void TouchState::clearHoveringPointers() {
     for (TouchedWindow& touchedWindow : windows) {
         touchedWindow.clearHoveringPointers();
@@ -70,7 +80,6 @@
             return;
         }
     }
-
     TouchedWindow touchedWindow;
     touchedWindow.windowHandle = windowHandle;
     touchedWindow.targetFlags = targetFlags;
@@ -175,6 +184,13 @@
     return nullptr;
 }
 
+const TouchedWindow& TouchState::getTouchedWindow(const sp<WindowInfoHandle>& windowHandle) const {
+    auto it = std::find_if(windows.begin(), windows.end(),
+                           [&](const TouchedWindow& w) { return w.windowHandle == windowHandle; });
+    LOG_ALWAYS_FATAL_IF(it == windows.end(), "Could not find %s", windowHandle->getName().c_str());
+    return *it;
+}
+
 bool TouchState::isDown() const {
     return std::any_of(windows.begin(), windows.end(),
                        [](const TouchedWindow& window) { return !window.pointerIds.isEmpty(); });
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index b75e6ef..4025db8 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -43,6 +43,8 @@
     void clearWindowsWithoutPointers();
 
     void removeTouchedPointer(int32_t pointerId);
+    void removeTouchedPointerFromWindow(int32_t pointerId,
+                                        const sp<android::gui::WindowInfoHandle>& windowHandle);
     void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
                            ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds,
                            std::optional<nsecs_t> eventTime = std::nullopt);
@@ -62,6 +64,8 @@
     sp<android::gui::WindowInfoHandle> getFirstForegroundWindowHandle() const;
     bool isSlippery() const;
     sp<android::gui::WindowInfoHandle> getWallpaperWindow() const;
+    const TouchedWindow& getTouchedWindow(
+            const sp<android::gui::WindowInfoHandle>& windowHandle) const;
     // Whether any of the windows are currently being touched
     bool isDown() const;
 
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 9bd50f7..bd41fa5 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -210,8 +210,14 @@
     // Touchscreens and touchpad devices.
     static const bool ENABLE_TOUCHPAD_GESTURES_LIBRARY =
             sysprop::InputProperties::enable_touchpad_gestures_library().value_or(false);
+    // TODO(b/246587538): Fix the new touchpad stack for Sony DualShock 4 (5c4, 9cc) and DualSense
+    // (ce6) touchpads, or at least load this setting from the IDC file.
+    const InputDeviceIdentifier& identifier = contextPtr->getDeviceIdentifier();
+    const bool isSonyGamepadTouchpad = identifier.vendor == 0x054c &&
+            (identifier.product == 0x05c4 || identifier.product == 0x09cc ||
+             identifier.product == 0x0ce6);
     if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) &&
-        classes.test(InputDeviceClass::TOUCH_MT)) {
+        classes.test(InputDeviceClass::TOUCH_MT) && !isSonyGamepadTouchpad) {
         mappers.push_back(std::make_unique<TouchpadInputMapper>(*contextPtr));
     } else if (classes.test(InputDeviceClass::TOUCH_MT)) {
         mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index ddddca2..0c57628 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -884,8 +884,6 @@
         mDeviceMode = DeviceMode::POINTER;
         if (hasStylus()) {
             mSource |= AINPUT_SOURCE_STYLUS;
-        } else {
-            mSource |= AINPUT_SOURCE_TOUCHPAD;
         }
     } else if (isTouchScreen()) {
         mSource = AINPUT_SOURCE_TOUCHSCREEN;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 95d35f4..feda191 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -5036,7 +5036,7 @@
     prepareAxes(POSITION);
     SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
 
-    ASSERT_EQ(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
+    ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
 }
 
 TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
@@ -8865,8 +8865,8 @@
     prepareAxes(POSITION);
     MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
 
-    // Check source is a touchpad that would obtain the PointerController.
-    ASSERT_EQ(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
+    // Check source is mouse that would obtain the PointerController.
+    ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
 
     NotifyMotionArgs motionArgs;
     processPosition(mapper, 100, 100);
@@ -9936,11 +9936,11 @@
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
 
-    // A non captured touchpad should have a mouse and touchpad source.
+    // non captured touchpad should be a mouse source
     mFakePolicy->setPointerCapture(false);
     configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
-    ASSERT_EQ(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
+    ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
 }
 
 TEST_F(MultiTouchInputMapperTest, Process_UnCapturedTouchpadPointer) {
@@ -9999,10 +9999,10 @@
     mFakePolicy->setPointerCapture(false);
     MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
 
-    // An uncaptured touchpad should be a pointer device, with additional touchpad source.
-    ASSERT_EQ(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
+    // uncaptured touchpad should be a pointer device
+    ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
 
-    // A captured touchpad should just have a touchpad source.
+    // captured touchpad should be a touchpad device
     mFakePolicy->setPointerCapture(true);
     configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
     ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 40de4d6..19445e0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1488,14 +1488,26 @@
         std::transform(combination.pixelFormats.cbegin(), combination.pixelFormats.cend(),
                        std::back_inserter(pixelFormats),
                        [](const auto& val) { return static_cast<int32_t>(val); });
-        std::vector<int32_t> dataspaces;
-        dataspaces.reserve(combination.dataspaces.size());
-        std::transform(combination.dataspaces.cbegin(), combination.dataspaces.cend(),
-                       std::back_inserter(dataspaces),
+        std::vector<int32_t> standards;
+        standards.reserve(combination.standards.size());
+        std::transform(combination.standards.cbegin(), combination.standards.cend(),
+                       std::back_inserter(standards),
+                       [](const auto& val) { return static_cast<int32_t>(val); });
+        std::vector<int32_t> transfers;
+        transfers.reserve(combination.transfers.size());
+        std::transform(combination.transfers.cbegin(), combination.transfers.cend(),
+                       std::back_inserter(transfers),
+                       [](const auto& val) { return static_cast<int32_t>(val); });
+        std::vector<int32_t> ranges;
+        ranges.reserve(combination.ranges.size());
+        std::transform(combination.ranges.cbegin(), combination.ranges.cend(),
+                       std::back_inserter(ranges),
                        [](const auto& val) { return static_cast<int32_t>(val); });
         gui::OverlayProperties::SupportedBufferCombinations outCombination;
         outCombination.pixelFormats = std::move(pixelFormats);
-        outCombination.dataspaces = std::move(dataspaces);
+        outCombination.standards = std::move(standards);
+        outCombination.transfers = std::move(transfers);
+        outCombination.ranges = std::move(ranges);
         outProperties->combinations.emplace_back(outCombination);
     }
     outProperties->supportMixedColorSpaces = aidlProperties.supportMixedColorSpaces;
@@ -2961,15 +2973,15 @@
 
         const auto enableFrameRateOverride = [&] {
             using Config = scheduler::RefreshRateSelector::Config;
-            if (!sysprop::enable_frame_rate_override(true)) {
+            if (!sysprop::enable_frame_rate_override(false)) {
                 return Config::FrameRateOverride::Disabled;
             }
 
-            if (sysprop::frame_rate_override_for_native_rates(false)) {
+            if (sysprop::frame_rate_override_for_native_rates(true)) {
                 return Config::FrameRateOverride::AppOverrideNativeRefreshRates;
             }
 
-            if (!sysprop::frame_rate_override_global(true)) {
+            if (!sysprop::frame_rate_override_global(false)) {
                 return Config::FrameRateOverride::AppOverride;
             }
 
@@ -3843,6 +3855,10 @@
 
     if (const bool scheduled = mTransactionFlags.fetch_or(mask) & mask; !scheduled) {
         scheduleCommit(frameHint);
+    } else if (frameHint == FrameHint::kActive) {
+        // Even if the next frame is already scheduled, we should reset the idle timer
+        // as a new activity just happened.
+        mScheduler->resetIdleTimer();
     }
 }
 
@@ -3973,7 +3989,7 @@
                                       transaction.displays, transaction.flags,
                                       transaction.inputWindowCommands,
                                       transaction.desiredPresentTime, transaction.isAutoTimestamp,
-                                      transaction.buffer, transaction.postTime,
+                                      std::move(transaction.uncacheBufferIds), transaction.postTime,
                                       transaction.permissions, transaction.hasListenerCallbacks,
                                       transaction.listenerCallbacks, transaction.originPid,
                                       transaction.originUid, transaction.id);
@@ -4061,8 +4077,9 @@
         const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states,
         const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
         const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
-        bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
-        const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
+        bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers,
+        bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
+        uint64_t transactionId) {
     ATRACE_CALL();
 
     uint32_t permissions =
@@ -4096,6 +4113,15 @@
     const int originPid = ipc->getCallingPid();
     const int originUid = ipc->getCallingUid();
 
+    std::vector<uint64_t> uncacheBufferIds;
+    uncacheBufferIds.reserve(uncacheBuffers.size());
+    for (const auto& uncacheBuffer : uncacheBuffers) {
+        sp<GraphicBuffer> buffer = ClientCache::getInstance().erase(uncacheBuffer);
+        if (buffer != nullptr) {
+            uncacheBufferIds.push_back(buffer->getId());
+        }
+    }
+
     std::vector<ResolvedComposerState> resolvedStates;
     resolvedStates.reserve(states.size());
     for (auto& state : states) {
@@ -4113,14 +4139,22 @@
         }
     }
 
-    TransactionState state{frameTimelineInfo,  resolvedStates,
-                           displays,           flags,
-                           applyToken,         inputWindowCommands,
-                           desiredPresentTime, isAutoTimestamp,
-                           uncacheBuffer,      postTime,
-                           permissions,        hasListenerCallbacks,
-                           listenerCallbacks,  originPid,
-                           originUid,          transactionId};
+    TransactionState state{frameTimelineInfo,
+                           resolvedStates,
+                           displays,
+                           flags,
+                           applyToken,
+                           inputWindowCommands,
+                           desiredPresentTime,
+                           isAutoTimestamp,
+                           std::move(uncacheBufferIds),
+                           postTime,
+                           permissions,
+                           hasListenerCallbacks,
+                           listenerCallbacks,
+                           originPid,
+                           originUid,
+                           transactionId};
 
     if (mTransactionTracing) {
         mTransactionTracing->addQueuedTransaction(state);
@@ -4144,7 +4178,7 @@
                                            Vector<DisplayState>& displays, uint32_t flags,
                                            const InputWindowCommands& inputWindowCommands,
                                            const int64_t desiredPresentTime, bool isAutoTimestamp,
-                                           const client_cache_t& uncacheBuffer,
+                                           const std::vector<uint64_t>& uncacheBufferIds,
                                            const int64_t postTime, uint32_t permissions,
                                            bool hasListenerCallbacks,
                                            const std::vector<ListenerCallbacks>& listenerCallbacks,
@@ -4185,11 +4219,8 @@
         ALOGE("Only privileged callers are allowed to send input commands.");
     }
 
-    if (uncacheBuffer.isValid()) {
-        sp<GraphicBuffer> buffer = ClientCache::getInstance().erase(uncacheBuffer);
-        if (buffer != nullptr) {
-            mBufferIdsToUncache.push_back(buffer->getId());
-        }
+    for (uint64_t uncacheBufferId : uncacheBufferIds) {
+        mBufferIdsToUncache.push_back(uncacheBufferId);
     }
 
     // If a synchronous transaction is explicitly requested without any changes, force a transaction
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5457be8..9245399 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -501,7 +501,8 @@
                                  uint32_t flags, const sp<IBinder>& applyToken,
                                  const InputWindowCommands& inputWindowCommands,
                                  int64_t desiredPresentTime, bool isAutoTimestamp,
-                                 const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+                                 const std::vector<client_cache_t>& uncacheBuffers,
+                                 bool hasListenerCallbacks,
                                  const std::vector<ListenerCallbacks>& listenerCallbacks,
                                  uint64_t transactionId) override;
     void bootFinished();
@@ -714,16 +715,14 @@
     /*
      * Transactions
      */
-    bool applyTransactionState(const FrameTimelineInfo& info,
-                               std::vector<ResolvedComposerState>& state,
-                               Vector<DisplayState>& displays, uint32_t flags,
-                               const InputWindowCommands& inputWindowCommands,
-                               const int64_t desiredPresentTime, bool isAutoTimestamp,
-                               const client_cache_t& uncacheBuffer, const int64_t postTime,
-                               uint32_t permissions, bool hasListenerCallbacks,
-                               const std::vector<ListenerCallbacks>& listenerCallbacks,
-                               int originPid, int originUid, uint64_t transactionId)
-            REQUIRES(mStateLock);
+    bool applyTransactionState(
+            const FrameTimelineInfo& info, std::vector<ResolvedComposerState>& state,
+            Vector<DisplayState>& displays, uint32_t flags,
+            const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
+            bool isAutoTimestamp, const std::vector<uint64_t>& uncacheBufferIds,
+            const int64_t postTime, uint32_t permissions, bool hasListenerCallbacks,
+            const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid,
+            uint64_t transactionId) REQUIRES(mStateLock);
     // Flush pending transactions that were presented after desiredPresentTime.
     bool flushTransactionQueues(VsyncId) REQUIRES(kMainThreadContext);
     // Returns true if there is at least one transaction that needs to be flushed
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h
index 366b09d..5025c49 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/TransactionState.h
@@ -43,7 +43,7 @@
                      const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
                      const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands,
                      int64_t desiredPresentTime, bool isAutoTimestamp,
-                     const client_cache_t& uncacheBuffer, int64_t postTime, uint32_t permissions,
+                     std::vector<uint64_t> uncacheBufferIds, int64_t postTime, uint32_t permissions,
                      bool hasListenerCallbacks, std::vector<ListenerCallbacks> listenerCallbacks,
                      int originPid, int originUid, uint64_t transactionId)
           : frameTimelineInfo(frameTimelineInfo),
@@ -54,7 +54,7 @@
             inputWindowCommands(inputWindowCommands),
             desiredPresentTime(desiredPresentTime),
             isAutoTimestamp(isAutoTimestamp),
-            buffer(uncacheBuffer),
+            uncacheBufferIds(std::move(uncacheBufferIds)),
             postTime(postTime),
             permissions(permissions),
             hasListenerCallbacks(hasListenerCallbacks),
@@ -109,7 +109,7 @@
     InputWindowCommands inputWindowCommands;
     int64_t desiredPresentTime;
     bool isAutoTimestamp;
-    client_cache_t buffer;
+    std::vector<uint64_t> uncacheBufferIds;
     int64_t postTime;
     uint32_t permissions;
     bool hasListenerCallbacks;
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 81ca659..c22d78b 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -730,17 +730,18 @@
         return mFlinger->mTransactionHandler.mPendingTransactionQueues;
     }
 
-    auto setTransactionState(const FrameTimelineInfo &frameTimelineInfo,
-                             Vector<ComposerState> &states, const Vector<DisplayState> &displays,
-                             uint32_t flags, const sp<IBinder> &applyToken,
-                             const InputWindowCommands &inputWindowCommands,
+    auto setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+                             Vector<ComposerState>& states, const Vector<DisplayState>& displays,
+                             uint32_t flags, const sp<IBinder>& applyToken,
+                             const InputWindowCommands& inputWindowCommands,
                              int64_t desiredPresentTime, bool isAutoTimestamp,
-                             const client_cache_t &uncacheBuffer, bool hasListenerCallbacks,
-                             std::vector<ListenerCallbacks> &listenerCallbacks,
+                             const std::vector<client_cache_t>& uncacheBuffers,
+                             bool hasListenerCallbacks,
+                             std::vector<ListenerCallbacks>& listenerCallbacks,
                              uint64_t transactionId) {
         return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken,
                                              inputWindowCommands, desiredPresentTime,
-                                             isAutoTimestamp, uncacheBuffer, hasListenerCallbacks,
+                                             isAutoTimestamp, uncacheBuffers, hasListenerCallbacks,
                                              listenerCallbacks, transactionId);
     }
 
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 584d52c..72e0c7b 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -439,12 +439,13 @@
                              uint32_t flags, const sp<IBinder>& applyToken,
                              const InputWindowCommands& inputWindowCommands,
                              int64_t desiredPresentTime, bool isAutoTimestamp,
-                             const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+                             const std::vector<client_cache_t>& uncacheBuffers,
+                             bool hasListenerCallbacks,
                              std::vector<ListenerCallbacks>& listenerCallbacks,
                              uint64_t transactionId) {
         return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken,
                                              inputWindowCommands, desiredPresentTime,
-                                             isAutoTimestamp, uncacheBuffer, hasListenerCallbacks,
+                                             isAutoTimestamp, uncacheBuffers, hasListenerCallbacks,
                                              listenerCallbacks, transactionId);
     }
 
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index d84698f..a28d1cd 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -102,7 +102,7 @@
         int64_t desiredPresentTime = 0;
         bool isAutoTimestamp = true;
         FrameTimelineInfo frameTimelineInfo;
-        client_cache_t uncacheBuffer;
+        std::vector<client_cache_t> uncacheBuffers;
         uint64_t id = static_cast<uint64_t>(-1);
         static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1));
     };
@@ -138,7 +138,7 @@
                                      transaction.displays, transaction.flags,
                                      transaction.applyToken, transaction.inputWindowCommands,
                                      transaction.desiredPresentTime, transaction.isAutoTimestamp,
-                                     transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
+                                     transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
                                      transaction.id);
 
         // If transaction is synchronous, SF applyTransactionState should time out (5s) wating for
@@ -165,7 +165,7 @@
                                      transaction.displays, transaction.flags,
                                      transaction.applyToken, transaction.inputWindowCommands,
                                      transaction.desiredPresentTime, transaction.isAutoTimestamp,
-                                     transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
+                                     transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
                                      transaction.id);
 
         nsecs_t returnedTime = systemTime();
@@ -196,7 +196,7 @@
                                      transactionA.displays, transactionA.flags,
                                      transactionA.applyToken, transactionA.inputWindowCommands,
                                      transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
-                                     transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
+                                     transactionA.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
                                      transactionA.id);
 
         // This thread should not have been blocked by the above transaction
@@ -211,7 +211,7 @@
                                      transactionB.displays, transactionB.flags,
                                      transactionB.applyToken, transactionB.inputWindowCommands,
                                      transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
-                                     transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
+                                     transactionB.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
                                      transactionB.id);
 
         // this thread should have been blocked by the above transaction
@@ -243,7 +243,7 @@
     mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
                                  transactionA.displays, transactionA.flags, transactionA.applyToken,
                                  transactionA.inputWindowCommands, transactionA.desiredPresentTime,
-                                 transactionA.isAutoTimestamp, transactionA.uncacheBuffer,
+                                 transactionA.isAutoTimestamp, transactionA.uncacheBuffers,
                                  mHasListenerCallbacks, mCallbacks, transactionA.id);
 
     auto& transactionQueue = mFlinger.getTransactionQueue();
@@ -263,7 +263,7 @@
     mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
                                  transactionA.displays, transactionA.flags, transactionA.applyToken,
                                  transactionA.inputWindowCommands, transactionA.desiredPresentTime,
-                                 transactionA.isAutoTimestamp, transactionA.uncacheBuffer,
+                                 transactionA.isAutoTimestamp, transactionA.uncacheBuffers,
                                  mHasListenerCallbacks, mCallbacks, transactionA.id);
 
     auto& transactionQueue = mFlinger.getTransactionQueue();
@@ -277,7 +277,7 @@
     mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags,
                                  empty.applyToken, empty.inputWindowCommands,
                                  empty.desiredPresentTime, empty.isAutoTimestamp,
-                                 empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id);
+                                 empty.uncacheBuffers, mHasListenerCallbacks, mCallbacks, empty.id);
 
     // flush transaction queue should flush as desiredPresentTime has
     // passed
@@ -374,8 +374,7 @@
                                               transaction.applyToken,
                                               transaction.inputWindowCommands,
                                               transaction.desiredPresentTime,
-                                              transaction.isAutoTimestamp,
-                                              transaction.uncacheBuffer, systemTime(), 0,
+                                              transaction.isAutoTimestamp, {}, systemTime(), 0,
                                               mHasListenerCallbacks, mCallbacks, getpid(),
                                               static_cast<int>(getuid()), transaction.id);
             mFlinger.setTransactionStateInternal(transactionState);