Merge "Add limit parameter to be applied to scaled audio haptic data" into sc-v2-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 4eb601d..2d11b90 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1241,8 +1241,15 @@
         if (status == OK) {
             dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
             std::chrono::duration<double> elapsed_seconds;
-            status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
-                                       /* as_proto = */ false, elapsed_seconds, bytes_written);
+            if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
+                service == String16("meminfo")) {
+                // Use a longer timeout for meminfo, since 30s is not always enough.
+                status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
+                                           /* as_proto = */ false, elapsed_seconds, bytes_written);
+            } else {
+                status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
+                                           /* as_proto = */ false, elapsed_seconds, bytes_written);
+            }
             dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
             bool dump_complete = (status == OK);
             dumpsys.stopDumpThread(dump_complete);
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index cd5c36f..871edfc 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -43,7 +43,7 @@
 #include <log/log.h>               // TODO: Move everything to base/logging.
 #include <openssl/sha.h>
 #include <private/android_filesystem_config.h>
-#include <processgroup/sched_policy.h>
+#include <processgroup/processgroup.h>
 #include <selinux/android.h>
 #include <server_configurable_flags/get_flags.h>
 #include <system/thread_defs.h>
@@ -282,8 +282,8 @@
 
 static void SetDex2OatScheduling(bool set_to_bg) {
     if (set_to_bg) {
-        if (set_sched_policy(0, SP_BACKGROUND) < 0) {
-            PLOG(ERROR) << "set_sched_policy failed";
+        if (!SetTaskProfiles(0, {"Dex2OatBootComplete"})) {
+            LOG(ERROR) << "Failed to set dex2oat task profile";
             exit(DexoptReturnCodes::kSetSchedPolicy);
         }
         if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
@@ -492,14 +492,6 @@
                  std::to_string(min_new_methods_percent_change));
         }
 
-        // On-device signing related. odsign sets the system property odsign.verification.success if
-        // AOT artifacts have the expected signatures.
-        const bool trust_art_apex_data_files =
-                ::android::base::GetBoolProperty("odsign.verification.success", false);
-        if (!trust_art_apex_data_files) {
-            AddRuntimeArg("-Xdeny-art-apex-data-files");
-        }
-
         // Do not add after dex2oat_flags, they should override others for debugging.
         PrepareArgs(profman_bin);
     }
diff --git a/include/input/Input.h b/include/input/Input.h
index e281ff4..d88dcfe 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -95,7 +95,7 @@
     AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT =
             android::os::IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT, // 0x800,
 #else
