Merge "Surface: Add a death notification to SurfaceListener" into main
diff --git a/include/input/InputEventBuilders.h b/include/input/InputEventBuilders.h
index 55e0583..5bd5070 100644
--- a/include/input/InputEventBuilders.h
+++ b/include/input/InputEventBuilders.h
@@ -19,6 +19,8 @@
 #include <android/input.h>
 #include <attestation/HmacKeyManager.h>
 #include <input/Input.h>
+#include <input/InputTransport.h>
+#include <ui/LogicalDisplayId.h>
 #include <utils/Timers.h> // for nsecs_t, systemTime
 
 #include <vector>
@@ -44,6 +46,11 @@
 
     PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
 
+    PointerBuilder& isResampled(bool isResampled) {
+        mCoords.isResampled = isResampled;
+        return *this;
+    }
+
     PointerBuilder& axis(int32_t axis, float value) {
         mCoords.setAxisValue(axis, value);
         return *this;
@@ -58,6 +65,87 @@
     PointerCoords mCoords;
 };
 
+class InputMessageBuilder {
+public:
+    InputMessageBuilder(InputMessage::Type type, uint32_t seq) : mType{type}, mSeq{seq} {}
+
+    InputMessageBuilder& eventId(int32_t eventId) {
+        mEventId = eventId;
+        return *this;
+    }
+
+    InputMessageBuilder& eventTime(nsecs_t eventTime) {
+        mEventTime = eventTime;
+        return *this;
+    }
+
+    InputMessageBuilder& deviceId(DeviceId deviceId) {
+        mDeviceId = deviceId;
+        return *this;
+    }
+
+    InputMessageBuilder& source(int32_t source) {
+        mSource = source;
+        return *this;
+    }
+
+    InputMessageBuilder& displayId(ui::LogicalDisplayId displayId) {
+        mDisplayId = displayId;
+        return *this;
+    }
+
+    InputMessageBuilder& action(int32_t action) {
+        mAction = action;
+        return *this;
+    }
+
+    InputMessageBuilder& downTime(nsecs_t downTime) {
+        mDownTime = downTime;
+        return *this;
+    }
+
+    InputMessageBuilder& pointer(PointerBuilder pointerBuilder) {
+        mPointers.push_back(pointerBuilder);
+        return *this;
+    }
+
+    InputMessage build() const {
+        InputMessage message{};
+        // Header
+        message.header.type = mType;
+        message.header.seq = mSeq;
+        // Body
+        message.body.motion.eventId = mEventId;
+        message.body.motion.pointerCount = mPointers.size();
+        message.body.motion.eventTime = mEventTime;
+        message.body.motion.deviceId = mDeviceId;
+        message.body.motion.source = mSource;
+        message.body.motion.displayId = mDisplayId.val();
+        message.body.motion.action = mAction;
+        message.body.motion.downTime = mDownTime;
+
+        for (size_t i = 0; i < mPointers.size(); ++i) {
+            message.body.motion.pointers[i].properties = mPointers[i].buildProperties();
+            message.body.motion.pointers[i].coords = mPointers[i].buildCoords();
+        }
+        return message;
+    }
+
+private:
+    const InputMessage::Type mType;
+    const uint32_t mSeq;
+
+    int32_t mEventId{InputEvent::nextId()};
+    nsecs_t mEventTime{systemTime(SYSTEM_TIME_MONOTONIC)};
+    DeviceId mDeviceId{DEFAULT_DEVICE_ID};
+    int32_t mSource{AINPUT_SOURCE_TOUCHSCREEN};
+    ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::DEFAULT};
+    int32_t mAction{AMOTION_EVENT_ACTION_MOVE};
+    nsecs_t mDownTime{mEventTime};
+
+    std::vector<PointerBuilder> mPointers;
+};
+
 class MotionEventBuilder {
 public:
     MotionEventBuilder(int32_t action, int32_t source) {
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 2929bce..72d255e 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -771,7 +771,7 @@
  * This provides a per-process-unique total ordering of binders where a null
  * AIBinder* object is considered to be before all other binder objects.
  * For instance, two binders refer to the same object in a local or remote
- * process when both AIBinder_lt(a, b) and AIBinder(b, a) are false. This API
+ * process when both AIBinder_lt(a, b) and AIBinder_lt(b, a) are false. This API
  * might be used to insert and lookup binders in binary search trees.
  *
  * AIBinder* pointers themselves actually also create a per-process-unique total
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index f065ffa..1fb59fd 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -356,8 +356,9 @@
     if (context == nullptr) {
         return;
     }
-    sp<BLASTBufferQueue> bq = static_cast<BLASTBufferQueue*>(context);
+    auto bq = static_cast<BLASTBufferQueue*>(context);
     bq->transactionCallback(latchTime, presentFence, stats);
+    bq->decStrong((void*)transactionCallbackThunk);
 }
 
 void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
@@ -413,8 +414,6 @@
             BQA_LOGE("No matching SurfaceControls found: mSurfaceControlsWithPendingCallback was "
                      "empty.");
         }
