Merge "Reland refactor of screenshot code on main thread." into main
diff --git a/include/input/Input.h b/include/input/Input.h
index a84dcfc..374254f 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -870,6 +870,10 @@
 
     void copyFrom(const MotionEvent* other, bool keepHistory);
 
+    // Initialize this event by keeping only the pointers from "other" that are in splitPointerIds.
+    void splitFrom(const MotionEvent& other, std::bitset<MAX_POINTER_ID + 1> splitPointerIds,
+                   int32_t newEventId);
+
     void addSample(
             nsecs_t eventTime,
             const PointerCoords* pointerCoords);
@@ -910,6 +914,11 @@
 
     static std::string actionToString(int32_t action);
 
+    static std::tuple<int32_t /*action*/, std::vector<PointerProperties>,
+                      std::vector<PointerCoords>>
+    split(int32_t action, int32_t flags, int32_t historySize, const std::vector<PointerProperties>&,
+          const std::vector<PointerCoords>&, std::bitset<MAX_POINTER_ID + 1> splitPointerIds);
+
     // MotionEvent will transform various axes in different ways, based on the source. For
     // example, the x and y axes will not have any offsets/translations applied if it comes from a
     // relative mouse device (since SOURCE_RELATIVE_MOUSE is a non-pointer source). These methods
diff --git a/include/input/InputEventBuilders.h b/include/input/InputEventBuilders.h
index 2d23b97..c0c5e24 100644
--- a/include/input/InputEventBuilders.h
+++ b/include/input/InputEventBuilders.h
@@ -118,6 +118,16 @@
         return *this;
     }
 
+    MotionEventBuilder& transform(ui::Transform t) {
+        mTransform = t;
+        return *this;
+    }
+
+    MotionEventBuilder& rawTransform(ui::Transform t) {
+        mRawTransform = t;
+        return *this;
+    }
+
     MotionEvent build() {
         std::vector<PointerProperties> pointerProperties;
         std::vector<PointerCoords> pointerCoords;
@@ -134,12 +144,11 @@
         }
 
         MotionEvent event;
-        static const ui::Transform kIdentityTransform;
         event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
                          mAction, mActionButton, mFlags, /*edgeFlags=*/0, AMETA_NONE, mButtonState,
-                         MotionClassification::NONE, kIdentityTransform,
+                         MotionClassification::NONE, mTransform,
                          /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
-                         mRawYCursorPosition, kIdentityTransform, mDownTime, mEventTime,
+                         mRawYCursorPosition, mRawTransform, mDownTime, mEventTime,
                          mPointers.size(), pointerProperties.data(), pointerCoords.data());
         return event;
     }
@@ -156,6 +165,8 @@
     int32_t mFlags{0};
     float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
     float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
+    ui::Transform mTransform;
+    ui::Transform mRawTransform;
 
     std::vector<PointerBuilder> mPointers;
 };
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index c1770b3..2dd310e 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -256,7 +256,7 @@
 
     if (const auto* rpcFields = maybeRpcFields()) {
         if (binder) {
-            status_t status = writeInt32(1); // non-null
+            status_t status = writeInt32(RpcFields::TYPE_BINDER); // non-null
             if (status != OK) return status;
             uint64_t address;
             // TODO(b/167966510): need to undo this if the Parcel is not sent
@@ -266,7 +266,7 @@
             status = writeUint64(address);
             if (status != OK) return status;
         } else {
-            status_t status = writeInt32(0); // null
+            status_t status = writeInt32(RpcFields::TYPE_BINDER_NULL); // null
             if (status != OK) return status;
         }
         return finishFlattenBinder(binder);
@@ -740,6 +740,12 @@
     return kernelFields->mHasFds;
 }
 
+status_t Parcel::hasBinders(bool* result) const {
+    status_t status = hasBindersInRange(0, dataSize(), result);
+    ALOGE_IF(status != NO_ERROR, "Error %d calling hasBindersInRange()", status);
+    return status;
+}
+
 std::vector<sp<IBinder>> Parcel::debugReadAllStrongBinders() const {
     std::vector<sp<IBinder>> ret;
 
@@ -799,6 +805,46 @@
     return ret;
 }
 
+status_t Parcel::hasBindersInRange(size_t offset, size_t len, bool* result) const {
+    if (len > INT32_MAX || offset > INT32_MAX) {
+        // Don't accept size_t values which may have come from an inadvertent conversion from a
+        // negative int.
+        return BAD_VALUE;
+    }
+    size_t limit;
+    if (__builtin_add_overflow(offset, len, &limit) || limit > mDataSize) {
+        return BAD_VALUE;
+    }
+    *result = false;
+    if (const auto* kernelFields = maybeKernelFields()) {
+#ifdef BINDER_WITH_KERNEL_IPC
+        for (size_t i = 0; i < kernelFields->mObjectsSize; i++) {
+            size_t pos = kernelFields->mObjects[i];
+            if (pos < offset) continue;
+            if (pos + sizeof(flat_binder_object) > offset + len) {
+                if (kernelFields->mObjectsSorted) {
+                    break;
+                } else {
+                    continue;
+                }
+            }
+            const flat_binder_object* flat =
+                    reinterpret_cast<const flat_binder_object*>(mData + pos);
+            if (flat->hdr.type == BINDER_TYPE_BINDER || flat->hdr.type == BINDER_TYPE_HANDLE) {
+                *result = true;
+                break;
+            }
+        }
+#else
+        LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
+        return INVALID_OPERATION;
+#endif // BINDER_WITH_KERNEL_IPC
+    } else if (const auto* rpcFields = maybeRpcFields()) {
+        return INVALID_OPERATION;
+    }
+    return NO_ERROR;
+}
+
 status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool* result) const {
     if (len > INT32_MAX || offset > INT32_MAX) {
         // Don't accept size_t values which may have come from an inadvertent conversion from a
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index d7096d8..5e18b91 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -101,7 +101,9 @@
     void                restoreAllowFds(bool lastValue);
 
     bool                hasFileDescriptors() const;
+    status_t hasBinders(bool* result) const;
     status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool* result) const;
+    status_t hasBindersInRange(size_t offset, size_t length, bool* result) const;
 
     // returns all binder objects in the Parcel
     std::vector<sp<IBinder>> debugReadAllStrongBinders() const;
@@ -647,6 +649,8 @@
     void                freeDataNoInit();
     void                initState();
     void                scanForFds() const;
+    status_t scanForBinders(bool* result) const;
+
     status_t            validateReadData(size_t len) const;
 
     void                updateWorkSourceRequestHeaderPosition() const;
diff --git a/libs/binder/tests/binderParcelUnitTest.cpp b/libs/binder/tests/binderParcelUnitTest.cpp
index 34fc43f..32a70e5 100644
--- a/libs/binder/tests/binderParcelUnitTest.cpp
+++ b/libs/binder/tests/binderParcelUnitTest.cpp
@@ -23,6 +23,7 @@
 using android::BBinder;
 using android::IBinder;
 using android::IPCThreadState;
+using android::NO_ERROR;
 using android::OK;
 using android::Parcel;
 using android::sp;
@@ -164,6 +165,45 @@
     ASSERT_EQ(2, p2.readInt32());
 }
 
