Merge "Revert "Revert "Remove incorrect isDataSpaceValid""" 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 1403b77..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
@@ -2816,6 +2815,7 @@
options->do_screenshot = false;
break;
case Dumpstate::BugreportMode::BUGREPORT_WEAR:
+ options->do_vibrate = false;
options->do_progress_updates = true;
options->do_screenshot = is_screenshot_requested;
break;
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index aa5219b..93d8cdf 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -286,8 +286,8 @@
// Other options retain default values
- EXPECT_TRUE(options_.do_vibrate);
EXPECT_FALSE(options_.progress_updates_to_socket);
+ EXPECT_FALSE(options_.do_vibrate);
EXPECT_FALSE(options_.show_header_only);
EXPECT_FALSE(options_.is_remote_mode);
EXPECT_FALSE(options_.stream_to_socket);
diff --git a/include/input/KeyLayoutMap.h b/include/input/KeyLayoutMap.h
index e203d19..8c3c74a 100644
--- a/include/input/KeyLayoutMap.h
+++ b/include/input/KeyLayoutMap.h
@@ -72,6 +72,7 @@
int32_t* outKeyCode, uint32_t* outFlags) const;
std::vector<int32_t> findScanCodesForKey(int32_t keyCode) const;
std::optional<int32_t> findScanCodeForLed(int32_t ledCode) const;
+ std::vector<int32_t> findUsageCodesForKey(int32_t keyCode) const;
std::optional<int32_t> findUsageCodeForLed(int32_t ledCode) const;
std::optional<AxisInfo> mapAxis(int32_t scanCode) const;
diff --git a/include/input/TfLiteMotionPredictor.h b/include/input/TfLiteMotionPredictor.h
index 7de551b41..a340bd0 100644
--- a/include/input/TfLiteMotionPredictor.h
+++ b/include/input/TfLiteMotionPredictor.h
@@ -106,6 +106,9 @@
// Returns the length of the model's input buffers.
size_t inputLength() const;
+ // Returns the length of the model's output buffers.
+ size_t outputLength() const;
+
// Executes the model.
// Returns true if the model successfully executed and the output tensors can be read.
bool invoke();
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/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 61a047b..873e955 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -238,6 +238,13 @@
"binderRpcUniversalTests.cpp",
],
+ // This test uses a lot of resources and takes a long time. Due to
+ // design of several tests, it is also very sensitive to resource
+ // contention on the device. b/276820894
+ test_options: {
+ unit_test: false,
+ },
+
test_suites: ["general-tests"],
require_root: true,
diff --git a/libs/binder/trusty/RpcServerTrusty.cpp b/libs/binder/trusty/RpcServerTrusty.cpp
index 109da75..3a99606 100644
--- a/libs/binder/trusty/RpcServerTrusty.cpp
+++ b/libs/binder/trusty/RpcServerTrusty.cpp
@@ -154,8 +154,18 @@
return NO_ERROR;
}
-void RpcServerTrusty::handleDisconnect(const tipc_port* /*port*/, handle_t /*chan*/,
- void* /*ctx*/) {}
+void RpcServerTrusty::handleDisconnect(const tipc_port* /*port*/, handle_t /*chan*/, void* ctx) {
+ auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
+ if (channelContext == nullptr) {
+ // Connections marked "incoming" (outgoing from the server's side)
+ // do not have a valid channel context because joinFn does not get
+ // called for them. We ignore them here.
+ return;
+ }
+
+ auto& session = channelContext->session;
+ (void)session->shutdownAndWait(false);
+}
void RpcServerTrusty::handleChannelCleanup(void* ctx) {
auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index a2649f6..a194513 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -247,6 +247,16 @@
return scanCodes;
}
+std::vector<int32_t> KeyLayoutMap::findUsageCodesForKey(int32_t keyCode) const {
+ std::vector<int32_t> usageCodes;
+ for (const auto& [usageCode, key] : mKeysByUsageCode) {
+ if (keyCode == key.keyCode) {
+ usageCodes.push_back(usageCode);
+ }
+ }
+ return usageCodes;
+}
+
std::optional<AxisInfo> KeyLayoutMap::mapAxis(int32_t scanCode) const {
auto it = mAxes.find(scanCode);
if (it == mAxes.end()) {
diff --git a/libs/input/TfLiteMotionPredictor.cpp b/libs/input/TfLiteMotionPredictor.cpp
index 3b061d1..85fa176 100644
--- a/libs/input/TfLiteMotionPredictor.cpp
+++ b/libs/input/TfLiteMotionPredictor.cpp
@@ -346,6 +346,10 @@
return getTensorBuffer<const float>(mInputR).size();
}
+size_t TfLiteMotionPredictorModel::outputLength() const {
+ return getTensorBuffer<const float>(mOutputR).size();
+}
+
std::span<float> TfLiteMotionPredictorModel::inputR() {
return getTensorBuffer<float>(mInputR);
}
diff --git a/libs/input/tests/TfLiteMotionPredictor_test.cpp b/libs/input/tests/TfLiteMotionPredictor_test.cpp
index 6e76ac1..b5ed9e4 100644
--- a/libs/input/tests/TfLiteMotionPredictor_test.cpp
+++ b/libs/input/tests/TfLiteMotionPredictor_test.cpp
@@ -139,8 +139,10 @@
ASSERT_TRUE(model->invoke());
- ASSERT_EQ(model->outputR().size(), model->outputPhi().size());
- ASSERT_EQ(model->outputR().size(), model->outputPressure().size());
+ const int outputLength = model->outputLength();
+ ASSERT_EQ(outputLength, model->outputR().size());
+ ASSERT_EQ(outputLength, model->outputPhi().size());
+ ASSERT_EQ(outputLength, model->outputPressure().size());
}
TEST(TfLiteMotionPredictorTest, ModelOutput) {
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/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp
index 210dca5..9eb42cd 100644
--- a/libs/renderengine/ExternalTexture.cpp
+++ b/libs/renderengine/ExternalTexture.cpp
@@ -14,17 +14,17 @@
* limitations under the License.
*/
+#include <log/log.h>
#include <renderengine/RenderEngine.h>
#include <renderengine/impl/ExternalTexture.h>
#include <ui/GraphicBuffer.h>
-
-#include "log/log_main.h"
+#include <utils/Trace.h>
namespace android::renderengine::impl {
ExternalTexture::ExternalTexture(const sp<GraphicBuffer>& buffer,
renderengine::RenderEngine& renderEngine, uint32_t usage)
- : mBuffer(buffer), mRenderEngine(renderEngine) {
+ : mBuffer(buffer), mRenderEngine(renderEngine), mWritable(usage & WRITEABLE) {
LOG_ALWAYS_FATAL_IF(buffer == nullptr,
"Attempted to bind a null buffer to an external texture!");
// GLESRenderEngine has a separate texture cache for output buffers,
@@ -35,11 +35,20 @@
renderengine::RenderEngine::RenderEngineType::THREADED)) {
return;
}
- mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & WRITEABLE);
+ mRenderEngine.mapExternalTextureBuffer(mBuffer, mWritable);
}
ExternalTexture::~ExternalTexture() {
mRenderEngine.unmapExternalTextureBuffer(std::move(mBuffer));
}
+void ExternalTexture::remapBuffer() {
+ ATRACE_CALL();
+ {
+ auto buf = mBuffer;
+ mRenderEngine.unmapExternalTextureBuffer(std::move(buf));
+ }
+ mRenderEngine.mapExternalTextureBuffer(mBuffer, mWritable);
+}
+
} // namespace android::renderengine::impl
diff --git a/libs/renderengine/include/renderengine/ExternalTexture.h b/libs/renderengine/include/renderengine/ExternalTexture.h
index 621a209..82e5d83 100644
--- a/libs/renderengine/include/renderengine/ExternalTexture.h
+++ b/libs/renderengine/include/renderengine/ExternalTexture.h
@@ -46,6 +46,8 @@
// Retrieves the buffer that is bound to this texture.
virtual const sp<GraphicBuffer>& getBuffer() const = 0;
+ virtual void remapBuffer() = 0;
+
Rect getBounds() const {
return {0, 0, static_cast<int32_t>(getWidth()), static_cast<int32_t>(getHeight())};
}
diff --git a/libs/renderengine/include/renderengine/impl/ExternalTexture.h b/libs/renderengine/include/renderengine/impl/ExternalTexture.h
index c0e24f0..d30262d 100644
--- a/libs/renderengine/include/renderengine/impl/ExternalTexture.h
+++ b/libs/renderengine/include/renderengine/impl/ExternalTexture.h
@@ -51,10 +51,12 @@
bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
return getBuffer() == other.getBuffer();
}
+ void remapBuffer() override;
private:
sp<GraphicBuffer> mBuffer;
android::renderengine::RenderEngine& mRenderEngine;
+ const bool mWritable;
};
} // namespace android::renderengine::impl
diff --git a/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
index b95f011..474e2e7 100644
--- a/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
+++ b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
@@ -45,6 +45,7 @@
uint64_t getId() const override { return mId; }
PixelFormat getPixelFormat() const override { return mPixelFormat; }
uint64_t getUsage() const override { return mUsage; }
+ void remapBuffer() override {}
~FakeExternalTexture() = default;
};
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/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 34b1251..415e8ea 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -21,6 +21,7 @@
#include <android-base/properties.h>
#include <android/dlext.h>
+#include <cutils/properties.h>
#include <dirent.h>
#include <dlfcn.h>
#include <graphicsenv/GraphicsEnv.h>
@@ -236,29 +237,22 @@
LOG_ALWAYS_FATAL("couldn't find an OpenGL ES implementation from %s",
android::GraphicsEnv::getInstance().getDriverPath().c_str());
}
- // Finally, try to load system driver. If ANGLE is the system driver
- // (i.e. we are forcing the legacy system driver instead of ANGLE), use
- // the driver suffix that was passed down from above.
- if (shouldForceLegacyDriver) {
- std::string suffix = android::GraphicsEnv::getInstance().getLegacySuffix();
- hnd = attempt_to_load_system_driver(cnx, suffix.c_str(), true);
- } else {
- // Start by searching for the library name appended by the system
- // properties of the GLES userspace driver in both locations.
- // i.e.:
- // libGLES_${prop}.so, or:
- // libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
- for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- auto prop = base::GetProperty(key, "");
- if (prop.empty()) {
- continue;
- }
- hnd = attempt_to_load_system_driver(cnx, prop.c_str(), true);
- if (hnd) {
- break;
- } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
- failToLoadFromDriverSuffixProperty = true;
- }
+ // Finally, try to load system driver.
+ // Start by searching for the library name appended by the system
+ // properties of the GLES userspace driver in both locations.
+ // i.e.:
+ // libGLES_${prop}.so, or:
+ // libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ auto prop = base::GetProperty(key, "");
+ if (prop.empty()) {
+ continue;
+ }
+ hnd = attempt_to_load_system_driver(cnx, prop.c_str(), true);
+ if (hnd) {
+ break;
+ } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
+ failToLoadFromDriverSuffixProperty = true;
}
}
}
@@ -272,7 +266,10 @@
hnd = attempt_to_load_system_driver(cnx, nullptr, true);
}
- if (!hnd && !failToLoadFromDriverSuffixProperty) {
+ if (!hnd && !failToLoadFromDriverSuffixProperty &&
+ property_get_int32("ro.vendor.api_level", 0) < __ANDROID_API_U__) {
+ // Still can't find the graphics drivers with the exact name. This time try to use wildcard
+ // matching if the device is launched before Android 14.
hnd = attempt_to_load_system_driver(cnx, nullptr, false);
}
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index ee8dde1..0eb4ad2 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -634,6 +634,11 @@
}
}
+ std::vector<int32_t> usageCodes = keyMap.keyLayoutMap->findUsageCodesForKey(keycode);
+ if (usageCodes.size() > 0 && mscBitmask.test(MSC_SCAN)) {
+ return true;
+ }
+
return false;
}
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index ddf6c87..eaed987 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -385,7 +385,7 @@
}
for_each_mapper([this, when, &config, changes, &out](InputMapper& mapper) {
- out += mapper.configure(when, config, changes);
+ out += mapper.reconfigure(when, config, changes);
mSources |= mapper.getSources();
});
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index a3fdcdf..d7dc2ae 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -133,10 +133,10 @@
dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
}
-std::list<NotifyArgs> CursorInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) {
- std::list<NotifyArgs> out = InputMapper::configure(when, config, changes);
+std::list<NotifyArgs> CursorInputMapper::reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) {
+ std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
if (!changes) { // first time only
mCursorScrollAccumulator.configure(getDeviceContext());
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index 5f02203..987b9de 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -59,9 +59,9 @@
virtual uint32_t getSources() const override;
virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
virtual void dump(std::string& dump) override;
- [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) override;
+ [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
index 99e6cf9..c5a3075 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
@@ -46,9 +46,9 @@
dumpStylusState(dump, mStylusState);
}
-std::list<NotifyArgs> ExternalStylusInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) {
+std::list<NotifyArgs> ExternalStylusInputMapper::reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) {
getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
mTouchButtonAccumulator.configure();
return {};
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
index 11b5315..0df8cf7 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
@@ -32,9 +32,9 @@
uint32_t getSources() const override;
void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
void dump(std::string& dump) override;
- [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) override;
+ [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp
index 9cf3696..9d1e9ce 100644
--- a/services/inputflinger/reader/mapper/InputMapper.cpp
+++ b/services/inputflinger/reader/mapper/InputMapper.cpp
@@ -35,8 +35,8 @@
void InputMapper::dump(std::string& dump) {}
-std::list<NotifyArgs> InputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
- uint32_t changes) {
+std::list<NotifyArgs> InputMapper::reconfigure(nsecs_t when, const InputReaderConfiguration* config,
+ uint32_t changes) {
return {};
}
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index 2722edd..bb15e4d 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -53,9 +53,9 @@
virtual uint32_t getSources() const = 0;
virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo);
virtual void dump(std::string& dump);
- [[nodiscard]] virtual std::list<NotifyArgs> configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes);
+ [[nodiscard]] virtual std::list<NotifyArgs> reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes);
[[nodiscard]] virtual std::list<NotifyArgs> reset(nsecs_t when);
[[nodiscard]] virtual std::list<NotifyArgs> process(const RawEvent* rawEvent) = 0;
[[nodiscard]] virtual std::list<NotifyArgs> timeoutExpired(nsecs_t when);
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
index f65cdcb..f60035b 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -103,10 +103,10 @@
}
}
-std::list<NotifyArgs> JoystickInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) {
- std::list<NotifyArgs> out = InputMapper::configure(when, config, changes);
+std::list<NotifyArgs> JoystickInputMapper::reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) {
+ std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
if (!changes) { // first time only
// Collect all axes.
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h
index 9ca4176..9adb07f 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.h
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.h
@@ -28,9 +28,9 @@
virtual uint32_t getSources() const override;
virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
virtual void dump(std::string& dump) override;
- [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) override;
+ [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 269c106..fc00c48 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -131,10 +131,10 @@
return std::nullopt;
}
-std::list<NotifyArgs> KeyboardInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) {
- std::list<NotifyArgs> out = InputMapper::configure(when, config, changes);
+std::list<NotifyArgs> KeyboardInputMapper::reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) {
+ std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
if (!changes) { // first time only
// Configure basic parameters.
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
index 2fc82c3..52576c3 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -29,9 +29,9 @@
uint32_t getSources() const override;
void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
void dump(std::string& dump) override;
- [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) override;
+ [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index c0a35b1..5b7b295 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -63,10 +63,10 @@
toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
}
-std::list<NotifyArgs> RotaryEncoderInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) {
- std::list<NotifyArgs> out = InputMapper::configure(when, config, changes);
+std::list<NotifyArgs> RotaryEncoderInputMapper::reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) {
+ std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
if (!changes) {
mRotaryEncoderScrollAccumulator.configure(getDeviceContext());
}
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
index a0516c4..639a987 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
@@ -31,9 +31,9 @@
virtual uint32_t getSources() const override;
virtual void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
virtual void dump(std::string& dump) override;
- [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) override;
+ [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
index 60e6727..720fc69 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
@@ -116,10 +116,10 @@
}
}
-std::list<NotifyArgs> SensorInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) {
- std::list<NotifyArgs> out = InputMapper::configure(when, config, changes);
+std::list<NotifyArgs> SensorInputMapper::reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) {
+ std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
if (!changes) { // first time only
mDeviceEnabled = true;
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h
index 7f47df7..93cc244 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.h
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.h
@@ -33,9 +33,9 @@
uint32_t getSources() const override;
void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
void dump(std::string& dump) override;
- [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) override;
+ [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
bool enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod,
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 073c18b..eb99438 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -287,10 +287,10 @@
}
}
-std::list<NotifyArgs> TouchInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) {
- std::list<NotifyArgs> out = InputMapper::configure(when, config, changes);
+std::list<NotifyArgs> TouchInputMapper::reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) {
+ std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
mConfig = *config;
@@ -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 bc358b9..d98ae60 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -152,9 +152,9 @@
uint32_t getSources() const override;
void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
void dump(std::string& dump) override;
- [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) override;
+ [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
@@ -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/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index 661461b..33f368e 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -219,9 +219,9 @@
dump += addLinePrefix(mPropertyProvider.dump(), INDENT4);
}
-std::list<NotifyArgs> TouchpadInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) {
+std::list<NotifyArgs> TouchpadInputMapper::reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) {
if (!changes) {
// First time configuration
mPropertyProvider.loadPropertiesFromIdcFile(getDeviceContext().getConfiguration());
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index fb36d92..6f152fa 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -44,9 +44,9 @@
void populateDeviceInfo(InputDeviceInfo& deviceInfo) override;
void dump(std::string& dump) override;
- [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when,
- const InputReaderConfiguration* config,
- uint32_t changes) override;
+ [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
+ const InputReaderConfiguration* config,
+ uint32_t changes) override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 3d0fbb4..2223b35 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -263,8 +263,8 @@
}
}
- std::list<NotifyArgs> configure(nsecs_t, const InputReaderConfiguration* config,
- uint32_t changes) override {
+ std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration* config,
+ uint32_t changes) override {
std::scoped_lock<std::mutex> lock(mLock);
mConfigureWasCalled = true;
diff --git a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
index 9a19b97..0d5f30c 100644
--- a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
@@ -52,13 +52,13 @@
[&]() -> void { mapper.getSources(); },
[&]() -> void {
std::list<NotifyArgs> unused =
- mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
- fdp->ConsumeIntegral<int32_t>());
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+ fdp->ConsumeIntegral<int32_t>());
},
[&]() -> void {
// Need to reconfigure with 0 or you risk a NPE.
std::list<NotifyArgs> unused =
- mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
InputDeviceInfo info;
mapper.populateDeviceInfo(info);
},
@@ -71,7 +71,7 @@
// Need to reconfigure with 0 or you risk a NPE.
std::list<NotifyArgs> unused =
- mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(),
fdp->ConsumeIntegral<nsecs_t>(),
fdp->ConsumeIntegral<int32_t>(),
@@ -90,7 +90,7 @@
[&]() -> void {
// Need to reconfigure with 0 or you risk a NPE.
std::list<NotifyArgs> unused =
- mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
mapper.getAssociatedDisplayId();
},
})();
diff --git a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
index 33e7dbf..14cb8a5 100644
--- a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
@@ -64,8 +64,8 @@
[&]() -> void { mapper.getSources(); },
[&]() -> void {
std::list<NotifyArgs> unused =
- mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
- fdp->ConsumeIntegral<uint32_t>());
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+ fdp->ConsumeIntegral<uint32_t>());
},
[&]() -> void {
std::list<NotifyArgs> unused = mapper.reset(fdp->ConsumeIntegral<nsecs_t>());
diff --git a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
index 20db39d..8352a90 100644
--- a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
@@ -79,8 +79,8 @@
[&]() -> void { mapper.getSources(); },
[&]() -> void {
std::list<NotifyArgs> unused =
- mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
- fdp->ConsumeIntegral<uint32_t>());
+ mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+ fdp->ConsumeIntegral<uint32_t>());
},
[&]() -> void {
std::list<NotifyArgs> unused = mapper.reset(fdp->ConsumeIntegral<nsecs_t>());
@@ -127,8 +127,7 @@
[&]() -> void {
StylusState state{fdp->ConsumeIntegral<nsecs_t>(),
fdp->ConsumeFloatingPoint<float>(),
- fdp->ConsumeIntegral<uint32_t>(),
- getFuzzedToolType(*fdp)};
+ fdp->ConsumeIntegral<uint32_t>(), getFuzzedToolType(*fdp)};
std::list<NotifyArgs> unused = mapper.updateExternalStylusState(state);
},
[&]() -> void { mapper.getAssociatedDisplayId(); },
diff --git a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
index 8629671..a209cad 100644
--- a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
+++ b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
@@ -64,11 +64,61 @@
transactionsPendingBarrier = flushPendingTransactionQueues(transactions, flushState);
} while (lastTransactionsPendingBarrier != transactionsPendingBarrier);
+ applyUnsignaledBufferTransaction(transactions, flushState);
+
mPendingTransactionCount.fetch_sub(transactions.size());
ATRACE_INT("TransactionQueue", static_cast<int>(mPendingTransactionCount.load()));
return transactions;
}
+void TransactionHandler::applyUnsignaledBufferTransaction(
+ std::vector<TransactionState>& transactions, TransactionFlushState& flushState) {
+ // only apply an unsignaled buffer transaction if it's the first one
+ if (!transactions.empty()) {
+ return;
+ }
+
+ if (!flushState.queueWithUnsignaledBuffer) {
+ return;
+ }
+
+ auto it = mPendingTransactionQueues.find(flushState.queueWithUnsignaledBuffer);
+ LOG_ALWAYS_FATAL_IF(it == mPendingTransactionQueues.end(),
+ "Could not find queue with unsignaled buffer!");
+
+ auto& queue = it->second;
+ popTransactionFromPending(transactions, flushState, queue);
+ if (queue.empty()) {
+ it = mPendingTransactionQueues.erase(it);
+ }
+}
+
+void TransactionHandler::popTransactionFromPending(std::vector<TransactionState>& transactions,
+ TransactionFlushState& flushState,
+ std::queue<TransactionState>& queue) {
+ auto& transaction = queue.front();
+ // Transaction is ready move it from the pending queue.
+ flushState.firstTransaction = false;
+ removeFromStalledTransactions(transaction.id);
+ transactions.emplace_back(std::move(transaction));
+ queue.pop();
+
+ auto& readyToApplyTransaction = transactions.back();
+ readyToApplyTransaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
+ const bool frameNumberChanged =
+ state.bufferData->flags.test(BufferData::BufferDataChange::frameNumberChanged);
+ if (frameNumberChanged) {
+ flushState.bufferLayersReadyToPresent.emplace_or_replace(state.surface.get(),
+ state.bufferData->frameNumber);
+ } else {
+ // Barrier function only used for BBQ which always includes a frame number.
+ // This value only used for barrier logic.
+ flushState.bufferLayersReadyToPresent
+ .emplace_or_replace(state.surface.get(), std::numeric_limits<uint64_t>::max());
+ }
+ });
+}
+
TransactionHandler::TransactionReadiness TransactionHandler::applyFilters(
TransactionFlushState& flushState) {
auto ready = TransactionReadiness::Ready;
@@ -79,8 +129,7 @@
case TransactionReadiness::NotReadyBarrier:
return perFilterReady;
- case TransactionReadiness::ReadyUnsignaled:
- case TransactionReadiness::ReadyUnsignaledSingle:
+ case TransactionReadiness::NotReadyUnsignaled:
// If one of the filters allows latching an unsignaled buffer, latch this ready
// state.
ready = perFilterReady;
@@ -97,17 +146,7 @@
int transactionsPendingBarrier = 0;
auto it = mPendingTransactionQueues.begin();
while (it != mPendingTransactionQueues.end()) {
- auto& queue = it->second;
- IBinder* queueToken = it->first.get();
-
- // if we have already flushed a transaction with an unsignaled buffer then stop queue
- // processing
- if (std::find(flushState.queuesWithUnsignaledBuffers.begin(),
- flushState.queuesWithUnsignaledBuffers.end(),
- queueToken) != flushState.queuesWithUnsignaledBuffers.end()) {
- continue;
- }
-
+ auto& [applyToken, queue] = *it;
while (!queue.empty()) {
auto& transaction = queue.front();
flushState.transaction = &transaction;
@@ -117,38 +156,14 @@
break;
} else if (ready == TransactionReadiness::NotReady) {
break;
- }
-
- // Transaction is ready move it from the pending queue.
- flushState.firstTransaction = false;
- removeFromStalledTransactions(transaction.id);
- transactions.emplace_back(std::move(transaction));
- queue.pop();
-
- // If the buffer is unsignaled, then we don't want to signal other transactions using
- // the buffer as a barrier.
- auto& readyToApplyTransaction = transactions.back();
- if (ready == TransactionReadiness::Ready) {
- readyToApplyTransaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
- const bool frameNumberChanged = state.bufferData->flags.test(
- BufferData::BufferDataChange::frameNumberChanged);
- if (frameNumberChanged) {
- flushState.bufferLayersReadyToPresent
- .emplace_or_replace(state.surface.get(),
- state.bufferData->frameNumber);
- } else {
- // Barrier function only used for BBQ which always includes a frame number.
- // This value only used for barrier logic.
- flushState.bufferLayersReadyToPresent
- .emplace_or_replace(state.surface.get(),
- std::numeric_limits<uint64_t>::max());
- }
- });
- } else if (ready == TransactionReadiness::ReadyUnsignaledSingle) {
- // Track queues with a flushed unsingaled buffer.
- flushState.queuesWithUnsignaledBuffers.emplace_back(queueToken);
+ } else if (ready == TransactionReadiness::NotReadyUnsignaled) {
+ // We maybe able to latch this transaction if it's the only transaction
+ // ready to be applied.
+ flushState.queueWithUnsignaledBuffer = applyToken;
break;
}
+ // ready == TransactionReadiness::Ready
+ popTransactionFromPending(transactions, flushState, queue);
}
if (queue.empty()) {
diff --git a/services/surfaceflinger/FrontEnd/TransactionHandler.h b/services/surfaceflinger/FrontEnd/TransactionHandler.h
index 7fc825e..865835f 100644
--- a/services/surfaceflinger/FrontEnd/TransactionHandler.h
+++ b/services/surfaceflinger/FrontEnd/TransactionHandler.h
@@ -40,14 +40,20 @@
// Layer handles that have transactions with buffers that are ready to be applied.
ftl::SmallMap<IBinder* /* binder address */, uint64_t /* framenumber */, 15>
bufferLayersReadyToPresent = {};
- ftl::SmallVector<IBinder* /* queueToken */, 15> queuesWithUnsignaledBuffers;
+ // Tracks the queue with an unsignaled buffer. This is used to handle
+ // LatchUnsignaledConfig::AutoSingleLayer to ensure we only apply an unsignaled buffer
+ // if it's the only transaction that is ready to be applied.
+ sp<IBinder> queueWithUnsignaledBuffer = nullptr;
};
enum class TransactionReadiness {
- NotReady,
- NotReadyBarrier,
+ // Transaction is ready to be applied
Ready,
- ReadyUnsignaled,
- ReadyUnsignaledSingle,
+ // Transaction has unmet conditions (fence, present time, etc) and cannot be applied.
+ NotReady,
+ // Transaction is waiting on a barrier (another buffer to be latched first)
+ NotReadyBarrier,
+ // Transaction has an unsignaled fence but can be applied if it's the only transaction
+ NotReadyUnsignaled,
};
using TransactionFilter = std::function<TransactionReadiness(const TransactionFlushState&)>;
@@ -64,6 +70,9 @@
friend class ::android::TestableSurfaceFlinger;
int flushPendingTransactionQueues(std::vector<TransactionState>&, TransactionFlushState&);
+ void applyUnsignaledBufferTransaction(std::vector<TransactionState>&, TransactionFlushState&);
+ void popTransactionFromPending(std::vector<TransactionState>&, TransactionFlushState&,
+ std::queue<TransactionState>&);
TransactionReadiness applyFilters(TransactionFlushState&);
std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash>
mPendingTransactionQueues;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8dec57b..3406e92 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -172,8 +172,7 @@
mDrawingState.crop.makeInvalid();
mDrawingState.acquireFence = sp<Fence>::make(-1);
mDrawingState.acquireFenceTime = std::make_shared<FenceTime>(mDrawingState.acquireFence);
- mDrawingState.dataspace = ui::Dataspace::UNKNOWN;
- mDrawingState.dataspaceRequested = false;
+ mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
mDrawingState.hdrMetadata.validTypes = 0;
mDrawingState.surfaceDamageRegion = Region::INVALID_REGION;
mDrawingState.cornerRadius = 0.0f;
@@ -209,7 +208,6 @@
mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
mProtectedByApp = args.flags & ISurfaceComposerClient::eProtectedByApp;
- mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
mSnapshot->sequence = sequence;
mSnapshot->name = getDebugName();
@@ -2127,7 +2125,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 +2137,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(); });
}
}
@@ -3141,7 +3142,6 @@
}
bool Layer::setDataspace(ui::Dataspace dataspace) {
- mDrawingState.dataspaceRequested = true;
if (mDrawingState.dataspace == dataspace) return false;
mDrawingState.dataspace = dataspace;
mDrawingState.modified = true;
@@ -3406,6 +3406,42 @@
mBufferInfo.mTransform = mDrawingState.bufferTransform;
auto lastDataspace = mBufferInfo.mDataspace;
mBufferInfo.mDataspace = translateDataspace(mDrawingState.dataspace);
+ if (mBufferInfo.mBuffer != nullptr) {
+ auto& mapper = GraphicBufferMapper::get();
+ // TODO: We should measure if it's faster to do a blind write if we're on newer api levels
+ // and don't need to possibly remaps buffers.
+ ui::Dataspace dataspace = ui::Dataspace::UNKNOWN;
+ status_t err = OK;
+ {
+ ATRACE_NAME("getDataspace");
+ err = mapper.getDataspace(mBufferInfo.mBuffer->getBuffer()->handle, &dataspace);
+ }
+ if (err != OK || dataspace != mBufferInfo.mDataspace) {
+ {
+ ATRACE_NAME("setDataspace");
+ err = mapper.setDataspace(mBufferInfo.mBuffer->getBuffer()->handle,
+ static_cast<ui::Dataspace>(mBufferInfo.mDataspace));
+ }
+
+ // Some GPU drivers may cache gralloc metadata which means before we composite we need
+ // to upsert RenderEngine's caches. Put in a special workaround to be backwards
+ // compatible with old vendors, with a ticking clock.
+ static const int32_t kVendorVersion =
+ base::GetIntProperty("ro.vndk.version", __ANDROID_API_FUTURE__);
+ if (const auto format =
+ static_cast<aidl::android::hardware::graphics::common::PixelFormat>(
+ mBufferInfo.mBuffer->getPixelFormat());
+ err == OK && kVendorVersion < __ANDROID_API_U__ &&
+ (format ==
+ aidl::android::hardware::graphics::common::PixelFormat::
+ IMPLEMENTATION_DEFINED ||
+ format == aidl::android::hardware::graphics::common::PixelFormat::YCBCR_420_888 ||
+ format == aidl::android::hardware::graphics::common::PixelFormat::YV12 ||
+ format == aidl::android::hardware::graphics::common::PixelFormat::YCBCR_P010)) {
+ mBufferInfo.mBuffer->remapBuffer();
+ }
+ }
+ }
if (lastDataspace != mBufferInfo.mDataspace) {
mFlinger->mHdrLayerInfoChanged = true;
}
@@ -3996,10 +4032,6 @@
}
ui::Dataspace Layer::getDataSpace() const {
- return mDrawingState.dataspaceRequested ? getRequestedDataSpace() : ui::Dataspace::UNKNOWN;
-}
-
-ui::Dataspace Layer::getRequestedDataSpace() const {
return hasBufferOrSidebandStream() ? mBufferInfo.mDataspace : mDrawingState.dataspace;
}
@@ -4007,6 +4039,8 @@
ui::Dataspace updatedDataspace = dataspace;
// translate legacy dataspaces to modern dataspaces
switch (dataspace) {
+ // Treat unknown dataspaces as V0_sRGB
+ case ui::Dataspace::UNKNOWN:
case ui::Dataspace::SRGB:
updatedDataspace = ui::Dataspace::V0_SRGB;
break;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 0bfab7c..70b4e9b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -137,7 +137,6 @@
wp<Layer> touchableRegionCrop;
ui::Dataspace dataspace;
- bool dataspaceRequested;
uint64_t frameNumber;
ui::Transform transform;
@@ -333,7 +332,6 @@
virtual FrameRateCompatibility getDefaultFrameRateCompatibility() const;
//
ui::Dataspace getDataSpace() const;
- ui::Dataspace getRequestedDataSpace() const;
virtual sp<LayerFE> getCompositionEngineLayerFE() const;
virtual sp<LayerFE> copyCompositionEngineLayerFE() const;
@@ -611,7 +609,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/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 7f8d394..3e12db6 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -409,6 +409,7 @@
}
void Scheduler::resyncAllToHardwareVsync(bool allowToEnable) {
+ ATRACE_CALL();
std::scoped_lock lock(mDisplayLock);
ftl::FakeGuard guard(kMainThreadContext);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 145fd46..2f024ce 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4262,20 +4262,23 @@
return TraverseBuffersReturnValues::STOP_TRAVERSAL;
}
- // check fence status
- const bool allowLatchUnsignaled = shouldLatchUnsignaled(layer, s, transaction.states.size(),
- flushState.firstTransaction);
- ATRACE_FORMAT("%s allowLatchUnsignaled=%s", layer->getName().c_str(),
- allowLatchUnsignaled ? "true" : "false");
-
- const bool acquireFenceChanged = s.bufferData &&
+ // ignore the acquire fence if LatchUnsignaledConfig::Always is set.
+ const bool checkAcquireFence = enableLatchUnsignaledConfig != LatchUnsignaledConfig::Always;
+ const bool acquireFenceAvailable = s.bufferData &&
s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) &&
s.bufferData->acquireFence;
- const bool fenceSignaled =
- (!acquireFenceChanged ||
- s.bufferData->acquireFence->getStatus() != Fence::Status::Unsignaled);
+ const bool fenceSignaled = !checkAcquireFence || !acquireFenceAvailable ||
+ s.bufferData->acquireFence->getStatus() != Fence::Status::Unsignaled;
if (!fenceSignaled) {
- if (!allowLatchUnsignaled) {
+ // check fence status
+ const bool allowLatchUnsignaled =
+ shouldLatchUnsignaled(layer, s, transaction.states.size(),
+ flushState.firstTransaction);
+ ATRACE_FORMAT("%s allowLatchUnsignaled=%s", layer->getName().c_str(),
+ allowLatchUnsignaled ? "true" : "false");
+ if (allowLatchUnsignaled) {
+ ready = TransactionReadiness::NotReadyUnsignaled;
+ } else {
ready = TransactionReadiness::NotReady;
auto& listener = s.bufferData->releaseBufferListener;
if (listener &&
@@ -4288,10 +4291,6 @@
}
return TraverseBuffersReturnValues::STOP_TRAVERSAL;
}
-
- ready = enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer
- ? TransactionReadiness::ReadyUnsignaledSingle
- : TransactionReadiness::ReadyUnsignaled;
}
return TraverseBuffersReturnValues::CONTINUE_TRAVERSAL;
});
@@ -8969,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 35707a2..5783c8d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -174,10 +174,15 @@
// Latch unsignaled is permitted when a single layer is updated in a frame,
// and the update includes just a buffer update (i.e. no sync transactions
// or geometry changes).
+ // Latch unsignaled is also only permitted when a single transaction is ready
+ // to be applied. If we pass an unsignaled fence to HWC, HWC might miss presenting
+ // the frame if the fence does not fire in time. If we apply another transaction,
+ // we may penalize the other transaction unfairly.
AutoSingleLayer,
// All buffers are latched unsignaled. This behaviour is discouraged as it
// can break sync transactions, stall the display and cause undesired side effects.
+ // This is equivalent to ignoring the acquire fence when applying transactions.
Always,
};
@@ -323,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
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index 593c4ff..57d927b 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -47,6 +47,7 @@
uint64_t getId() const override { return mId; }
PixelFormat getPixelFormat() const override { return mPixelFormat; }
uint64_t getUsage() const override { return mUsage; }
+ void remapBuffer() override {}
~FakeExternalTexture() = default;
};
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f596061..156007b 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -605,7 +605,7 @@
EXPECT_EQ(false, layer.source.buffer.isOpaque);
EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.x);
EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.y);
- EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace);
+ EXPECT_EQ(ui::Dataspace::V0_SRGB, layer.sourceDataspace);
EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha);
return resultFuture;
});
@@ -654,7 +654,7 @@
layer.source.solidColor);
EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.x);
EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.y);
- EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace);
+ EXPECT_EQ(ui::Dataspace::V0_SRGB, layer.sourceDataspace);
EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha);
return resultFuture;
});
@@ -731,7 +731,7 @@
EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer.source.solidColor);
EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.x);
EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.y);
- EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace);
+ EXPECT_EQ(ui::Dataspace::V0_SRGB, layer.sourceDataspace);
EXPECT_EQ(1.0f, layer.alpha);
return resultFuture;
});
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index d4e2357..03c4e71 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -294,7 +294,8 @@
return fence;
}
- ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what) {
+ ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what,
+ std::optional<sp<IBinder>> layerHandle = std::nullopt) {
ComposerState state;
state.state.bufferData =
std::make_shared<fake::BufferData>(/* bufferId */ 123L, /* width */ 1,
@@ -302,15 +303,20 @@
/* outUsage */ 0);
state.state.bufferData->acquireFence = std::move(fence);
state.state.layerId = layerId;
- state.state.surface =
+ state.state.surface = layerHandle.value_or(
sp<Layer>::make(LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
- ->getHandle();
+ ->getHandle());
state.state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
state.state.what = what;
if (what & layer_state_t::eCropChanged) {
state.state.crop = Rect(1, 2, 3, 4);
}
+ if (what & layer_state_t::eFlagsChanged) {
+ state.state.flags = layer_state_t::eEnableBackpressure;
+ state.state.mask = layer_state_t::eEnableBackpressure;
+ }
+
return state;
}
@@ -601,6 +607,41 @@
setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
}
+TEST_F(LatchUnsignaledAutoSingleLayerTest, UnsignaledNotAppliedWhenThereAreSignaled_SignaledFirst) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const sp<IBinder> kApplyToken3 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction2 =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken3,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+
+ setTransactionStates({signaledTransaction, signaledTransaction2, unsignaledTransaction},
+ kExpectedTransactionsPending);
+}
+
class LatchUnsignaledDisabledTest : public LatchUnsignaledTest {
public:
void SetUp() override {
@@ -943,6 +984,43 @@
kExpectedTransactionsPending);
}
+TEST_F(LatchUnsignaledAlwaysTest, RespectsBackPressureFlag) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kExpectedTransactionsPending = 1u;
+ auto layer =
+ sp<Layer>::make(LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}));
+ auto layerHandle = layer->getHandle();
+ const auto setBackPressureFlagTransaction =
+ createTransactionInfo(kApplyToken1,
+ {createComposerState(kLayerId1, fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged |
+ layer_state_t::eFlagsChanged,
+ {layerHandle})});
+ setTransactionStates({setBackPressureFlagTransaction}, 0u);
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged,
+ {layerHandle}),
+ });
+ const auto unsignaledTransaction2 =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged,
+ {layerHandle}),
+ });
+ setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
+ kExpectedTransactionsPending);
+}
+
TEST_F(LatchUnsignaledAlwaysTest, LatchUnsignaledWhenEarlyOffset) {
const sp<IBinder> kApplyToken =
IInterface::asBinder(TransactionCompletedListener::getIInstance());