-    AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800;
+    AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800,
 #endif
 
     /* Motion event is inconsistent with previously sent motion events. */
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index b58d919..1010a2d 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -52,6 +52,9 @@
       "name": "CtsOsTestCases",
       "options": [
         {
+          "exclude-annotation": "android.platform.test.annotations.LargeTest"
+        },
+        {
           "exclude-filter": "android.os.cts.BuildTest#testSdkInt"
         },
         {
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index ebc436f..d9024fa 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -171,6 +171,8 @@
           .apply();
     mNumAcquired = 0;
     mNumFrameAvailable = 0;
+    BQA_LOGV("BLASTBufferQueue created width=%d height=%d format=%d mTransformHint=%d", width,
+             height, format, mTransformHint);
 }
 
 BLASTBufferQueue::~BLASTBufferQueue() {
@@ -190,7 +192,6 @@
 void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
                               int32_t format) {
     std::unique_lock _lock{mMutex};
-    BQA_LOGV("update width=%d height=%d format=%d", width, height, format);
     if (mFormat != format) {
         mFormat = format;
         mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
@@ -212,6 +213,8 @@
         mTransformHint = mSurfaceControl->getTransformHint();
         mBufferItemConsumer->setTransformHint(mTransformHint);
     }
+    BQA_LOGV("update width=%d height=%d format=%d mTransformHint=%d", width, height, format,
+             mTransformHint);
 
     ui::Size newSize(width, height);
     if (mRequestedSize != newSize) {
@@ -267,6 +270,7 @@
 
                 mTransformHint = stat.transformHint;
                 mBufferItemConsumer->setTransformHint(mTransformHint);
+                BQA_LOGV("updated mTransformHint=%d", mTransformHint);
                 // Update frametime stamps if the frame was latched and presented, indicated by a
                 // valid latch time.
                 if (stat.latchTime > 0) {
@@ -339,6 +343,7 @@
         mTransformHint = transformHint;
         mSurfaceControl->setTransformHint(transformHint);
         mBufferItemConsumer->setTransformHint(mTransformHint);
+        BQA_LOGV("updated mTransformHint=%d", mTransformHint);
     }
 
     // Calculate how many buffers we need to hold before we release them back
@@ -422,7 +427,7 @@
     }
 
     if (rejectBuffer(bufferItem)) {
-        BQA_LOGE("rejecting buffer:active_size=%dx%d, requested_size=%dx%d"
+        BQA_LOGE("rejecting buffer:active_size=%dx%d, requested_size=%dx%d "
                  "buffer{size=%dx%d transform=%d}",
                  mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height,
                  buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform);
@@ -515,11 +520,11 @@
 
     BQA_LOGV("processNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64
              " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d"
-             " graphicBufferId=%" PRIu64 "%s",
+             " graphicBufferId=%" PRIu64 "%s transform=%d",
              mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction),
              bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp ? "(auto)" : "",
              static_cast<uint32_t>(mPendingTransactions.size()), bufferItem.mGraphicBuffer->getId(),
-             bufferItem.mAutoRefresh ? " mAutoRefresh" : "");
+             bufferItem.mAutoRefresh ? " mAutoRefresh" : "", bufferItem.mTransform);
 }
 
 Rect BLASTBufferQueue::computeCrop(const BufferItem& item) {
@@ -646,14 +651,6 @@
     status_t setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) override {
         return mBbq->setFrameTimelineInfo(frameTimelineInfo);
     }
- protected:
-    uint32_t getTransformHint() const override {
-        if (mStickyTransform == 0 && !transformToDisplayInverse()) {
-            return mBbq->getLastTransformHint();
-        } else {
-            return 0;
-        }
-    }
 };
 
 // TODO: Can we coalesce this with frame updates? Need to confirm
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 001570c..17d614e 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -564,6 +564,10 @@
     return (what & layer_state_t::eBufferChanged) || (what & layer_state_t::eCachedBufferChanged);
 }
 
+bool layer_state_t::hasValidBuffer() const {
+    return buffer || cachedBuffer.isValid();
+}
+
 status_t layer_state_t::matrix22_t::write(Parcel& output) const {
     SAFE_PARCEL(output.writeFloat, dsdx);
     SAFE_PARCEL(output.writeFloat, dtdx);
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 92de74a..d1a9a04 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -124,6 +124,7 @@
     status_t write(Parcel& output) const;
     status_t read(const Parcel& input);
     bool hasBufferChanges() const;
+    bool hasValidBuffer() const;
 
     struct matrix22_t {
         float dsdx{0};
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 6ff67aa..9082d27 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -71,6 +71,10 @@
         return mBlastBufferQueueAdapter->mSurfaceControl;
     }
 
+    sp<Surface> getSurface() {
+        return mBlastBufferQueueAdapter->getSurface(false /* includeSurfaceControlHandle */);
+    }
+
     void waitForCallbacks() {
         std::unique_lock lock{mBlastBufferQueueAdapter->mMutex};
         // Wait until all but one of the submitted buffers have been released.
@@ -758,6 +762,48 @@
                                {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}));
 }
 