+TEST(Parcel, HasBinders) {
+    sp<IBinder> b1 = sp<BBinder>::make();
+
+    Parcel p1;
+    p1.writeInt32(1);
+    p1.writeStrongBinder(b1);
+
+    bool result = false;
+    ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
+    ASSERT_EQ(true, result);
+
+    p1.setDataSize(0); // clear data
+    result = false;
+    ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
+    ASSERT_EQ(false, result);
+    p1.writeStrongBinder(b1); // reset with binder data
+    result = false;
+    ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
+    ASSERT_EQ(true, result);
+
+    Parcel p3;
+    p3.appendFrom(&p1, 0, p1.dataSize());
+    result = false;
+    ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
+    ASSERT_EQ(true, result);
+}
+
+TEST(Parcel, HasBindersInRange) {
+    sp<IBinder> b1 = sp<BBinder>::make();
+    Parcel p1;
+    p1.writeStrongBinder(b1);
+    bool result = false;
+    ASSERT_EQ(NO_ERROR, p1.hasBindersInRange(0, p1.dataSize(), &result));
+    ASSERT_EQ(true, result);
+    result = false;
+    ASSERT_EQ(NO_ERROR, p1.hasBinders(&result));
+    ASSERT_EQ(true, result);
+}
+
 TEST(Parcel, AppendWithBinder) {
     sp<IBinder> b1 = sp<BBinder>::make();
     sp<IBinder> b2 = sp<BBinder>::make();
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 08fe071..5c280f4 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -353,6 +353,20 @@
         FUZZ_LOG() << " status: " << status  << " result: " << result;
     },
     [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
+        FUZZ_LOG() << "about to call hasBinders() with status";
+        bool result;
+        status_t status = p.hasBinders(&result);
+        FUZZ_LOG() << " status: " << status  << " result: " << result;
+    },
+    [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
+        FUZZ_LOG() << "about to call hasBindersInRange() with status";
+        size_t offset = p.readUint32();
+        size_t length = p.readUint32();
+        bool result;
+        status_t status = p.hasBindersInRange(offset, length, &result);
+        FUZZ_LOG() << " status: " << status  << " result: " << result;
+    },
+    [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
         FUZZ_LOG() << "about to call compareDataInRange() with status";
         size_t thisOffset = p.readUint32();
         size_t otherOffset = p.readUint32();
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 9e0ce1d..d58fb42 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -60,6 +60,45 @@
     return !isFromSource(source, AINPUT_SOURCE_CLASS_POINTER);
 }
 
+int32_t resolveActionForSplitMotionEvent(
+        int32_t action, int32_t flags, const std::vector<PointerProperties>& pointerProperties,
+        const std::vector<PointerProperties>& splitPointerProperties) {
+    LOG_ALWAYS_FATAL_IF(splitPointerProperties.empty());
+    const auto maskedAction = MotionEvent::getActionMasked(action);
+    if (maskedAction != AMOTION_EVENT_ACTION_POINTER_DOWN &&
+        maskedAction != AMOTION_EVENT_ACTION_POINTER_UP) {
+        // The action is unaffected by splitting this motion event.
+        return action;
+    }
+    const auto actionIndex = MotionEvent::getActionIndex(action);
+    if (CC_UNLIKELY(actionIndex >= pointerProperties.size())) {
+        LOG(FATAL) << "Action index is out of bounds, index: " << actionIndex;
+    }
+
+    const auto affectedPointerId = pointerProperties[actionIndex].id;
+    std::optional<uint32_t> splitActionIndex;
+    for (uint32_t i = 0; i < splitPointerProperties.size(); i++) {
+        if (affectedPointerId == splitPointerProperties[i].id) {
+            splitActionIndex = i;
+            break;
+        }
+    }
+    if (!splitActionIndex.has_value()) {
+        // The affected pointer is not part of the split motion event.
+        return AMOTION_EVENT_ACTION_MOVE;
+    }
+
+    if (splitPointerProperties.size() > 1) {
+        return maskedAction | (*splitActionIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+    }
+
+    if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
+        return ((flags & AMOTION_EVENT_FLAG_CANCELED) != 0) ? AMOTION_EVENT_ACTION_CANCEL
+                                                            : AMOTION_EVENT_ACTION_UP;
+    }
+    return AMOTION_EVENT_ACTION_DOWN;
+}
+
 } // namespace
 
 const char* motionClassificationToString(MotionClassification classification) {
@@ -584,6 +623,28 @@
     }
 }
 