-
-        decStrong((void*)transactionCallbackThunk);
     }
 }
 
diff --git a/libs/input/tests/Resampler_test.cpp b/libs/input/tests/Resampler_test.cpp
index b372c0b..7ae9a28 100644
--- a/libs/input/tests/Resampler_test.cpp
+++ b/libs/input/tests/Resampler_test.cpp
@@ -70,22 +70,18 @@
 };
 
 InputSample::operator InputMessage() const {
-    InputMessage message;
-    message.header.type = InputMessage::Type::MOTION;
-    message.body.motion.pointerCount = pointers.size();
-    message.body.motion.eventTime = static_cast<std::chrono::nanoseconds>(eventTime).count();
-    message.body.motion.source = AINPUT_SOURCE_CLASS_POINTER;
-    message.body.motion.downTime = 0;
+    InputMessageBuilder messageBuilder =
+            InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
+                    .eventTime(std::chrono::nanoseconds{eventTime}.count())
+                    .source(AINPUT_SOURCE_TOUCHSCREEN)
+                    .downTime(0);
 
-    const uint32_t pointerCount = message.body.motion.pointerCount;
-    for (uint32_t i = 0; i < pointerCount; ++i) {
-        message.body.motion.pointers[i].properties.id = pointers[i].id;
-        message.body.motion.pointers[i].properties.toolType = pointers[i].toolType;
-        message.body.motion.pointers[i].coords.setAxisValue(AMOTION_EVENT_AXIS_X, pointers[i].x);
-        message.body.motion.pointers[i].coords.setAxisValue(AMOTION_EVENT_AXIS_Y, pointers[i].y);
-        message.body.motion.pointers[i].coords.isResampled = pointers[i].isResampled;
+    for (const Pointer& pointer : pointers) {
+        messageBuilder.pointer(
+                PointerBuilder{pointer.id, pointer.toolType}.x(pointer.x).y(pointer.y).isResampled(
+                        pointer.isResampled));
     }
-    return message;
+    return messageBuilder.build();
 }
 
 struct InputStream {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 566bb8e..be00079 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -127,7 +127,7 @@
     mVsyncModulator->cancelRefreshRateChange();
 
     mVsyncConfiguration->reset();
-    updatePhaseConfiguration(pacesetterSelectorPtr()->getActiveMode().fps);
+    updatePhaseConfiguration(pacesetterId, pacesetterSelectorPtr()->getActiveMode().fps);
 }
 
 void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr,
@@ -487,7 +487,12 @@
     }
 }
 
-void Scheduler::updatePhaseConfiguration(Fps refreshRate) {
+void Scheduler::updatePhaseConfiguration(PhysicalDisplayId displayId, Fps refreshRate) {
+    const bool isPacesetter =
+            FTL_FAKE_GUARD(kMainThreadContext,
+                           (std::scoped_lock(mDisplayLock), displayId == mPacesetterDisplayId));
+    if (!isPacesetter) return;
+
     mRefreshRateStats->setRefreshRate(refreshRate);
     mVsyncConfiguration->setRefreshRateFps(refreshRate);
     setVsyncConfig(mVsyncModulator->setVsyncConfigSet(mVsyncConfiguration->getCurrentConfigs()),
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 88f0e94..1367ec3 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -187,7 +187,7 @@
         }
     }
 
-    void updatePhaseConfiguration(Fps);
+    void updatePhaseConfiguration(PhysicalDisplayId, Fps);
 
     const VsyncConfiguration& getVsyncConfiguration() const { return *mVsyncConfiguration; }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0aad282..0c297d9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1280,20 +1280,14 @@
         return BAD_VALUE;
     }
 