+TEST_F(BLASTBufferQueueTest, TransformHint) {
+    // Transform hint is provided to BBQ via the surface control passed by WM
+    mSurfaceControl->setTransformHint(ui::Transform::ROT_90);
+
+    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+    sp<IGraphicBufferProducer> igbProducer = adapter.getIGraphicBufferProducer();
+    ASSERT_NE(nullptr, igbProducer.get());
+    ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(2));
+    sp<Surface> surface = adapter.getSurface();
+
+    // Before connecting to the surface, we do not get a valid transform hint
+    int transformHint;
+    surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
+    ASSERT_EQ(ui::Transform::ROT_0, transformHint);
+
+    ASSERT_EQ(NO_ERROR,
+              surface->connect(NATIVE_WINDOW_API_CPU, new TestProducerListener(igbProducer)));
+
+    // After connecting to the surface, we should get the correct hint.
+    surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
+    ASSERT_EQ(ui::Transform::ROT_90, transformHint);
+
+    ANativeWindow_Buffer buffer;
+    surface->lock(&buffer, nullptr /* inOutDirtyBounds */);
+
+    // Transform hint is updated via callbacks or surface control updates
+    mSurfaceControl->setTransformHint(ui::Transform::ROT_0);
+    adapter.update(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+
+    // The hint does not change and matches the value used when dequeueing the buffer.
+    surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
+    ASSERT_EQ(ui::Transform::ROT_90, transformHint);
+
+    surface->unlockAndPost();
+
+    // After queuing the buffer, we get the updated transform hint
+    surface->query(NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
+    ASSERT_EQ(ui::Transform::ROT_0, transformHint);
+
+    adapter.waitForCallbacks();
+}
+
 class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest {
 public:
     void test(uint32_t tr) {
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 081de2e..ae8f238 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -56,42 +56,64 @@
                              const std::shared_ptr<ExternalTexture>& dstTexture) {
     // Somewhat arbitrary dimensions, but on screen and slightly shorter, based
     // on actual use.
-    FloatRect rect(0, 0, display.physicalDisplay.width(), display.physicalDisplay.height() - 30);
+    const Rect& displayRect = display.physicalDisplay;
+    FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+    FloatRect smallerRect(20, 20, displayRect.width()-20, displayRect.height()-20);
+
     LayerSettings layer{
             .geometry =
                     Geometry{
                             .boundaries = rect,
                             .roundedCornersCrop = rect,
+                            .roundedCornersRadius = 50.f,
                     },
             // drawShadow ignores alpha
             .shadow =
                     ShadowSettings{
+                            .boundaries = rect,
                             .ambientColor = vec4(0, 0, 0, 0.00935997f),
                             .spotColor = vec4(0, 0, 0, 0.0455841f),
-                            .lightPos = vec3(370.508f, -1527.03f, 1650.f),
-                            .lightRadius = 2200.0f,
-                            .length = 0.955342f,
+                            .lightPos = vec3(500.f, -1500.f, 1500.f),
+                            .lightRadius = 2500.0f,
+                            .length = 15.f,
                     },
-            // important that this matches dest so the general shadow fragment shader doesn't
-            // have color correction added, and important that it be srgb, so the *vertex* shader
-            // doesn't have color correction added.
-            .sourceDataspace = kDestDataSpace,
             // setting this is mandatory for shadows and blurs
             .skipContentDraw = true,
+            .alpha = 1,
+    };
+    LayerSettings caster{
+            .geometry =
+                    Geometry{
+                            .boundaries = smallerRect,
+                            .roundedCornersCrop = rect,
+                            .roundedCornersRadius = 50.f,
+                    },
+            .source =
+                    PixelSource{
+                            .solidColor = half3(0.f, 0.f, 0.f),
+                    },
+            .alpha = 1,
     };
 
-    auto layers = std::vector<const LayerSettings*>{&layer};
-    // The identity matrix will generate the fast shader
-    renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(),
-                             nullptr);
-    // This matrix, which has different scales for x and y, will
-    // generate the slower (more general case) version, which has variants for translucent
-    // casters and rounded rects.
-    layer.geometry.positionTransform = kScaleAsymmetric;
-    for (auto translucent : {false, true}) {
-        layer.shadow.casterIsTranslucent = translucent;
-        renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
-                                 base::unique_fd(), nullptr);
+    auto layers = std::vector<const LayerSettings*>{&layer, &caster};
+    // When sourceDataspace matches dest, the general shadow fragment shader doesn't
+    // have color correction added.
+    // independently, when it is not srgb, the *vertex* shader has color correction added.
+    // This may be a bug, but the shader still needs to be cached as it is triggered
+    // during youtube pip.
+    for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) {
+        layer.sourceDataspace = dataspace;
+        // The 2nd matrix, which has different scales for x and y, will
+        // generate the slower (more general case) shadow shader
+        for (auto transform : {mat4(), kScaleAndTranslate, kFlip}) {
+            layer.geometry.positionTransform = transform;
+            caster.geometry.positionTransform = transform;
+            for (bool translucent : {false, true}){
+                layer.shadow.casterIsTranslucent = translucent;
+                renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
+                                        base::unique_fd(), nullptr);
+            }
+        }
     }
 }
 