+void MotionEvent::splitFrom(const android::MotionEvent& other,
+                            std::bitset<MAX_POINTER_ID + 1> splitPointerIds, int32_t newEventId) {
+    // TODO(b/327503168): The down time should be a parameter to the split function, because only
+    //   the caller can know when the first event went down on the target.
+    const nsecs_t splitDownTime = other.mDownTime;
+
+    auto [action, pointerProperties, pointerCoords] =
+            split(other.getAction(), other.getFlags(), other.getHistorySize(),
+                  other.mPointerProperties, other.mSamplePointerCoords, splitPointerIds);
+
+    // Initialize the event with zero pointers, and manually set the split pointers.
+    initialize(newEventId, other.mDeviceId, other.mSource, other.mDisplayId, /*hmac=*/{}, action,
+               other.mActionButton, other.mFlags, other.mEdgeFlags, other.mMetaState,
+               other.mButtonState, other.mClassification, other.mTransform, other.mXPrecision,
+               other.mYPrecision, other.mRawXCursorPosition, other.mRawYCursorPosition,
+               other.mRawTransform, splitDownTime, other.getEventTime(), /*pointerCount=*/0,
+               pointerProperties.data(), pointerCoords.data());
+    mPointerProperties = std::move(pointerProperties);
+    mSamplePointerCoords = std::move(pointerCoords);
+    mSampleEventTimes = other.mSampleEventTimes;
+}
+
 void MotionEvent::addSample(
         int64_t eventTime,
         const PointerCoords* pointerCoords) {
@@ -934,6 +995,45 @@
     return android::base::StringPrintf("%" PRId32, action);
 }
 