+    // TODO: b/277364366 - Require a display token from clients and remove fallback to pacesetter.
     std::optional<PhysicalDisplayId> displayIdOpt;
-    {
+    if (displayToken) {
         Mutex::Autolock lock(mStateLock);
-        if (displayToken) {
-            displayIdOpt = getPhysicalDisplayIdLocked(displayToken);
-            if (!displayIdOpt) {
-                ALOGW("%s: Invalid physical display token %p", __func__, displayToken.get());
-                return NAME_NOT_FOUND;
-            }
-        } else {
-            // TODO (b/277364366): Clients should be updated to pass in the display they
-            // want, rather than us picking an arbitrary one (the active display, in this
-            // case).
-            displayIdOpt = mActiveDisplayId;
+        displayIdOpt = getPhysicalDisplayIdLocked(displayToken);
+        if (!displayIdOpt) {
+            ALOGW("%s: Invalid physical display token %p", __func__, displayToken.get());
+            return NAME_NOT_FOUND;
         }
     }
 
@@ -1340,19 +1334,13 @@
             // VsyncController model is locked.
             mScheduler->modulateVsync(displayId, &VsyncModulator::onRefreshRateChangeInitiated);
 
-            if (displayId == mActiveDisplayId) {
-                mScheduler->updatePhaseConfiguration(mode.fps);
-            }
-
+            mScheduler->updatePhaseConfiguration(displayId, mode.fps);
             mScheduler->setModeChangePending(true);
             break;
         }
         case DesiredModeAction::InitiateRenderRateSwitch:
             mScheduler->setRenderRate(displayId, mode.fps, /*applyImmediately*/ false);
-
-            if (displayId == mActiveDisplayId) {
-                mScheduler->updatePhaseConfiguration(mode.fps);
-            }
+            mScheduler->updatePhaseConfiguration(displayId, mode.fps);
 
             if (emitEvent) {
                 mScheduler->onDisplayModeChanged(displayId, mode);
@@ -1447,9 +1435,7 @@
     mDisplayModeController.finalizeModeChange(displayId, activeMode.modePtr->getId(),
                                               activeMode.modePtr->getVsyncRate(), activeMode.fps);
 
-    if (displayId == mActiveDisplayId) {
-        mScheduler->updatePhaseConfiguration(activeMode.fps);
-    }
+    mScheduler->updatePhaseConfiguration(displayId, activeMode.fps);
 
     if (pendingModeOpt->emitEvent) {
         mScheduler->onDisplayModeChanged(displayId, activeMode);
@@ -1473,11 +1459,9 @@
 
     constexpr bool kAllowToEnable = true;
     mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, std::move(activeModePtr).take());
-    mScheduler->setRenderRate(displayId, renderFps, /*applyImmediately*/ true);
 
-    if (displayId == mActiveDisplayId) {
-        mScheduler->updatePhaseConfiguration(renderFps);
-    }
+    mScheduler->setRenderRate(displayId, renderFps, /*applyImmediately*/ true);
+    mScheduler->updatePhaseConfiguration(displayId, renderFps);
 }
 
 void SurfaceFlinger::initiateDisplayModeChanges() {
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index c97f401..3d8124b 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -32,6 +32,8 @@
 using aidl::android::hardware::vibrator::Effect;
 using aidl::android::hardware::vibrator::EffectStrength;
 using aidl::android::hardware::vibrator::PrimitivePwle;
+using aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
+using aidl::android::hardware::vibrator::PwleV2Primitive;
 using aidl::android::hardware::vibrator::VendorEffect;
 
 using std::chrono::milliseconds;
@@ -114,6 +116,12 @@
     return HalResult<void>::unsupported();
 }
 
+HalResult<void> HalWrapper::composePwleV2(const std::vector<PwleV2Primitive>&,
+                                          const std::function<void()>&) {
+    ALOGV("Skipped composePwleV2 because it's not available in Vibrator HAL");
+    return HalResult<void>::unsupported();
+}
+
 HalResult<Capabilities> HalWrapper::getCapabilities() {
     std::lock_guard<std::mutex> lock(mInfoMutex);
     if (mInfoCache.mCapabilities.isFailed()) {
@@ -313,6 +321,13 @@
     return HalResultFactory::fromStatus(getHal()->composePwle(primitives, cb));
 }
 
+HalResult<void> AidlHalWrapper::composePwleV2(const std::vector<PwleV2Primitive>& composite,
+                                              const std::function<void()>& completionCallback) {
+    // This method should always support callbacks, so no need to double check.
+    auto cb = ndk::SharedRefBase::make<HalCallbackWrapper>(completionCallback);
+    return HalResultFactory::fromStatus(getHal()->composePwleV2(composite, cb));
+}
+
 HalResult<Capabilities> AidlHalWrapper::getCapabilitiesInternal() {
     int32_t cap = 0;
     auto status = getHal()->getCapabilities(&cap);
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index 20979bd..ae0d9ab 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -354,6 +354,8 @@
     using CompositeEffect = aidl::android::hardware::vibrator::CompositeEffect;
     using Braking = aidl::android::hardware::vibrator::Braking;
     using PrimitivePwle = aidl::android::hardware::vibrator::PrimitivePwle;
+    using PwleV2Primitive = aidl::android::hardware::vibrator::PwleV2Primitive;
+    using PwleV2OutputMapEntry = aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
 
     explicit HalWrapper(std::shared_ptr<CallbackScheduler> scheduler)
           : mCallbackScheduler(std::move(scheduler)) {}
@@ -391,6 +393,9 @@
     virtual HalResult<void> performPwleEffect(const std::vector<PrimitivePwle>& primitives,
                                               const std::function<void()>& completionCallback);
 
+    virtual HalResult<void> composePwleV2(const std::vector<PwleV2Primitive>& composite,
+                                          const std::function<void()>& completionCallback);
+
 protected:
     // Shared pointer to allow CallbackScheduler to outlive this wrapper.
     const std::shared_ptr<CallbackScheduler> mCallbackScheduler;
@@ -471,6 +476,9 @@
             const std::vector<PrimitivePwle>& primitives,
             const std::function<void()>& completionCallback) override final;
 
+    HalResult<void> composePwleV2(const std::vector<PwleV2Primitive>& composite,
+                                  const std::function<void()>& completionCallback) override final;
+
 protected:
     HalResult<Capabilities> getCapabilitiesInternal() override final;
     HalResult<std::vector<Effect>> getSupportedEffectsInternal() override final;
diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
index 7bcc59a..ba7e1f0 100644
--- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
@@ -39,6 +39,7 @@
 using aidl::android::hardware::vibrator::IVibrator;
 using aidl::android::hardware::vibrator::IVibratorCallback;
 using aidl::android::hardware::vibrator::PrimitivePwle;
+using aidl::android::hardware::vibrator::PwleV2Primitive;
 using aidl::android::hardware::vibrator::VendorEffect;
 using aidl::android::os::PersistableBundle;
 
@@ -681,3 +682,38 @@
     ASSERT_TRUE(result.isOk());
     ASSERT_EQ(1, *callbackCounter.get());
 }
+
+TEST_F(VibratorHalWrapperAidlTest, TestComposePwleV2) {
+    auto pwleEffect = {
+            PwleV2Primitive(/*amplitude=*/0.2, /*frequency=*/50, /*time=*/100),
+            PwleV2Primitive(/*amplitude=*/0.5, /*frequency=*/150, /*time=*/100),
+            PwleV2Primitive(/*amplitude=*/0.8, /*frequency=*/250, /*time=*/100),
+    };
+
+    {
+        InSequence seq;
+        EXPECT_CALL(*mMockHal.get(), composePwleV2(_, _))
+                .Times(Exactly(3))
+                .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION)))
+                .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
+                .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()),
+                                Return(ndk::ScopedAStatus::ok())));
+    }
+
+    std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
+    auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
+
+    auto result = mWrapper->composePwleV2(pwleEffect, callback);
+    ASSERT_TRUE(result.isUnsupported());
+    // Callback not triggered on failure
+    ASSERT_EQ(0, *callbackCounter.get());
+
+    result = mWrapper->composePwleV2(pwleEffect, callback);
+    ASSERT_TRUE(result.isFailed());
+    // Callback not triggered for unsupported
+    ASSERT_EQ(0, *callbackCounter.get());
+
+    result = mWrapper->composePwleV2(pwleEffect, callback);
+    ASSERT_TRUE(result.isOk());
+    ASSERT_EQ(1, *callbackCounter.get());
+}
diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
index 9a7c69d..83430d7 100644
--- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
@@ -40,6 +40,7 @@
 using aidl::android::hardware::vibrator::EffectStrength;
 using aidl::android::hardware::vibrator::IVibrator;
 using aidl::android::hardware::vibrator::PrimitivePwle;