@@ -329,6 +351,12 @@
                 .maxLuminance = 500,
                 .outputDataspace = kDestDataSpace,
         };
+        DisplaySettings p3Display{
+                .physicalDisplay = displayRect,
+                .clip = displayRect,
+                .maxLuminance = 500,
+                .outputDataspace = kOtherDataSpace,
+        };
 
         const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
 
@@ -354,6 +382,7 @@
         drawHolePunchLayer(renderengine, display, dstTexture);
         drawSolidLayers(renderengine, display, dstTexture);
         drawShadowLayers(renderengine, display, srcTexture);
+        drawShadowLayers(renderengine, p3Display, srcTexture);
 
         if (renderengine->supportsBackgroundBlur()) {
             drawBlurLayers(renderengine, display, dstTexture);
diff --git a/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl b/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl
index f91f5b9..9564cba 100644
--- a/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl
+++ b/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl
@@ -36,7 +36,7 @@
 
     void setSensorPrivacy(boolean enable);
 
-    void setIndividualSensorPrivacy(int userId, int sensor, boolean enable);
+    void setIndividualSensorPrivacy(int userId, int source, int sensor, boolean enable);
 
-    void setIndividualSensorPrivacyForProfileGroup(int userId, int sensor, boolean enable);
+    void setIndividualSensorPrivacyForProfileGroup(int userId, int source, int sensor, boolean enable);
 }
diff --git a/libs/ui/include/ui/Transform.h b/libs/ui/include/ui/Transform.h
index a197b3b..33fbe05 100644
--- a/libs/ui/include/ui/Transform.h
+++ b/libs/ui/include/ui/Transform.h
@@ -112,6 +112,7 @@
     void dump(const char* name, const char* prefix = "") const;
 
     static constexpr RotationFlags toRotationFlags(Rotation);
+    static constexpr Rotation toRotation(RotationFlags);
 
 private:
     struct mat33 {
@@ -151,5 +152,20 @@
     }
 }
 