+std::tuple<int32_t, std::vector<PointerProperties>, std::vector<PointerCoords>> MotionEvent::split(
+        int32_t action, int32_t flags, int32_t historySize,
+        const std::vector<PointerProperties>& pointerProperties,
+        const std::vector<PointerCoords>& pointerCoords,
+        std::bitset<MAX_POINTER_ID + 1> splitPointerIds) {
+    LOG_ALWAYS_FATAL_IF(!splitPointerIds.any());
+    const auto pointerCount = pointerProperties.size();
+    LOG_ALWAYS_FATAL_IF(pointerCoords.size() != (pointerCount * (historySize + 1)));
+    const auto splitCount = splitPointerIds.count();
+
+    std::vector<PointerProperties> splitPointerProperties;
+    std::vector<PointerCoords> splitPointerCoords;
+
+    for (uint32_t i = 0; i < pointerCount; i++) {
+        if (splitPointerIds.test(pointerProperties[i].id)) {
+            splitPointerProperties.emplace_back(pointerProperties[i]);
+        }
+    }
+    for (uint32_t i = 0; i < pointerCoords.size(); i++) {
+        if (splitPointerIds.test(pointerProperties[i % pointerCount].id)) {
+            splitPointerCoords.emplace_back(pointerCoords[i]);
+        }
+    }
+    LOG_ALWAYS_FATAL_IF(splitPointerCoords.size() !=
+                        (splitPointerProperties.size() * (historySize + 1)));
+
+    if (CC_UNLIKELY(splitPointerProperties.size() != splitCount)) {
+        LOG(FATAL) << "Cannot split MotionEvent: Requested splitting " << splitCount
+                   << " pointers from the original event, but the original event only contained "
+                   << splitPointerProperties.size() << " of those pointers.";
+    }
+
+    // TODO(b/327503168): Verify the splitDownTime here once it is used correctly.
+
+    const auto splitAction = resolveActionForSplitMotionEvent(action, flags, pointerProperties,
+                                                              splitPointerProperties);
+    return {splitAction, splitPointerProperties, splitPointerCoords};
+}
+
 // Apply the given transformation to the point without checking whether the entire transform
 // should be disregarded altogether for the provided source.
 static inline vec2 calculateTransformedXYUnchecked(uint32_t source, const ui::Transform& transform,
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index a965573..540766d 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -23,6 +23,7 @@
 #include <gtest/gtest.h>
 #include <gui/constants.h>
 #include <input/Input.h>
+#include <input/InputEventBuilders.h>
 
 namespace android {
 
@@ -31,6 +32,18 @@
 
 static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION;
 
+static constexpr auto POINTER_0_DOWN =
+        AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+
+static constexpr auto POINTER_1_DOWN =
+        AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+
+static constexpr auto POINTER_0_UP =
+        AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+
+static constexpr auto POINTER_1_UP =
+        AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+
 class BaseTest : public testing::Test {
 protected:
     static constexpr std::array<uint8_t, 32> HMAC = {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10,
@@ -554,6 +567,145 @@
     ASSERT_EQ(event.getX(0), copy.getX(0));
 }
 
+TEST_F(MotionEventTest, SplitPointerDown) {
+    MotionEvent event = MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+                                .downTime(ARBITRARY_DOWN_TIME)
+                                .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4))
+                                .pointer(PointerBuilder(/*id=*/6, ToolType::FINGER).x(6).y(6))
+                                .pointer(PointerBuilder(/*id=*/8, ToolType::FINGER).x(8).y(8))
+                                .build();
+
+    MotionEvent splitDown;
+    std::bitset<MAX_POINTER_ID + 1> splitDownIds{};
+    splitDownIds.set(6, true);
+    splitDown.splitFrom(event, splitDownIds, /*eventId=*/42);
+    ASSERT_EQ(splitDown.getAction(), AMOTION_EVENT_ACTION_DOWN);
+    ASSERT_EQ(splitDown.getPointerCount(), 1u);
+    ASSERT_EQ(splitDown.getPointerId(0), 6);
+    ASSERT_EQ(splitDown.getX(0), 6);
+    ASSERT_EQ(splitDown.getY(0), 6);
+
+    MotionEvent splitPointerDown;
+    std::bitset<MAX_POINTER_ID + 1> splitPointerDownIds{};
+    splitPointerDownIds.set(6, true);
+    splitPointerDownIds.set(8, true);
+    splitPointerDown.splitFrom(event, splitPointerDownIds, /*eventId=*/42);
+    ASSERT_EQ(splitPointerDown.getAction(), POINTER_0_DOWN);
+    ASSERT_EQ(splitPointerDown.getPointerCount(), 2u);
+    ASSERT_EQ(splitPointerDown.getPointerId(0), 6);
+    ASSERT_EQ(splitPointerDown.getX(0), 6);
+    ASSERT_EQ(splitPointerDown.getY(0), 6);
+    ASSERT_EQ(splitPointerDown.getPointerId(1), 8);
+    ASSERT_EQ(splitPointerDown.getX(1), 8);
+    ASSERT_EQ(splitPointerDown.getY(1), 8);
+
+    MotionEvent splitMove;
+    std::bitset<MAX_POINTER_ID + 1> splitMoveIds{};
+    splitMoveIds.set(4, true);
+    splitMove.splitFrom(event, splitMoveIds, /*eventId=*/43);
+    ASSERT_EQ(splitMove.getAction(), AMOTION_EVENT_ACTION_MOVE);
+    ASSERT_EQ(splitMove.getPointerCount(), 1u);
+    ASSERT_EQ(splitMove.getPointerId(0), 4);
+    ASSERT_EQ(splitMove.getX(0), 4);
+    ASSERT_EQ(splitMove.getY(0), 4);
+}
+
+TEST_F(MotionEventTest, SplitPointerUp) {
+    MotionEvent event = MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
+                                .downTime(ARBITRARY_DOWN_TIME)
+                                .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4))
+                                .pointer(PointerBuilder(/*id=*/6, ToolType::FINGER).x(6).y(6))
+                                .pointer(PointerBuilder(/*id=*/8, ToolType::FINGER).x(8).y(8))
+                                .build();
+
+    MotionEvent splitUp;
+    std::bitset<MAX_POINTER_ID + 1> splitUpIds{};
+    splitUpIds.set(4, true);
+    splitUp.splitFrom(event, splitUpIds, /*eventId=*/42);
+    ASSERT_EQ(splitUp.getAction(), AMOTION_EVENT_ACTION_UP);
+    ASSERT_EQ(splitUp.getPointerCount(), 1u);
+    ASSERT_EQ(splitUp.getPointerId(0), 4);
+    ASSERT_EQ(splitUp.getX(0), 4);
+    ASSERT_EQ(splitUp.getY(0), 4);
+
+    MotionEvent splitPointerUp;
+    std::bitset<MAX_POINTER_ID + 1> splitPointerUpIds{};
+    splitPointerUpIds.set(4, true);
+    splitPointerUpIds.set(8, true);
+    splitPointerUp.splitFrom(event, splitPointerUpIds, /*eventId=*/42);
+    ASSERT_EQ(splitPointerUp.getAction(), POINTER_0_UP);
+    ASSERT_EQ(splitPointerUp.getPointerCount(), 2u);
+    ASSERT_EQ(splitPointerUp.getPointerId(0), 4);
+    ASSERT_EQ(splitPointerUp.getX(0), 4);
+    ASSERT_EQ(splitPointerUp.getY(0), 4);
+    ASSERT_EQ(splitPointerUp.getPointerId(1), 8);
+    ASSERT_EQ(splitPointerUp.getX(1), 8);
+    ASSERT_EQ(splitPointerUp.getY(1), 8);
+
+    MotionEvent splitMove;
+    std::bitset<MAX_POINTER_ID + 1> splitMoveIds{};
+    splitMoveIds.set(6, true);
+    splitMoveIds.set(8, true);
+    splitMove.splitFrom(event, splitMoveIds, /*eventId=*/43);
+    ASSERT_EQ(splitMove.getAction(), AMOTION_EVENT_ACTION_MOVE);
+    ASSERT_EQ(splitMove.getPointerCount(), 2u);
+    ASSERT_EQ(splitMove.getPointerId(0), 6);
+    ASSERT_EQ(splitMove.getX(0), 6);
+    ASSERT_EQ(splitMove.getY(0), 6);
+    ASSERT_EQ(splitMove.getPointerId(1), 8);
+    ASSERT_EQ(splitMove.getX(1), 8);
+    ASSERT_EQ(splitMove.getY(1), 8);
+}
+
+TEST_F(MotionEventTest, SplitPointerUpCancel) {
+    MotionEvent event = MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
+                                .downTime(ARBITRARY_DOWN_TIME)
+                                .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4))
+                                .pointer(PointerBuilder(/*id=*/6, ToolType::FINGER).x(6).y(6))
+                                .pointer(PointerBuilder(/*id=*/8, ToolType::FINGER).x(8).y(8))
+                                .addFlag(AMOTION_EVENT_FLAG_CANCELED)
+                                .build();
+
+    MotionEvent splitUp;
+    std::bitset<MAX_POINTER_ID + 1> splitUpIds{};
+    splitUpIds.set(6, true);
+    splitUp.splitFrom(event, splitUpIds, /*eventId=*/42);
+    ASSERT_EQ(splitUp.getAction(), AMOTION_EVENT_ACTION_CANCEL);
+    ASSERT_EQ(splitUp.getPointerCount(), 1u);
+    ASSERT_EQ(splitUp.getPointerId(0), 6);
+    ASSERT_EQ(splitUp.getX(0), 6);
+    ASSERT_EQ(splitUp.getY(0), 6);
+}
+
+TEST_F(MotionEventTest, SplitPointerMove) {
+    MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+                                .downTime(ARBITRARY_DOWN_TIME)
+                                .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4))
+                                .pointer(PointerBuilder(/*id=*/6, ToolType::FINGER).x(6).y(6))
+                                .pointer(PointerBuilder(/*id=*/8, ToolType::FINGER).x(8).y(8))
+                                .transform(ui::Transform(ui::Transform::ROT_90, 100, 100))
+                                .rawTransform(ui::Transform(ui::Transform::FLIP_H, 50, 50))
+                                .build();
+
+    MotionEvent splitMove;
+    std::bitset<MAX_POINTER_ID + 1> splitMoveIds{};
+    splitMoveIds.set(4, true);
+    splitMoveIds.set(8, true);
+    splitMove.splitFrom(event, splitMoveIds, /*eventId=*/42);
+    ASSERT_EQ(splitMove.getAction(), AMOTION_EVENT_ACTION_MOVE);
+    ASSERT_EQ(splitMove.getPointerCount(), 2u);
+    ASSERT_EQ(splitMove.getPointerId(0), 4);
+    ASSERT_EQ(splitMove.getX(0), event.getX(0));
+    ASSERT_EQ(splitMove.getY(0), event.getY(0));
+    ASSERT_EQ(splitMove.getRawX(0), event.getRawX(0));
+    ASSERT_EQ(splitMove.getRawY(0), event.getRawY(0));
+    ASSERT_EQ(splitMove.getPointerId(1), 8);
+    ASSERT_EQ(splitMove.getX(1), event.getX(2));
+    ASSERT_EQ(splitMove.getY(1), event.getY(2));
+    ASSERT_EQ(splitMove.getRawX(1), event.getRawX(2));
+    ASSERT_EQ(splitMove.getRawY(1), event.getRawY(2));
+}
+
 TEST_F(MotionEventTest, OffsetLocation) {
     MotionEvent event;
     initializeEventWithHistory(&event);
diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp
index 1e7e707..00514c4 100644
--- a/libs/sensorprivacy/Android.bp
+++ b/libs/sensorprivacy/Android.bp
@@ -57,7 +57,6 @@
 filegroup {
     name: "libsensorprivacy_aidl",
     srcs: [
-        "aidl/android/hardware/CameraPrivacyAllowlistEntry.aidl",
         "aidl/android/hardware/ISensorPrivacyListener.aidl",
         "aidl/android/hardware/ISensorPrivacyManager.aidl",
     ],
diff --git a/libs/sensorprivacy/SensorPrivacyManager.cpp b/libs/sensorprivacy/SensorPrivacyManager.cpp
index fe93786..3f3ad93 100644
--- a/libs/sensorprivacy/SensorPrivacyManager.cpp
+++ b/libs/sensorprivacy/SensorPrivacyManager.cpp
@@ -155,10 +155,9 @@
     return DISABLED;
 }
 
-std::vector<hardware::CameraPrivacyAllowlistEntry>
-        SensorPrivacyManager::getCameraPrivacyAllowlist(){
+std::vector<String16> SensorPrivacyManager::getCameraPrivacyAllowlist(){
     sp<hardware::ISensorPrivacyManager> service = getService();
-    std::vector<hardware::CameraPrivacyAllowlistEntry> result;
+    std::vector<String16> result;
     if (service != nullptr) {
         service->getCameraPrivacyAllowlist(&result);
         return result;
diff --git a/libs/sensorprivacy/aidl/android/hardware/CameraPrivacyAllowlistEntry.aidl b/libs/sensorprivacy/aidl/android/hardware/CameraPrivacyAllowlistEntry.aidl
deleted file mode 100644
index 03e1537..0000000
--- a/libs/sensorprivacy/aidl/android/hardware/CameraPrivacyAllowlistEntry.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * 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.
- */
-
-package android.hardware;
-
-parcelable CameraPrivacyAllowlistEntry {
-    String packageName;
-    boolean isMandatory;
-}
diff --git a/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl b/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl
index b6bd39e..f707187 100644
--- a/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl
+++ b/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl
@@ -16,7 +16,6 @@
 
 package android.hardware;
 
-import android.hardware.CameraPrivacyAllowlistEntry;
 import android.hardware.ISensorPrivacyListener;
 
 /** @hide */
@@ -43,7 +42,7 @@
 
     void setToggleSensorPrivacyForProfileGroup(int userId, int source, int sensor, boolean enable);
 
-    List<CameraPrivacyAllowlistEntry> getCameraPrivacyAllowlist();
+    List<String> getCameraPrivacyAllowlist();
 
     int getToggleSensorPrivacyState(int toggleType, int sensor);
 
diff --git a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
index 9e97e16..8935b76 100644
--- a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
+++ b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
@@ -45,9 +45,7 @@
     enum {
         ENABLED = 1,
         DISABLED = 2,
-        AUTOMOTIVE_DRIVER_ASSISTANCE_HELPFUL_APPS = 3,
-        AUTOMOTIVE_DRIVER_ASSISTANCE_REQUIRED_APPS = 4,
-        AUTOMOTIVE_DRIVER_ASSISTANCE_APPS = 5
+        ENABLED_EXCEPT_ALLOWLISTED_APPS = 3
     };
 
     SensorPrivacyManager();
@@ -62,7 +60,7 @@
     bool isToggleSensorPrivacyEnabled(int toggleType, int sensor);
     status_t isToggleSensorPrivacyEnabled(int toggleType, int sensor, bool &result);
     int getToggleSensorPrivacyState(int toggleType, int sensor);
-    std::vector<hardware::CameraPrivacyAllowlistEntry> getCameraPrivacyAllowlist();
+    std::vector<String16> getCameraPrivacyAllowlist();
     bool isCameraPrivacyEnabled(String16 packageName);
 
     status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 7f54bf1..9c04a1d 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4268,72 +4268,13 @@
 std::unique_ptr<MotionEntry> InputDispatcher::splitMotionEvent(
         const MotionEntry& originalMotionEntry, std::bitset<MAX_POINTER_ID + 1> pointerIds,
         nsecs_t splitDownTime) {
-    ALOG_ASSERT(pointerIds.any());
+    const auto& [action, pointerProperties, pointerCoords] =
+            MotionEvent::split(originalMotionEntry.action, originalMotionEntry.flags,
+                               /*historySize=*/0, originalMotionEntry.pointerProperties,
+                               originalMotionEntry.pointerCoords, pointerIds);
 
-    uint32_t splitPointerIndexMap[MAX_POINTERS];
-    std::vector<PointerProperties> splitPointerProperties;
-    std::vector<PointerCoords> splitPointerCoords;
-
-    uint32_t originalPointerCount = originalMotionEntry.getPointerCount();
-    uint32_t splitPointerCount = 0;
-
-    for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
-         originalPointerIndex++) {
-        const PointerProperties& pointerProperties =
-                originalMotionEntry.pointerProperties[originalPointerIndex];
-        uint32_t pointerId = uint32_t(pointerProperties.id);
-        if (pointerIds.test(pointerId)) {
-            splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
-            splitPointerProperties.push_back(pointerProperties);
-            splitPointerCoords.push_back(originalMotionEntry.pointerCoords[originalPointerIndex]);
-            splitPointerCount += 1;
-        }
-    }
-
-    if (splitPointerCount != pointerIds.count()) {
-        // This is bad.  We are missing some of the pointers that we expected to deliver.
-        // Most likely this indicates that we received an ACTION_MOVE events that has
-        // different pointer ids than we expected based on the previous ACTION_DOWN
-        // or ACTION_POINTER_DOWN events that caused us to decide to split the pointers
-        // in this way.
-        ALOGW("Dropping split motion event because the pointer count is %d but "
-              "we expected there to be %zu pointers.  This probably means we received "
-              "a broken sequence of pointer ids from the input device: %s",
-              splitPointerCount, pointerIds.count(), originalMotionEntry.getDescription().c_str());
-        return nullptr;
-    }
-
-    int32_t action = originalMotionEntry.action;
-    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-    if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN ||
-        maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
-        int32_t originalPointerIndex = MotionEvent::getActionIndex(action);
-        const PointerProperties& pointerProperties =
-                originalMotionEntry.pointerProperties[originalPointerIndex];
-        uint32_t pointerId = uint32_t(pointerProperties.id);
-        if (pointerIds.test(pointerId)) {
-            if (pointerIds.count() == 1) {
-                // The first/last pointer went down/up.
-                action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
-                        ? AMOTION_EVENT_ACTION_DOWN
-                        : (originalMotionEntry.flags & AMOTION_EVENT_FLAG_CANCELED) != 0
-                                ? AMOTION_EVENT_ACTION_CANCEL
-                                : AMOTION_EVENT_ACTION_UP;
-            } else {
-                // A secondary pointer went down/up.
-                uint32_t splitPointerIndex = 0;
-                while (pointerId != uint32_t(splitPointerProperties[splitPointerIndex].id)) {
-                    splitPointerIndex += 1;
-                }
-                action = maskedAction |
-                        (splitPointerIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
-            }
-        } else {
-            // An unrelated pointer changed.
-            action = AMOTION_EVENT_ACTION_MOVE;
-        }
-    }
-
+    // TODO(b/327503168): Move this check inside MotionEvent::split once all callers handle it
+    //   correctly.
     if (action == AMOTION_EVENT_ACTION_DOWN && splitDownTime != originalMotionEntry.eventTime) {
         logDispatchStateLocked();
         LOG_ALWAYS_FATAL("Split motion event has mismatching downTime and eventTime for "
@@ -4361,7 +4302,7 @@
                                           originalMotionEntry.yPrecision,
                                           originalMotionEntry.xCursorPosition,
                                           originalMotionEntry.yCursorPosition, splitDownTime,
-                                          splitPointerProperties, splitPointerCoords);
+                                          pointerProperties, pointerCoords);
 
     return splitMotionEntry;
 }
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 118d928..bd54d24 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -340,8 +340,8 @@
             binder::Status onSensorPrivacyChanged(int toggleType, int sensor,
                                                   bool enabled);
 
-            // This callback is used for additional automotive-specific states for sensor privacy
-            // such as AUTO_DRIVER_ASSISTANCE_APPS. The newly defined states will only be valid
+            // This callback is used for additional automotive-specific state for sensor privacy
+            // such as ENABLED_EXCEPT_ALLOWLISTED_APPS. The newly defined states will only be valid
             // for camera privacy on automotive devices. onSensorPrivacyChanged() will still be
             // invoked whenever the enabled status of a toggle changes.
             binder::Status onSensorPrivacyStateChanged(int, int, int) {return binder::Status::ok();}
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 46252e1..d771803 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -45,6 +45,7 @@
         "android.hardware.power-ndk_shared",
         "librenderengine_deps",
         "libtimestats_deps",
+        "libsurfaceflinger_common_deps",
         "surfaceflinger_defaults",
     ],
     cflags: [
@@ -85,7 +86,6 @@
         "libinput",
         "libutils",
         "libSurfaceFlingerProp",
-        "server_configurable_flags",
     ],
     static_libs: [
         "libaidlcommonsupport",
@@ -98,10 +98,8 @@
         "libscheduler",
         "libserviceutils",
         "libshaders",
-        "libsurfaceflinger_common",
         "libtimestats",
         "libtonemap",
-        "libsurfaceflingerflags",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 0b01c66..a52cc87 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -38,7 +38,6 @@
         "libSurfaceFlingerProp",
         "libui",
         "libutils",
-        "server_configurable_flags",
     ],
     static_libs: [
         "liblayers_proto",
@@ -90,24 +89,23 @@
 
 cc_library {
     name: "libcompositionengine",
-    defaults: ["libcompositionengine_defaults"],
-    static_libs: [
-        "libsurfaceflinger_common",
-        "libsurfaceflingerflags",
+    defaults: [
+        "libcompositionengine_defaults",
+        "libsurfaceflinger_common_deps",
     ],
     srcs: [
         ":libcompositionengine_sources",
     ],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
-    shared_libs: [
-        "server_configurable_flags",
-    ],
 }
 
 cc_library {
     name: "libcompositionengine_mocks",
-    defaults: ["libcompositionengine_defaults"],
+    defaults: [
+        "libcompositionengine_defaults",
+        "libsurfaceflinger_common_test_deps",
+    ],
     srcs: [
         "mock/CompositionEngine.cpp",
         "mock/Display.cpp",
@@ -123,11 +121,6 @@
         "libgtest",
         "libgmock",
         "libcompositionengine",
-        "libsurfaceflinger_common_test",
-        "libsurfaceflingerflags_test",
-    ],
-    shared_libs: [
-        "server_configurable_flags",
     ],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
@@ -140,7 +133,10 @@
         "frameworks/native/services/surfaceflinger/common/include",
         "frameworks/native/services/surfaceflinger/tests/unittests",
     ],
-    defaults: ["libcompositionengine_defaults"],
+    defaults: [
+        "libcompositionengine_defaults",
+        "libsurfaceflinger_common_test_deps",
+    ],
     srcs: [
         ":libcompositionengine_sources",
         "tests/planner/CachedSetTest.cpp",
@@ -166,14 +162,11 @@
         "librenderengine_mocks",
         "libgmock",
         "libgtest",
-        "libsurfaceflinger_common_test",
-        "libsurfaceflingerflags_test",
     ],
     shared_libs: [
         // For some reason, libvulkan isn't picked up from librenderengine
         // Probably ASAN related?
         "libvulkan",
-        "server_configurable_flags",
     ],
     sanitize: {
         hwaddress: true,
diff --git a/services/surfaceflinger/Scheduler/Android.bp b/services/surfaceflinger/Scheduler/Android.bp
index 16776cf..5455fdc 100644
--- a/services/surfaceflinger/Scheduler/Android.bp
+++ b/services/surfaceflinger/Scheduler/Android.bp
@@ -53,7 +53,10 @@
 cc_test {
     name: "libscheduler_test",
     test_suites: ["device-tests"],
-    defaults: ["libscheduler_defaults"],
+    defaults: [
+        "libscheduler_defaults",
+        "libsurfaceflinger_common_test_deps",
+    ],
     srcs: [
         "tests/FrameTargeterTest.cpp",
         "tests/PresentLatencyTrackerTest.cpp",
@@ -63,9 +66,5 @@
         "libgmock",
         "libgtest",
         "libscheduler",
-        "libsurfaceflingerflags_test",
-    ],
-    shared_libs: [
-        "server_configurable_flags",
     ],
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8847cee..2501f4b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -854,6 +854,9 @@
     mCompositionEngine->getHwComposer().setCallback(*this);
     ClientCache::getInstance().setRenderEngine(&getRenderEngine());
 
+    mHasReliablePresentFences =
+            !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE);
+
     enableLatchUnsignaledConfig = getLatchUnsignaledConfig();
 
     if (base::GetBoolProperty("debug.sf.enable_hwc_vds"s, false)) {
@@ -927,9 +930,7 @@
 
     // Inform native graphics APIs whether the present timestamp is supported:
 
-    const bool presentFenceReliable =
-            !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE);
-    mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable);
+    mStartPropertySetThread = getFactory().createStartPropertySetThread(mHasReliablePresentFences);
 
     if (mStartPropertySetThread->Start() != NO_ERROR) {
         ALOGE("Run StartPropertySetThread failed!");
@@ -1003,9 +1004,7 @@
         FrameEvent::RELEASE,
     };
 
-    ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
-
-    if (!getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) {
+    if (mHasReliablePresentFences) {
         outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
     }
     return NO_ERROR;
@@ -3031,10 +3030,9 @@
     // but that should be okay since CompositorTiming has snapping logic.
     const TimePoint compositeTime =
             TimePoint::fromNs(mCompositionEngine->getLastFrameRefreshTimestamp());
-    const Duration presentLatency =
-            getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)
-            ? Duration::zero()
-            : mPresentLatencyTracker.trackPendingFrame(compositeTime, pacesetterPresentFenceTime);
+    const Duration presentLatency = mHasReliablePresentFences
+            ? mPresentLatencyTracker.trackPendingFrame(compositeTime, pacesetterPresentFenceTime)
+            : Duration::zero();
 
     const auto schedule = mScheduler->getVsyncSchedule();
     const TimePoint vsyncDeadline = schedule->vsyncDeadlineAfter(presentTime);
@@ -4357,7 +4355,7 @@
         features |= Feature::kTracePredictedVsync;
     }
     if (!base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false) &&
-        !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) {
+        mHasReliablePresentFences) {
         features |= Feature::kPresentFences;
     }
     if (display->refreshRateSelector().kernelIdleTimerController()) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1ce8606..005f2e6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1224,6 +1224,7 @@
     // constant members (no synchronization needed for access)
     const nsecs_t mBootTime = systemTime();
     bool mIsUserBuild = true;
+    bool mHasReliablePresentFences = false;
 
     // Can only accessed from the main thread, these members
     // don't need synchronization
diff --git a/services/surfaceflinger/common/Android.bp b/services/surfaceflinger/common/Android.bp
index f2ff00b..4a89dd0 100644
--- a/services/surfaceflinger/common/Android.bp
+++ b/services/surfaceflinger/common/Android.bp
@@ -35,6 +35,7 @@
     ],
     static_libs: [
         "libsurfaceflingerflags",
+        "android.os.flags-aconfig-cc",
     ],
 }
 
