Merge "Use the correct dataspace in shaders.cpp" into tm-dev
diff --git a/include/input/Input.h b/include/input/Input.h
index b23a951..e7d68fc 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -837,6 +837,8 @@
std::vector<PointerCoords> mSamplePointerCoords;
};
+std::ostream& operator<<(std::ostream& out, const MotionEvent& event);
+
/*
* Focus events.
*/
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index fe1754c..13ca9ec 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -22,7 +22,9 @@
#include <inttypes.h>
#include <string.h>
+#include <android-base/logging.h>
#include <android-base/stringprintf.h>
+#include <cutils/compiler.h>
#include <gui/constants.h>
#include <input/DisplayViewport.h>
#include <input/Input.h>
@@ -542,7 +544,14 @@
}
const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
- return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
+ if (CC_UNLIKELY(pointerIndex < 0 || pointerIndex >= getPointerCount())) {
+ LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for " << *this;
+ }
+ const size_t position = getHistorySize() * getPointerCount() + pointerIndex;
+ if (CC_UNLIKELY(position < 0 || position >= mSamplePointerCoords.size())) {
+ LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << *this;
+ }
+ return &mSamplePointerCoords[position];
}
float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
@@ -555,7 +564,18 @@
const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
size_t pointerIndex, size_t historicalIndex) const {
- return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
+ if (CC_UNLIKELY(pointerIndex < 0 || pointerIndex >= getPointerCount())) {
+ LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for " << *this;
+ }
+ if (CC_UNLIKELY(historicalIndex < 0 || historicalIndex > getHistorySize())) {
+ LOG(FATAL) << __func__ << ": Invalid historical index " << historicalIndex << " for "
+ << *this;
+ }
+ const size_t position = historicalIndex * getPointerCount() + pointerIndex;
+ if (CC_UNLIKELY(position < 0 || position >= mSamplePointerCoords.size())) {
+ LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << *this;
+ }
+ return &mSamplePointerCoords[position];
}
float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
@@ -903,6 +923,53 @@
return out;
}
+std::ostream& operator<<(std::ostream& out, const MotionEvent& event) {
+ out << "MotionEvent { action=" << MotionEvent::actionToString(event.getAction());
+ if (event.getActionButton() != 0) {
+ out << ", actionButton=" << std::to_string(event.getActionButton());
+ }
+ const size_t pointerCount = event.getPointerCount();
+ for (size_t i = 0; i < pointerCount; i++) {
+ out << ", id[" << i << "]=" << event.getPointerId(i);
+ float x = event.getX(i);
+ float y = event.getY(i);
+ if (x != 0 || y != 0) {
+ out << ", x[" << i << "]=" << x;
+ out << ", y[" << i << "]=" << y;
+ }
+ int toolType = event.getToolType(i);
+ if (toolType != AMOTION_EVENT_TOOL_TYPE_FINGER) {
+ out << ", toolType[" << i << "]=" << toolType;
+ }
+ }
+ if (event.getButtonState() != 0) {
+ out << ", buttonState=" << event.getButtonState();
+ }
+ if (event.getClassification() != MotionClassification::NONE) {
+ out << ", classification=" << motionClassificationToString(event.getClassification());
+ }
+ if (event.getMetaState() != 0) {
+ out << ", metaState=" << event.getMetaState();
+ }
+ if (event.getEdgeFlags() != 0) {
+ out << ", edgeFlags=" << event.getEdgeFlags();
+ }
+ if (pointerCount != 1) {
+ out << ", pointerCount=" << pointerCount;
+ }
+ if (event.getHistorySize() != 0) {
+ out << ", historySize=" << event.getHistorySize();
+ }
+ out << ", eventTime=" << event.getEventTime();
+ out << ", downTime=" << event.getDownTime();
+ out << ", deviceId=" << event.getDeviceId();
+ out << ", source=" << inputEventSourceToString(event.getSource());
+ out << ", displayId=" << event.getDisplayId();
+ out << ", eventId=" << event.getId();
+ out << "}";
+ return out;
+}
+
// --- FocusEvent ---
void FocusEvent::initialize(int32_t id, bool hasFocus) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 4d25c59..5e9427a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2507,7 +2507,7 @@
}
void InputDispatcher::addDragEventLocked(const MotionEntry& entry) {
- if (!mDragState) {
+ if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId) {
return;
}
@@ -4765,9 +4765,11 @@
// If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
// could just clear the state here.
- if (mDragState &&
+ if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
windowHandles.end()) {
+ ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
+ sendDropWindowCommandLocked(nullptr, 0, 0);
mDragState.reset();
}
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 91a666c..df43071 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -6407,6 +6407,58 @@
mSecondWindow->consumeMotionMove();
}
+TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
+ performDrag();
+
+ // Update window of second display.
+ sp<FakeWindowHandle> windowInSecondary =
+ new FakeWindowHandle(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
+ mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
+
+ // Let second display has a touch state.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(SECOND_DISPLAY_ID)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(100)
+ .y(100))
+ .build()));
+ windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
+ SECOND_DISPLAY_ID, 0 /* expectedFlag */);
+ // Update window again.
+ mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
+
+ // Move on window.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {50, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
+ mWindow->consumeDragEvent(false, 50, 50);
+ mSecondWindow->assertNoEvents();
+
+ // Move to another window.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {150, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
+ mWindow->consumeDragEvent(true, 150, 50);
+ mSecondWindow->consumeDragEvent(false, 50, 50);
+
+ // drop to another window.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {150, 50}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+ mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
+ mWindow->assertNoEvents();
+ mSecondWindow->assertNoEvents();
+}
+
class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index f8c53c3..d9c89cd 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -358,8 +358,6 @@
// composition.
if (!mBufferInfo.mFrameLatencyNeeded) return;
- mAlreadyDisplayedThisCompose = false;
-
// Update mFrameEventHistory.
finalizeFrameEventHistory(glDoneFence, compositorTiming);
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 1a5b925..fecf5ae 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -79,10 +79,10 @@
// For example we can only use it if all the displays are client comp, and we need
// to merge all the client comp fences. We could do this, but for now we just
// disable the optimization when a layer is composed on multiple displays.
- if (mAlreadyDisplayedThisCompose) {
+ if (mClearClientCompositionFenceOnLayerDisplayed) {
mLastClientCompositionFence = nullptr;
} else {
- mAlreadyDisplayedThisCompose = true;
+ mClearClientCompositionFenceOnLayerDisplayed = true;
}
// The previous release fence notifies the client that SurfaceFlinger is done with the previous
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
index 2e7a377..e65aa73 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
@@ -147,6 +147,8 @@
bool hasProtectedLayers() const;
+ bool hasSolidColorLayers() const;
+
private:
CachedSet() = default;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
index 29d3366..5aec7c2 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
@@ -248,6 +248,12 @@
bool isProtected() const {
return getOutputLayer()->getLayerFE().getCompositionState()->hasProtectedContent;
}
+
+ bool hasSolidColorCompositionType() const {
+ return getOutputLayer()->getLayerFE().getCompositionState()->compositionType ==
+ aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR;
+ }
+
float getFps() const { return getOutputLayer()->getLayerFE().getCompositionState()->fps; }
void dump(std::string& result) const;
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index aac478d..c3385a8 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1300,6 +1300,7 @@
const auto& layerState = layer->getState();
const auto* layerFEState = layer->getLayerFE().getCompositionState();
auto& layerFE = layer->getLayerFE();
+ layerFE.setWasClientComposed(nullptr);
const Region clip(viewportRegion.intersect(layerState.visibleRegion));
ALOGV("Layer: %s", layerFE.getDebugName());
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 742af58..1bb9d0eb 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -377,6 +377,7 @@
auto requestedCompositionType = outputIndependentState->compositionType;
if (requestedCompositionType == Composition::SOLID_COLOR && state.overrideInfo.buffer) {
+ // this should never happen, as SOLID_COLOR is skipped from caching, b/230073351
requestedCompositionType = Composition::DEVICE;
}
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
index d15b0a7..641b806 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -388,6 +388,12 @@
[](const Layer& layer) { return layer.getState()->isProtected(); });
}
+bool CachedSet::hasSolidColorLayers() const {
+ return std::any_of(mLayers.cbegin(), mLayers.cend(), [](const Layer& layer) {
+ return layer.getState()->hasSolidColorCompositionType();
+ });
+}
+
void CachedSet::dump(std::string& result) const {
const auto now = std::chrono::steady_clock::now();
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index 250f648..1062b70 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -498,6 +498,13 @@
}
}
+ for (const CachedSet& layer : mLayers) {
+ if (layer.hasSolidColorLayers()) {
+ ATRACE_NAME("layer->hasSolidColorLayers()");
+ return;
+ }
+ }
+
std::vector<Run> runs = findCandidateRuns(now);
std::optional<Run> bestRun = findBestRun(runs);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3988e51..24abad9 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -620,6 +620,7 @@
void setWasClientComposed(const sp<Fence>& fence) override {
mLastClientCompositionFence = fence;
+ mClearClientCompositionFenceOnLayerDisplayed = false;
}
const char* getDebugName() const override;
@@ -1035,7 +1036,7 @@
mutable bool mDrawingStateModified = false;
sp<Fence> mLastClientCompositionFence;
- bool mAlreadyDisplayedThisCompose = false;
+ bool mClearClientCompositionFenceOnLayerDisplayed = false;
private:
virtual void setTransformHint(ui::Transform::RotationFlags) {}
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index cbea77e..639ba5a 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -177,6 +177,11 @@
}
binder::Status EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
+ std::scoped_lock lock(mLock);
+ if (mChannel.initCheck() != NO_ERROR) {
+ return binder::Status::fromStatusT(NAME_NOT_FOUND);
+ }
+
outChannel->setReceiveFd(mChannel.moveReceiveFd());
outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd())));
return binder::Status::ok();
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index c406478..adb96fd 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -112,7 +112,8 @@
private:
virtual void onFirstRef();
EventThread* const mEventThread;
- gui::BitTube mChannel;
+ std::mutex mLock;
+ gui::BitTube mChannel GUARDED_BY(mLock);
std::vector<DisplayEventReceiver::Event> mPendingEvents;
};