+inline constexpr Rotation Transform::toRotation(Transform::RotationFlags rotationFlags) {
+    switch (rotationFlags) {
+        case ROT_0:
+            return ROTATION_0;
+        case ROT_90:
+            return ROTATION_90;
+        case ROT_180:
+            return ROTATION_180;
+        case ROT_270:
+            return ROTATION_270;
+        default:
+            return ROTATION_0;
+    }
+}
+
 }  // namespace ui
 }  // namespace android
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index ca43123..fab7f4c 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -104,36 +104,37 @@
 #endif
         } else {
             Slot* slot = &mSlots[mCurrentSlot];
+            // If mUsingSlotsProtocol is true, it means the raw pointer has axis info of
+            // ABS_MT_TRACKING_ID and ABS_MT_SLOT, so driver should send a valid trackingId while
+            // updating the slot.
+            if (!mUsingSlotsProtocol) {
+                slot->mInUse = true;
+            }
 
             switch (rawEvent->code) {
                 case ABS_MT_POSITION_X:
-                    slot->mInUse = true;
                     slot->mAbsMTPositionX = rawEvent->value;
+                    warnIfNotInUse(*rawEvent, *slot);
                     break;
                 case ABS_MT_POSITION_Y:
-                    slot->mInUse = true;
                     slot->mAbsMTPositionY = rawEvent->value;
+                    warnIfNotInUse(*rawEvent, *slot);
                     break;
                 case ABS_MT_TOUCH_MAJOR:
-                    slot->mInUse = true;
                     slot->mAbsMTTouchMajor = rawEvent->value;
                     break;
                 case ABS_MT_TOUCH_MINOR:
-                    slot->mInUse = true;
                     slot->mAbsMTTouchMinor = rawEvent->value;
                     slot->mHaveAbsMTTouchMinor = true;
                     break;
                 case ABS_MT_WIDTH_MAJOR:
-                    slot->mInUse = true;
                     slot->mAbsMTWidthMajor = rawEvent->value;
                     break;
                 case ABS_MT_WIDTH_MINOR:
-                    slot->mInUse = true;
                     slot->mAbsMTWidthMinor = rawEvent->value;
                     slot->mHaveAbsMTWidthMinor = true;
                     break;
                 case ABS_MT_ORIENTATION:
-                    slot->mInUse = true;
                     slot->mAbsMTOrientation = rawEvent->value;
                     break;
                 case ABS_MT_TRACKING_ID:
@@ -147,15 +148,12 @@
                     }
                     break;
                 case ABS_MT_PRESSURE:
-                    slot->mInUse = true;
                     slot->mAbsMTPressure = rawEvent->value;
                     break;
                 case ABS_MT_DISTANCE:
-                    slot->mInUse = true;
                     slot->mAbsMTDistance = rawEvent->value;
                     break;
                 case ABS_MT_TOOL_TYPE:
-                    slot->mInUse = true;
                     slot->mAbsMTToolType = rawEvent->value;
                     slot->mHaveAbsMTToolType = true;
                     break;
@@ -177,6 +175,13 @@
     return mHaveStylus;
 }
 
+void MultiTouchMotionAccumulator::warnIfNotInUse(const RawEvent& event, const Slot& slot) {
+    if (!slot.mInUse) {
+        ALOGW("Received unexpected event (0x%0x, 0x%0x) for slot %i with tracking id %i",
+              event.code, event.value, mCurrentSlot, slot.mAbsMTTrackingId);
+    }
+}
+
 // --- MultiTouchMotionAccumulator::Slot ---
 
 MultiTouchMotionAccumulator::Slot::Slot() {
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
index ea6f207..225ad49 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
@@ -87,6 +87,7 @@
     bool mHaveStylus;
 
     void clearSlots(int32_t initialSlot);
+    void warnIfNotInUse(const RawEvent& event, const Slot& slot);
 };
 
 class MultiTouchInputMapper : public TouchInputMapper {
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index fbb4db0..af02844 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -1471,6 +1471,13 @@
           next.rawPointerData.canceledIdBits.value);
 #endif
 
+    if (!next.rawPointerData.touchingIdBits.isEmpty() &&
+        !next.rawPointerData.hoveringIdBits.isEmpty() &&
+        last.rawPointerData.hoveringIdBits != next.rawPointerData.hoveringIdBits) {
+        ALOGI("Multi-touch contains some hovering ids 0x%08x",
+              next.rawPointerData.hoveringIdBits.value);
+    }
+
     processRawTouches(false /*timeout*/);
 }
 
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 02423c4..778f6e6 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -2277,6 +2277,7 @@
     const Point centerPoint = mDevice->getCenterPoint();
 
     // ACTION_DOWN
+    mDevice->sendTrackingId(FIRST_TRACKING_ID);
     mDevice->sendDown(centerPoint);
     ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
@@ -2297,6 +2298,8 @@
     const Point centerPoint = mDevice->getCenterPoint();
 
     // ACTION_DOWN
+    mDevice->sendSlot(FIRST_SLOT);
+    mDevice->sendTrackingId(FIRST_TRACKING_ID);
     mDevice->sendDown(centerPoint);
     ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
     ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
@@ -8218,6 +8221,70 @@
     ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
 }
 