+using aidl::android::hardware::vibrator::PwleV2Primitive;
 using aidl::android::hardware::vibrator::VendorEffect;
 using aidl::android::os::PersistableBundle;
 
@@ -369,3 +370,19 @@
     // No callback is triggered.
     ASSERT_EQ(0, *callbackCounter.get());
 }
+
+TEST_F(VibratorHalWrapperHidlV1_0Test, TestComposePwleV2Unsupported) {
+    auto pwleEffect = {
+            PwleV2Primitive(/*amplitude=*/0.2, /*frequency=*/50, /*time=*/100),
+            PwleV2Primitive(/*amplitude=*/0.5, /*frequency=*/150, /*time=*/100),
+            PwleV2Primitive(/*amplitude=*/0.8, /*frequency=*/250, /*time=*/100),
+    };
+
+    std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
+    auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
+
+    ASSERT_TRUE(mWrapper->composePwleV2(pwleEffect, callback).isUnsupported());
+
+    // No callback is triggered.
+    ASSERT_EQ(0, *callbackCounter.get());
+}
diff --git a/services/vibratorservice/test/test_mocks.h b/services/vibratorservice/test/test_mocks.h
index 2f9451e..5e09084 100644
--- a/services/vibratorservice/test/test_mocks.h
+++ b/services/vibratorservice/test/test_mocks.h
@@ -41,6 +41,8 @@
 using aidl::android::hardware::vibrator::IVibrator;
 using aidl::android::hardware::vibrator::IVibratorCallback;
 using aidl::android::hardware::vibrator::PrimitivePwle;
