Merge "InputMapper refactor: Rename configure to reconfigure" into udc-dev
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index aa0ef25..1c4e63e 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -38,6 +38,7 @@
],
init_rc: ["atrace.rc"],
+ required: ["ftrace_synthetic_events.conf"],
product_variables: {
debuggable: {
@@ -45,3 +46,8 @@
},
},
}
+
+prebuilt_etc {
+ name: "ftrace_synthetic_events.conf",
+ src: "ftrace_synthetic_events.conf",
+}
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index e66cc41..92b1677 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -291,12 +291,10 @@
# Setup synthetic events
chmod 0666 /sys/kernel/tracing/synthetic_events
chmod 0666 /sys/kernel/debug/tracing/synthetic_events
+ copy /system/etc/ftrace_synthetic_events.conf /sys/kernel/tracing/synthetic_events
+ copy /system/etc/ftrace_synthetic_events.conf /sys/kernel/debug/tracing/synthetic_events
- # rss_stat_throttled
- write /sys/kernel/tracing/synthetic_events "rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size"
- write /sys/kernel/debug/tracing/synthetic_events "rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size"
-
- # allow creating event triggers
+ # allow creating rss_stat event triggers
chmod 0666 /sys/kernel/tracing/events/kmem/rss_stat/trigger
chmod 0666 /sys/kernel/debug/tracing/events/kmem/rss_stat/trigger
@@ -304,6 +302,14 @@
chmod 0666 /sys/kernel/tracing/events/synthetic/rss_stat_throttled/enable
chmod 0666 /sys/kernel/debug/tracing/events/synthetic/rss_stat_throttled/enable
+ # allow creating suspend_resume triggers
+ chmod 0666 /sys/kernel/tracing/events/power/suspend_resume/trigger
+ chmod 0666 /sys/kernel/debug/tracing/events/power/suspend_resume/trigger
+
+ # allow enabling suspend_resume_minimal
+ chmod 0666 /sys/kernel/tracing/events/synthetic/suspend_resume_minimal/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/synthetic/suspend_resume_minimal/enable
+
on late-init && property:ro.boot.fastboot.boottrace=enabled
setprop debug.atrace.tags.enableflags 802922
setprop persist.traced.enable 0
diff --git a/cmds/atrace/ftrace_synthetic_events.conf b/cmds/atrace/ftrace_synthetic_events.conf
new file mode 100644
index 0000000..e2257fe
--- /dev/null
+++ b/cmds/atrace/ftrace_synthetic_events.conf
@@ -0,0 +1,2 @@
+rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size
+suspend_resume_minimal bool start
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 40683ed..043a7f1 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2236,8 +2236,7 @@
const uint64_t start = Nanotime();
const int ret = dump_backtrace_to_file_timeout(
- pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
- is_java_process ? 5 : 20, fd);
+ pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace, 3, fd);
if (ret == -1) {
// For consistency, the header and footer to this message match those
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 0d06e9e..851b407 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -295,7 +295,8 @@
bool RpcServer::shutdown() {
RpcMutexUniqueLock _l(mLock);
if (mShutdownTrigger == nullptr) {
- LOG_RPC_DETAIL("Cannot shutdown. No shutdown trigger installed (already shutdown?)");
+ LOG_RPC_DETAIL("Cannot shutdown. No shutdown trigger installed (already shutdown, or not "
+ "joined yet?)");
return false;
}
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrutils.h b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrutils.h
index dd06fa2..09f4165 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrutils.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/jpegrutils.h
@@ -105,14 +105,16 @@
* xmlns:Item="http://ns.google.com/photos/1.0/container/item/">
* <Container:Directory>
* <rdf:Seq>
- * <rdf:li>
+ * <rdf:li
+ * rdf:parseType="Resource">
* <Container:Item
* Item:Semantic="Primary"
* Item:Mime="image/jpeg"/>
* </rdf:li>
- * <rdf:li>
+ * <rdf:li
+ * rdf:parseType="Resource">
* <Container:Item
- * Item:Semantic="RecoveryMap"
+ * Item:Semantic="GainMap"
* Item:Mime="image/jpeg"
* Item:Length="1000"/>
* </rdf:li>
@@ -142,14 +144,14 @@
* <rdf:Description
* xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/"
* hdrgm:Version="1"
- * hdrgm:GainMapMin="0.5"
- * hdrgm:GainMapMax="8.5"
+ * hdrgm:GainMapMin="-1"
+ * hdrgm:GainMapMax="3"
* hdrgm:Gamma="1"
* hdrgm:OffsetSDR="0"
* hdrgm:OffsetHDR="0"
- * hdrgm:HDRCapacityMin="0.5"
- * hdrgm:HDRCapacityMax="8.5"
- * hdrgm:BaseRendition="SDR"/>
+ * hdrgm:HDRCapacityMin="0"
+ * hdrgm:HDRCapacityMax="3"
+ * hdrgm:BaseRenditionIsHDR="False"/>
* </rdf:RDF>
* </x:xmpmeta>
*
diff --git a/libs/jpegrecoverymap/jpegrutils.cpp b/libs/jpegrecoverymap/jpegrutils.cpp
index ff96447..cde0ceb 100644
--- a/libs/jpegrecoverymap/jpegrutils.cpp
+++ b/libs/jpegrecoverymap/jpegrutils.cpp
@@ -15,14 +15,17 @@
*/
#include <jpegrecoverymap/jpegrutils.h>
-#include <utils/Log.h>
+
+#include <algorithm>
+#include <cmath>
+
#include <image_io/xml/xml_reader.h>
#include <image_io/xml/xml_writer.h>
#include <image_io/base/message_handler.h>
#include <image_io/xml/xml_element_rules.h>
#include <image_io/xml/xml_handler.h>
#include <image_io/xml/xml_rule.h>
-#include <cmath>
+#include <utils/Log.h>
using namespace photos_editing_formats::image_io;
using namespace std;
@@ -230,26 +233,26 @@
const string kItemSemantic = Name(kItemPrefix, "Semantic");
// Item XMP constants - element and attribute values
-const string kSemanticPrimary = "Primary";
-const string kSemanticRecoveryMap = "RecoveryMap";
-const string kMimeImageJpeg = "image/jpeg";
+const string kSemanticPrimary = "Primary";
+const string kSemanticGainMap = "GainMap";
+const string kMimeImageJpeg = "image/jpeg";
-// RecoveryMap XMP constants - URI and namespace prefix
-const string kRecoveryMapUri = "http://ns.adobe.com/hdr-gain-map/1.0/";
-const string kRecoveryMapPrefix = "hdrgm";
+// GainMap XMP constants - URI and namespace prefix
+const string kGainMapUri = "http://ns.adobe.com/hdr-gain-map/1.0/";
+const string kGainMapPrefix = "hdrgm";
-// RecoveryMap XMP constants - element and attribute names
-const string kMapVersion = Name(kRecoveryMapPrefix, "Version");
-const string kMapGainMapMin = Name(kRecoveryMapPrefix, "GainMapMin");
-const string kMapGainMapMax = Name(kRecoveryMapPrefix, "GainMapMax");
-const string kMapGamma = Name(kRecoveryMapPrefix, "Gamma");
-const string kMapOffsetSdr = Name(kRecoveryMapPrefix, "OffsetSDR");
-const string kMapOffsetHdr = Name(kRecoveryMapPrefix, "OffsetHDR");
-const string kMapHDRCapacityMin = Name(kRecoveryMapPrefix, "HDRCapacityMin");
-const string kMapHDRCapacityMax = Name(kRecoveryMapPrefix, "HDRCapacityMax");
-const string kMapBaseRendition = Name(kRecoveryMapPrefix, "BaseRendition");
+// GainMap XMP constants - element and attribute names
+const string kMapVersion = Name(kGainMapPrefix, "Version");
+const string kMapGainMapMin = Name(kGainMapPrefix, "GainMapMin");
+const string kMapGainMapMax = Name(kGainMapPrefix, "GainMapMax");
+const string kMapGamma = Name(kGainMapPrefix, "Gamma");
+const string kMapOffsetSdr = Name(kGainMapPrefix, "OffsetSDR");
+const string kMapOffsetHdr = Name(kGainMapPrefix, "OffsetHDR");
+const string kMapHDRCapacityMin = Name(kGainMapPrefix, "HDRCapacityMin");
+const string kMapHDRCapacityMax = Name(kGainMapPrefix, "HDRCapacityMax");
+const string kMapBaseRenditionIsHDR = Name(kGainMapPrefix, "BaseRenditionIsHDR");
-// RecoveryMap XMP constants - names for XMP handlers
+// GainMap XMP constants - names for XMP handlers
const string XMPXmlHandler::minContentBoostAttrName = kMapGainMapMin;
const string XMPXmlHandler::maxContentBoostAttrName = kMapGainMapMax;
@@ -313,15 +316,23 @@
writer.StartWritingElement("rdf:Description");
writer.WriteXmlns(kContainerPrefix, kContainerUri);
writer.WriteXmlns(kItemPrefix, kItemUri);
+
writer.StartWritingElements(kConDirSeq);
- size_t item_depth = writer.StartWritingElements(kLiItem);
+
+ size_t item_depth = writer.StartWritingElement("rdf:li");
+ writer.WriteAttributeNameAndValue("rdf:parseType", "Resource");
+ writer.StartWritingElement(kConItem);
writer.WriteAttributeNameAndValue(kItemSemantic, kSemanticPrimary);
writer.WriteAttributeNameAndValue(kItemMime, kMimeImageJpeg);
writer.FinishWritingElementsToDepth(item_depth);
- writer.StartWritingElements(kLiItem);
- writer.WriteAttributeNameAndValue(kItemSemantic, kSemanticRecoveryMap);
+
+ writer.StartWritingElement("rdf:li");
+ writer.WriteAttributeNameAndValue("rdf:parseType", "Resource");
+ writer.StartWritingElement(kConItem);
+ writer.WriteAttributeNameAndValue(kItemSemantic, kSemanticGainMap);
writer.WriteAttributeNameAndValue(kItemMime, kMimeImageJpeg);
writer.WriteAttributeNameAndValue(kItemLength, secondary_image_length);
+
writer.FinishWriting();
return ss.str();
@@ -329,7 +340,6 @@
string generateXmpForSecondaryImage(jpegr_metadata_struct& metadata) {
const vector<string> kConDirSeq({kConDirectory, string("rdf:Seq")});
- const vector<string> kLiItem({string("rdf:li"), kConItem});
std::stringstream ss;
photos_editing_formats::image_io::XmlWriter writer(ss);
@@ -339,16 +349,17 @@
writer.StartWritingElement("rdf:RDF");
writer.WriteXmlns("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
writer.StartWritingElement("rdf:Description");
- writer.WriteXmlns(kRecoveryMapPrefix, kRecoveryMapUri);
+ writer.WriteXmlns(kGainMapPrefix, kGainMapUri);
writer.WriteAttributeNameAndValue(kMapVersion, metadata.version);
writer.WriteAttributeNameAndValue(kMapGainMapMin, log2(metadata.minContentBoost));
writer.WriteAttributeNameAndValue(kMapGainMapMax, log2(metadata.maxContentBoost));
writer.WriteAttributeNameAndValue(kMapGamma, "1");
writer.WriteAttributeNameAndValue(kMapOffsetSdr, "0");
writer.WriteAttributeNameAndValue(kMapOffsetHdr, "0");
- writer.WriteAttributeNameAndValue(kMapHDRCapacityMin, "0");
- writer.WriteAttributeNameAndValue(kMapHDRCapacityMax, "2.3");
- writer.WriteAttributeNameAndValue(kMapBaseRendition, "SDR");
+ writer.WriteAttributeNameAndValue(
+ kMapHDRCapacityMin, std::max(log2(metadata.minContentBoost), 0.0f));
+ writer.WriteAttributeNameAndValue(kMapHDRCapacityMax, log2(metadata.maxContentBoost));
+ writer.WriteAttributeNameAndValue(kMapBaseRenditionIsHDR, "False");
writer.FinishWriting();
return ss.str();
diff --git a/libs/jpegrecoverymap/tests/jpegr_test.cpp b/libs/jpegrecoverymap/tests/jpegr_test.cpp
index df90f53..7c669ab 100644
--- a/libs/jpegrecoverymap/tests/jpegr_test.cpp
+++ b/libs/jpegrecoverymap/tests/jpegr_test.cpp
@@ -192,8 +192,8 @@
jpegr_metadata_struct metadata_read;
EXPECT_TRUE(getMetadataFromXMP(xmpData.data(), xmpData.size(), &metadata_read));
- ASSERT_EQ(metadata_expected.maxContentBoost, metadata_read.maxContentBoost);
- ASSERT_EQ(metadata_expected.minContentBoost, metadata_read.minContentBoost);
+ EXPECT_FLOAT_EQ(metadata_expected.maxContentBoost, metadata_read.maxContentBoost);
+ EXPECT_FLOAT_EQ(metadata_expected.minContentBoost, metadata_read.minContentBoost);
}
/* Test Encode API-0 and decode */
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index e393fb2..8256dd8 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -264,14 +264,11 @@
SkAndroidFrameworkTraceUtil::setEnableTracing(tracingEnabled);
}
-SkiaRenderEngine::SkiaRenderEngine(
- RenderEngineType type,
- PixelFormat pixelFormat,
- bool useColorManagement,
- bool supportsBackgroundBlur) :
- RenderEngine(type),
- mDefaultPixelFormat(pixelFormat),
- mUseColorManagement(useColorManagement) {
+SkiaRenderEngine::SkiaRenderEngine(RenderEngineType type, PixelFormat pixelFormat,
+ bool useColorManagement, bool supportsBackgroundBlur)
+ : RenderEngine(type),
+ mDefaultPixelFormat(pixelFormat),
+ mUseColorManagement(useColorManagement) {
if (supportsBackgroundBlur) {
ALOGD("Background Blurs Enabled");
mBlurFilter = new KawaseBlurFilter();
@@ -507,15 +504,9 @@
}
if (parameters.requiresLinearEffect) {
- const ui::Dataspace inputDataspace = mUseColorManagement ? parameters.layer.sourceDataspace
- : ui::Dataspace::V0_SRGB_LINEAR;
- const ui::Dataspace outputDataspace = mUseColorManagement
- ? parameters.display.outputDataspace
- : ui::Dataspace::V0_SRGB_LINEAR;
-
auto effect =
- shaders::LinearEffect{.inputDataspace = inputDataspace,
- .outputDataspace = outputDataspace,
+ shaders::LinearEffect{.inputDataspace = parameters.layer.sourceDataspace,
+ .outputDataspace = parameters.outputDataSpace,
.undoPremultipliedAlpha = parameters.undoPremultipliedAlpha};
auto effectIter = mRuntimeEffects.find(effect);
@@ -678,9 +669,8 @@
// wait on the buffer to be ready to use prior to using it
waitFence(grContext, bufferFence);
- const ui::Dataspace dstDataspace =
- mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR;
- sk_sp<SkSurface> dstSurface = surfaceTextureRef->getOrCreateSurface(dstDataspace, grContext);
+ sk_sp<SkSurface> dstSurface =
+ surfaceTextureRef->getOrCreateSurface(display.outputDataspace, grContext);
SkCanvas* dstCanvas = mCapture->tryCapture(dstSurface.get());
if (dstCanvas == nullptr) {
@@ -888,10 +878,31 @@
const bool dimInLinearSpace = display.dimmingStage !=
aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF;
+ const bool isExtendedHdr = (layer.sourceDataspace & ui::Dataspace::RANGE_MASK) ==
+ static_cast<int32_t>(ui::Dataspace::RANGE_EXTENDED) &&
+ (display.outputDataspace & ui::Dataspace::TRANSFER_MASK) ==
+ static_cast<int32_t>(ui::Dataspace::TRANSFER_SRGB);
+
+ const ui::Dataspace runtimeEffectDataspace = !dimInLinearSpace && isExtendedHdr
+ ? static_cast<ui::Dataspace>(
+ (display.outputDataspace & ui::Dataspace::STANDARD_MASK) |
+ ui::Dataspace::TRANSFER_GAMMA2_2 |
+ (display.outputDataspace & ui::Dataspace::RANGE_MASK))
+ : display.outputDataspace;
+
+ // If the input dataspace is range extended, the output dataspace transfer is sRGB
+ // and dimmingStage is GAMMA_OETF, dim in linear space instead, and
+ // set the output dataspace's transfer to be GAMMA2_2.
+ // This allows DPU side to use oetf_gamma_2p2 for extended HDR layer
+ // to avoid tone shift.
+ // The reason of tone shift here is because HDR layers manage white point
+ // luminance in linear space, which color pipelines request GAMMA_OETF break
+ // without a gamma 2.2 fixup.
const bool requiresLinearEffect = layer.colorTransform != mat4() ||
(mUseColorManagement &&
needsToneMapping(layer.sourceDataspace, display.outputDataspace)) ||
- (dimInLinearSpace && !equalsWithinMargin(1.f, layerDimmingRatio));
+ (dimInLinearSpace && !equalsWithinMargin(1.f, layerDimmingRatio)) ||
+ (!dimInLinearSpace && isExtendedHdr);
// quick abort from drawing the remaining portion of the layer
if (layer.skipContentDraw ||
@@ -904,7 +915,7 @@
// image with the same colorspace as the destination surface so that Skia's color
// management is a no-op.
const ui::Dataspace layerDataspace = (!mUseColorManagement || requiresLinearEffect)
- ? dstDataspace
+ ? display.outputDataspace
: layer.sourceDataspace;
SkPaint paint;
@@ -985,7 +996,8 @@
.requiresLinearEffect = requiresLinearEffect,
.layerDimmingRatio = dimInLinearSpace
? layerDimmingRatio
- : 1.f}));
+ : 1.f,
+ .outputDataSpace = runtimeEffectDataspace}));
// Turn on dithering when dimming beyond this (arbitrary) threshold...
static constexpr float kDimmingThreshold = 0.2f;
@@ -1048,7 +1060,8 @@
.display = display,
.undoPremultipliedAlpha = false,
.requiresLinearEffect = requiresLinearEffect,
- .layerDimmingRatio = layerDimmingRatio}));
+ .layerDimmingRatio = layerDimmingRatio,
+ .outputDataSpace = runtimeEffectDataspace}));
}
if (layer.disableBlending) {
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index e4406b4..6457bfa 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -156,6 +156,7 @@
bool undoPremultipliedAlpha;
bool requiresLinearEffect;
float layerDimmingRatio;
+ const ui::Dataspace outputDataSpace;
};
sk_sp<SkShader> createRuntimeEffectShader(const RuntimeEffectShaderParameters&);
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 66d3849..eb99438 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -873,14 +873,26 @@
: ui::Transform();
// Step 4: Scale the raw coordinates to the display space.
- // - Here, we assume that the raw surface of the touch device maps perfectly to the surface
- // of the display panel. This is usually true for touchscreens.
+ // - In DIRECT mode, we assume that the raw surface of the touch device maps perfectly to
+ // the surface of the display panel. This is usually true for touchscreens.
+ // - In POINTER mode, we cannot assume that the display and the touch device have the same
+ // aspect ratio, since it is likely to be untrue for devices like external drawing tablets.
+ // In this case, we used a fixed scale so that 1) we use the same scale across both the x and
+ // y axes to ensure the mapping does not stretch gestures, and 2) the entire region of the
+ // display can be reached by the touch device.
// - From this point onward, we are no longer in the discrete space of the raw coordinates but
// are in the continuous space of the logical display.
ui::Transform scaleRawToDisplay;
const float xScale = static_cast<float>(mViewport.deviceWidth) / rotatedRawSize.width;
const float yScale = static_cast<float>(mViewport.deviceHeight) / rotatedRawSize.height;
- scaleRawToDisplay.set(xScale, 0, 0, yScale);
+ if (mDeviceMode == DeviceMode::DIRECT) {
+ scaleRawToDisplay.set(xScale, 0, 0, yScale);
+ } else if (mDeviceMode == DeviceMode::POINTER) {
+ const float fixedScale = std::max(xScale, yScale);
+ scaleRawToDisplay.set(fixedScale, 0, 0, fixedScale);
+ } else {
+ LOG_ALWAYS_FATAL("computeInputTransform can only be used for DIRECT and POINTER modes");
+ }
// Step 5: Undo the display rotation to bring us back to the un-rotated display coordinate space
// that InputReader uses.
@@ -3479,14 +3491,19 @@
if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
- mPointerController
- ->setPosition(mCurrentCookedState.cookedPointerData.pointerCoords[index].getX(),
- mCurrentCookedState.cookedPointerData.pointerCoords[index].getY());
-
hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
down = !hovering;
- const auto [x, y] = mPointerController->getPosition();
+ float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
+ float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
+ // Styluses are configured specifically for one display. We only update the
+ // PointerController for this stylus if the PointerController is configured for
+ // the same display as this stylus,
+ if (getAssociatedDisplayId() == mViewport.displayId) {
+ mPointerController->setPosition(x, y);
+ std::tie(x, y) = mPointerController->getPosition();
+ }
+
mPointerSimple.currentCoords.copyFrom(
mCurrentCookedState.cookedPointerData.pointerCoords[index]);
mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
@@ -3499,7 +3516,7 @@
hovering = false;
}
- return dispatchPointerSimple(when, readTime, policyFlags, down, hovering);
+ return dispatchPointerSimple(when, readTime, policyFlags, down, hovering, mViewport.displayId);
}
std::list<NotifyArgs> TouchInputMapper::abortPointerStylus(nsecs_t when, nsecs_t readTime,
@@ -3542,7 +3559,8 @@
hovering = false;
}
- return dispatchPointerSimple(when, readTime, policyFlags, down, hovering);
+ const int32_t displayId = mPointerController->getDisplayId();
+ return dispatchPointerSimple(when, readTime, policyFlags, down, hovering, displayId);
}
std::list<NotifyArgs> TouchInputMapper::abortPointerMouse(nsecs_t when, nsecs_t readTime,
@@ -3556,7 +3574,7 @@
std::list<NotifyArgs> TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsecs_t readTime,
uint32_t policyFlags, bool down,
- bool hovering) {
+ bool hovering, int32_t displayId) {
LOG_ALWAYS_FATAL_IF(mDeviceMode != DeviceMode::POINTER,
"%s cannot be used when the device is not in POINTER mode.", __func__);
std::list<NotifyArgs> out;
@@ -3569,7 +3587,6 @@
} else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
}
- int32_t displayId = mPointerController->getDisplayId();
const auto [xCursorPosition, yCursorPosition] = mPointerController->getPosition();
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index dd6a9c3..d98ae60 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -789,7 +789,7 @@
[[nodiscard]] std::list<NotifyArgs> dispatchPointerSimple(nsecs_t when, nsecs_t readTime,
uint32_t policyFlags, bool down,
- bool hovering);
+ bool hovering, int32_t displayId);
[[nodiscard]] std::list<NotifyArgs> abortPointerSimple(nsecs_t when, nsecs_t readTime,
uint32_t policyFlags);
@@ -821,6 +821,7 @@
static void assignPointerIds(const RawState& last, RawState& current);
+ // Compute input transforms for DIRECT and POINTER modes.
void computeInputTransforms();
void configureDeviceType();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8dec57b..9e66d8a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2127,7 +2127,9 @@
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
if (traceFlags & LayerTracing::TRACE_COMPOSITION) {
- writeCompositionStateToProto(layerProto);
+ ui::LayerStack layerStack =
+ (mSnapshot) ? mSnapshot->outputFilter.layerStack : ui::INVALID_LAYER_STACK;
+ writeCompositionStateToProto(layerProto, layerStack);
}
for (const sp<Layer>& layer : mDrawingChildren) {
@@ -2137,14 +2139,15 @@
return layerProto;
}
-void Layer::writeCompositionStateToProto(LayerProto* layerProto) {
+void Layer::writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack) {
ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread.
+ ftl::FakeGuard mainThreadGuard(kMainThreadContext);
// Only populate for the primary display.
- if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) {
+ if (const auto display = mFlinger->getDisplayFromLayerStack(layerStack)) {
const auto compositionType = getCompositionType(*display);
layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
- LayerProtoHelper::writeToProto(getVisibleRegion(display.get()),
+ LayerProtoHelper::writeToProto(getVisibleRegion(display),
[&]() { return layerProto->mutable_visible_region(); });
}
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 0bfab7c..f11128f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -611,7 +611,7 @@
bool isRemovedFromCurrentState() const;
LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags);
- void writeCompositionStateToProto(LayerProto* layerProto);
+ void writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack);
// Write states that are modified by the main thread. This includes drawing
// state as well as buffer data. This should be called in the main or tracing
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index b5ae1a7..5d92485 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -332,7 +332,7 @@
if (mTraceFlags & LayerTracing::TRACE_COMPOSITION) {
auto it = mLegacyLayers.find(layer.id);
if (it != mLegacyLayers.end()) {
- it->second->writeCompositionStateToProto(layerProto);
+ it->second->writeCompositionStateToProto(layerProto, snapshot->outputFilter.layerStack);
}
}
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 57661f1..74665a7 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -525,7 +525,7 @@
bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
const sp<EventThreadConnection>& connection) const {
- const auto throttleVsync = [&] {
+ const auto throttleVsync = [&]() REQUIRES(mMutex) {
const auto& vsyncData = event.vsync.vsyncData;
if (connection->frameRate.isValid()) {
return !mVsyncSchedule->getTracker()
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 87e20a0..30869e9 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -205,7 +205,7 @@
TracedOrdinal<int> mVsyncTracer;
TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mMutex);
std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex);
- std::shared_ptr<scheduler::VsyncSchedule> mVsyncSchedule;
+ std::shared_ptr<scheduler::VsyncSchedule> mVsyncSchedule GUARDED_BY(mMutex);
TimePoint mLastVsyncCallbackTime GUARDED_BY(mMutex) = TimePoint::now();
scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex);
frametimeline::TokenManager* const mTokenManager;
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 7457b84..18c0a69 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -78,20 +78,42 @@
void MessageQueue::initVsync(std::shared_ptr<scheduler::VSyncDispatch> dispatch,
frametimeline::TokenManager& tokenManager,
std::chrono::nanoseconds workDuration) {
- std::lock_guard lock(mVsync.mutex);
- mVsync.workDuration = workDuration;
- mVsync.tokenManager = &tokenManager;
- onNewVsyncScheduleLocked(std::move(dispatch));
+ std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
+ {
+ std::lock_guard lock(mVsync.mutex);
+ mVsync.workDuration = workDuration;
+ mVsync.tokenManager = &tokenManager;
+ oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
+ }
+
+ // See comments in onNewVsyncSchedule. Today, oldRegistration should be
+ // empty, but nothing prevents us from calling initVsync multiple times, so
+ // go ahead and destruct it outside the lock for safety.
+ oldRegistration.reset();
}
void MessageQueue::onNewVsyncSchedule(std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
- std::lock_guard lock(mVsync.mutex);
- onNewVsyncScheduleLocked(std::move(dispatch));
+ std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
+ {
+ std::lock_guard lock(mVsync.mutex);
+ oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
+ }
+
+ // The old registration needs to be deleted after releasing mVsync.mutex to
+ // avoid deadlock. This is because the callback may be running on the timer
+ // thread. In that case, timerCallback sets
+ // VSyncDispatchTimerQueueEntry::mRunning to true, then attempts to lock
+ // mVsync.mutex. But if it's already locked, the VSyncCallbackRegistration's
+ // destructor has to wait until VSyncDispatchTimerQueueEntry::mRunning is
+ // set back to false, but it won't be until mVsync.mutex is released.
+ oldRegistration.reset();
}
-void MessageQueue::onNewVsyncScheduleLocked(std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
+std::unique_ptr<scheduler::VSyncCallbackRegistration> MessageQueue::onNewVsyncScheduleLocked(
+ std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
const bool reschedule = mVsync.registration &&
mVsync.registration->cancel() == scheduler::CancelResult::Cancelled;
+ auto oldRegistration = std::move(mVsync.registration);
mVsync.registration = std::make_unique<
scheduler::VSyncCallbackRegistration>(std::move(dispatch),
std::bind(&MessageQueue::vsyncCallback, this,
@@ -105,6 +127,7 @@
.readyDuration = 0,
.earliestVsync = mVsync.lastCallbackTime.ns()});
}
+ return oldRegistration;
}
void MessageQueue::destroyVsync() {
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
index 9c9b2f3..a523147 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.h
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -117,9 +117,9 @@
struct Vsync {
frametimeline::TokenManager* tokenManager = nullptr;
- std::unique_ptr<scheduler::VSyncCallbackRegistration> registration;
mutable std::mutex mutex;
+ std::unique_ptr<scheduler::VSyncCallbackRegistration> registration GUARDED_BY(mutex);
TracedOrdinal<std::chrono::nanoseconds> workDuration
GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)};
TimePoint lastCallbackTime GUARDED_BY(mutex);
@@ -129,7 +129,10 @@
Vsync mVsync;
- void onNewVsyncScheduleLocked(std::shared_ptr<scheduler::VSyncDispatch>) REQUIRES(mVsync.mutex);
+ // Returns the old registration so it can be destructed outside the lock to
+ // avoid deadlock.
+ std::unique_ptr<scheduler::VSyncCallbackRegistration> onNewVsyncScheduleLocked(
+ std::shared_ptr<scheduler::VSyncDispatch>) REQUIRES(mVsync.mutex);
public:
explicit MessageQueue(ICompositor&);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b543467..2f024ce 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -8968,6 +8968,15 @@
static_cast<void>(mScheduler->scheduleDelayed([&]() { scheduleRepaint(); }, ms2ns(delayInMs)));
}
+const DisplayDevice* SurfaceFlinger::getDisplayFromLayerStack(ui::LayerStack layerStack) {
+ for (const auto& [_, display] : mDisplays) {
+ if (display->getLayerStack() == layerStack) {
+ return display.get();
+ }
+ }
+ return nullptr;
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6fa918c..5783c8d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -328,6 +328,8 @@
bool mIgnoreHwcPhysicalDisplayOrientation = false;
void forceFutureUpdate(int delayInMs);
+ const DisplayDevice* getDisplayFromLayerStack(ui::LayerStack)
+ REQUIRES(mStateLock, kMainThreadContext);
protected:
// We're reference counted, never destroy SurfaceFlinger directly