+/**
+ * Test multi-touch should sent ACTION_POINTER_UP/ACTION_UP when received the INVALID_TRACKING_ID,
+ * to prevent the driver side may send unexpected data after set tracking id as INVALID_TRACKING_ID
+ * cause slot be valid again.
+ */
+TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
+    addConfigurationProperty("touch.deviceType", "touchScreen");
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION | ID | SLOT | PRESSURE);
+    MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+    NotifyMotionArgs motionArgs;
+
+    constexpr int32_t x1 = 100, y1 = 200, x2 = 0, y2 = 0;
+    // First finger down.
+    processId(mapper, FIRST_TRACKING_ID);
+    processPosition(mapper, x1, y1);
+    processPressure(mapper, RAW_PRESSURE_MAX);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+    ASSERT_EQ(uint32_t(1), motionArgs.pointerCount);
+
+    // First finger move.
+    processId(mapper, FIRST_TRACKING_ID);
+    processPosition(mapper, x1 + 1, y1 + 1);
+    processPressure(mapper, RAW_PRESSURE_MAX);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(uint32_t(1), motionArgs.pointerCount);
+
+    // Second finger down.
+    processSlot(mapper, SECOND_SLOT);
+    processId(mapper, SECOND_TRACKING_ID);
+    processPosition(mapper, x2, y2);
+    processPressure(mapper, RAW_PRESSURE_MAX);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+              motionArgs.action);
+    ASSERT_EQ(uint32_t(2), motionArgs.pointerCount);
+
+    // second finger up with some unexpected data.
+    processSlot(mapper, SECOND_SLOT);
+    processId(mapper, INVALID_TRACKING_ID);
+    processPosition(mapper, x2, y2);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+              motionArgs.action);
+    ASSERT_EQ(uint32_t(2), motionArgs.pointerCount);
+
+    // first finger up with some unexpected data.
+    processSlot(mapper, FIRST_SLOT);
+    processId(mapper, INVALID_TRACKING_ID);
+    processPosition(mapper, x2, y2);
+    processPressure(mapper, RAW_PRESSURE_MAX);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+    ASSERT_EQ(uint32_t(1), motionArgs.pointerCount);
+}
+
 // --- MultiTouchInputMapperTest_ExternalDevice ---
 
 class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 6a78b53..71db330 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -421,33 +421,35 @@
         mFrameTracker.setFrameReadyTime(desiredPresentTime);
     }
 
-    const Fps refreshRate = display->refreshRateConfigs().getCurrentRefreshRate().getFps();
-    const std::optional<Fps> renderRate = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
-    if (presentFence->isValid()) {
-        mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence,
-                                              refreshRate, renderRate,
-                                              frameRateToSetFrameRateVotePayload(
-                                                      mDrawingState.frameRate),
-                                              getGameMode());
-        mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
-                                           presentFence, FrameTracer::FrameEvent::PRESENT_FENCE);
-        mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
-    } else if (!display) {
-        // Do nothing.
-    } else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId());
-               displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
-        // The HWC doesn't support present fences, so use the refresh
-        // timestamp instead.
-        const nsecs_t actualPresentTime = display->getRefreshTimestamp();
-        mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime,
-                                             refreshRate, renderRate,
-                                             frameRateToSetFrameRateVotePayload(
-                                                     mDrawingState.frameRate),
-                                             getGameMode());
-        mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
-                                               actualPresentTime,
+    if (display) {
+        const Fps refreshRate = display->refreshRateConfigs().getCurrentRefreshRate().getFps();
+        const std::optional<Fps> renderRate =
+                mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
+        if (presentFence->isValid()) {
+            mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence,
+                                                  refreshRate, renderRate,
+                                                  frameRateToSetFrameRateVotePayload(
+                                                          mDrawingState.frameRate),
+                                                  getGameMode());
+            mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
+                                               presentFence,
                                                FrameTracer::FrameEvent::PRESENT_FENCE);