@@ -45,5 +46,30 @@
     ],
     static_libs: [
         "libsurfaceflingerflags_test",
+        "android.os.flags-aconfig-cc-test",
+    ],
+}
+
+cc_defaults {
+    name: "libsurfaceflinger_common_deps",
+    shared_libs: [
+        "server_configurable_flags",
+    ],
+    static_libs: [
+        "libsurfaceflinger_common",
+        "libsurfaceflingerflags",
+        "android.os.flags-aconfig-cc",
+    ],
+}
+
+cc_defaults {
+    name: "libsurfaceflinger_common_test_deps",
+    shared_libs: [
+        "server_configurable_flags",
+    ],
+    static_libs: [
+        "libsurfaceflinger_common_test",
+        "libsurfaceflingerflags_test",
+        "android.os.flags-aconfig-cc-test",
     ],
 }
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index b7f06a9..3b669c6 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -26,6 +26,7 @@
 #include <server_configurable_flags/get_flags.h>
 #include <cinttypes>
 
+#include <android_os.h>
 #include <com_android_graphics_surfaceflinger_flags.h>
 
 namespace android {
@@ -109,6 +110,7 @@
 
     /// Trunk stable server flags ///
     DUMP_SERVER_FLAG(refresh_rate_overlay_on_external_display);
+    DUMP_SERVER_FLAG(adpf_use_fmq_channel);
 
     /// Trunk stable readonly flags ///
     DUMP_READ_ONLY_FLAG(connected_display);
@@ -158,7 +160,7 @@
         return getServerConfigurableFlag(serverFlagName);                                   \
     }
 