+using aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
+using aidl::android::hardware::vibrator::PwleV2Primitive;
 using aidl::android::hardware::vibrator::VendorEffect;
 
 // -------------------------------------------------------------------------------------------------
@@ -89,6 +91,17 @@
     MOCK_METHOD(ndk::ScopedAStatus, getPwlePrimitiveDurationMax, (int32_t * ret), (override));
     MOCK_METHOD(ndk::ScopedAStatus, getPwleCompositionSizeMax, (int32_t * ret), (override));
     MOCK_METHOD(ndk::ScopedAStatus, getSupportedBraking, (std::vector<Braking> * ret), (override));
+    MOCK_METHOD(ndk::ScopedAStatus, getPwleV2FrequencyToOutputAccelerationMap,
+                (std::vector<PwleV2OutputMapEntry> * ret), (override));
+    MOCK_METHOD(ndk::ScopedAStatus, getPwleV2PrimitiveDurationMaxMillis, (int32_t* ret),
+                (override));
+    MOCK_METHOD(ndk::ScopedAStatus, getPwleV2PrimitiveDurationMinMillis, (int32_t* ret),
+                (override));
+    MOCK_METHOD(ndk::ScopedAStatus, getPwleV2CompositionSizeMax, (int32_t* ret), (override));
+    MOCK_METHOD(ndk::ScopedAStatus, composePwleV2,
+                (const std::vector<PwleV2Primitive>& e,
+                 const std::shared_ptr<IVibratorCallback>& cb),
+                (override));
     MOCK_METHOD(ndk::ScopedAStatus, getInterfaceVersion, (int32_t*), (override));
     MOCK_METHOD(ndk::ScopedAStatus, getInterfaceHash, (std::string*), (override));
     MOCK_METHOD(ndk::SpAIBinder, asBinder, (), (override));