-        mFrameTracker.setActualPresentTime(actualPresentTime);
+            mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
+        } else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId());
+                   displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
+            // The HWC doesn't support present fences, so use the refresh
+            // timestamp instead.
+            const nsecs_t actualPresentTime = display->getRefreshTimestamp();
+            mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime,
+                                                 refreshRate, renderRate,
+                                                 frameRateToSetFrameRateVotePayload(
+                                                         mDrawingState.frameRate),
+                                                 getGameMode());
+            mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(),
+                                                   mCurrentFrameNumber, actualPresentTime,
+                                                   FrameTracer::FrameEvent::PRESENT_FENCE);
+            mFrameTracker.setActualPresentTime(actualPresentTime);
+        }
     }
 
     mFrameTracker.advanceFrame();
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 645e883..032ff9a 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -590,6 +590,7 @@
 }
 
 bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
+    mDrawingState.sequence++;
     mDrawingState.transparentRegionHint = transparent;
     mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
index 2bf931c..2e7a377 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
@@ -65,7 +65,9 @@
     size_t getLayerCount() const { return mLayers.size(); }
     const Layer& getFirstLayer() const { return mLayers[0]; }
     const Rect& getBounds() const { return mBounds; }
-    Rect getTextureBounds() const { return mOutputSpace.content; }
+    Rect getTextureBounds() const {
+        return mTexture ? mTexture->get()->getBuffer()->getBounds() : Rect::INVALID_RECT;
+    }
     const Region& getVisibleRegion() const { return mVisibleRegion; }
     size_t getAge() const { return mAge; }
     std::shared_ptr<renderengine::ExternalTexture> getBuffer() const {
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index 7f0e186..b05a594 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -355,7 +355,7 @@
     expectReadyBuffer(cachedSet);
 
     EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
-    EXPECT_EQ(mOutputState.framebufferSpace.content, cachedSet.getTextureBounds());
+    EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds());
 
     // Now check that appending a new cached set properly cleans up RenderEngine resources.
     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e3a324d..cb3f242 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -45,6 +45,7 @@
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/RenderSurface.h>
 #include <compositionengine/impl/OutputCompositionState.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <configstore/Utils.h>
 #include <cutils/compiler.h>
 #include <cutils/properties.h>
@@ -2300,21 +2301,24 @@
         HdrLayerInfoReporter::HdrLayerInfo info;
         int32_t maxArea = 0;
         mDrawingState.traverse([&, compositionDisplay = compositionDisplay](Layer* layer) {
-            if (layer->isVisible() &&
-                compositionDisplay->belongsInOutput(layer->getCompositionEngineLayerFE())) {
+            const auto layerFe = layer->getCompositionEngineLayerFE();
+            if (layer->isVisible() && compositionDisplay->belongsInOutput(layerFe)) {
                 const Dataspace transfer =
                         static_cast<Dataspace>(layer->getDataSpace() & Dataspace::TRANSFER_MASK);
                 const bool isHdr = (transfer == Dataspace::TRANSFER_ST2084 ||
                                     transfer == Dataspace::TRANSFER_HLG);
 
                 if (isHdr) {
-                    info.numberOfHdrLayers++;
-                    auto bufferRect = layer->getCompositionState()->geomBufferSize;
-                    int32_t area = bufferRect.width() * bufferRect.height();
-                    if (area > maxArea) {
-                        maxArea = area;
-                        info.maxW = bufferRect.width();
-                        info.maxH = bufferRect.height();
+                    const auto* outputLayer = compositionDisplay->getOutputLayerForLayer(layerFe);
+                    if (outputLayer) {
+                        info.numberOfHdrLayers++;
+                        const auto displayFrame = outputLayer->getState().displayFrame;
+                        const int32_t area = displayFrame.width() * displayFrame.height();
+                        if (area > maxArea) {
+                            maxArea = area;
+                            info.maxW = displayFrame.width();
+                            info.maxH = displayFrame.height();
+                        }
                     }
                 }
             }
@@ -6832,7 +6836,7 @@
 void SurfaceFlinger::TransactionState::traverseStatesWithBuffers(
         std::function<void(const layer_state_t&)> visitor) {
     for (const auto& state : states) {
-        if (state.state.hasBufferChanges() && (state.state.surface)) {
+        if (state.state.hasBufferChanges() && state.state.hasValidBuffer() && state.state.surface) {
             visitor(state.state);
         }
     }