-#define FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, checkForBootCompleted)                \
+#define FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, checkForBootCompleted, owner)         \
     bool FlagManager::name() const {                                                            \
         if (checkForBootCompleted) {                                                            \
             LOG_ALWAYS_FATAL_IF(!mBootCompleted,                                                \
@@ -166,21 +168,24 @@
                                 __func__);                                                      \
         }                                                                                       \
         static const std::optional<bool> debugOverride = getBoolProperty(syspropOverride);      \
-        static const bool value = getFlagValue([] { return flags::name(); }, debugOverride);    \
+        static const bool value = getFlagValue([] { return owner ::name(); }, debugOverride);   \
         if (mUnitTestMode) {                                                                    \
             /*                                                                                  \
              * When testing, we don't want to rely on the cached `value` or the debugOverride.  \
              */                                                                                 \
-            return flags::name();                                                               \
+            return owner ::name();                                                              \
         }                                                                                       \
         return value;                                                                           \
     }
 
 #define FLAG_MANAGER_SERVER_FLAG(name, syspropOverride) \
-    FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true)
+    FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true, flags)
 
 #define FLAG_MANAGER_READ_ONLY_FLAG(name, syspropOverride) \
-    FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, false)
+    FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, false, flags)
+
+#define FLAG_MANAGER_SERVER_FLAG_IMPORTED(name, syspropOverride, owner) \
+    FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true, owner)
 
 /// Legacy server flags ///
 FLAG_MANAGER_LEGACY_SERVER_FLAG(test_flag, "", "")
@@ -216,4 +221,7 @@
 /// Trunk stable server flags ///
 FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
 
+/// Trunk stable server flags from outside SurfaceFlinger ///
+FLAG_MANAGER_SERVER_FLAG_IMPORTED(adpf_use_fmq_channel, "", android::os)
+
 } // namespace android
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 241c814..763963e 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -49,6 +49,7 @@
 
     /// Trunk stable server flags ///
     bool refresh_rate_overlay_on_external_display() const;
+    bool adpf_use_fmq_channel() const;
 
     /// Trunk stable readonly flags ///
     bool connected_display() const;
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index dab0a3f..925fe0b 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -27,6 +27,7 @@
     defaults: [
         "android.hardware.graphics.common-ndk_shared",
         "surfaceflinger_defaults",
+        "libsurfaceflinger_common_test_deps",
     ],
     test_suites: ["device-tests"],
     srcs: [
@@ -66,7 +67,6 @@
     static_libs: [
         "liblayers_proto",
         "android.hardware.graphics.composer@2.1",
-        "libsurfaceflingerflags",
     ],
     shared_libs: [
         "android.hardware.graphics.common@1.2",
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 08cfc55..0c13db3 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -149,6 +149,7 @@
         "android.hardware.graphics.composer3-ndk_static",
         "android.hardware.power-ndk_static",
         "librenderengine_deps",
+        "libsurfaceflinger_common_test_deps",
     ],
     static_libs: [
         "android.hardware.common-V2-ndk",
@@ -173,13 +174,11 @@
         "librenderengine_mocks",
         "libscheduler",
         "libserviceutils",
-        "libsurfaceflinger_common_test",
         "libtimestats",
         "libtimestats_atoms_proto",
         "libtimestats_proto",
         "libtonemap",
         "perfetto_trace_protos",
-        "libsurfaceflingerflags_test",
     ],
     shared_libs: [
         "android.hardware.configstore-utils",
@@ -208,7 +207,6 @@
         "libsync",
         "libui",
         "libutils",
-        "server_configurable_flags",
     ],
     header_libs: [
         "android.hardware.graphics.composer3-command-buffer",