Merge "SF: Introduce LayerTraceGenerator" into tm-dev am: 120a2361df am: bede51a6da
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/16947238
Change-Id: I265297de159f4e6de8177ab1537bc79b7ef9129c
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index 41a8426..8f5dc9b 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -31,23 +31,15 @@
MultiTouchMotionAccumulator::MultiTouchMotionAccumulator()
: mCurrentSlot(-1),
- mSlots(nullptr),
- mSlotCount(0),
mUsingSlotsProtocol(false),
mHaveStylus(false) {}
-MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
- delete[] mSlots;
-}
-
void MultiTouchMotionAccumulator::configure(InputDeviceContext& deviceContext, size_t slotCount,
bool usingSlotsProtocol) {
- mSlotCount = slotCount;
mUsingSlotsProtocol = usingSlotsProtocol;
mHaveStylus = deviceContext.hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
- delete[] mSlots;
- mSlots = new Slot[slotCount];
+ mSlots = std::vector<Slot>(slotCount);
}
void MultiTouchMotionAccumulator::reset(InputDeviceContext& deviceContext) {
@@ -76,10 +68,8 @@
}
void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
- if (mSlots) {
- for (size_t i = 0; i < mSlotCount; i++) {
- mSlots[i].clear();
- }
+ for (Slot& slot : mSlots) {
+ slot.clear();
}
mCurrentSlot = initialSlot;
}
@@ -96,68 +86,68 @@
mCurrentSlot = 0;
}
- if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
+ if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlots.size()) {
if (DEBUG_POINTERS) {
if (newSlot) {
ALOGW("MultiTouch device emitted invalid slot index %d but it "
"should be between 0 and %zd; ignoring this slot.",
- mCurrentSlot, mSlotCount - 1);
+ mCurrentSlot, mSlots.size() - 1);
}
}
} else {
- Slot* slot = &mSlots[mCurrentSlot];
+ Slot& slot = mSlots[mCurrentSlot];
// If mUsingSlotsProtocol is true, it means the raw pointer has axis info of
// ABS_MT_TRACKING_ID and ABS_MT_SLOT, so driver should send a valid trackingId while
// updating the slot.
if (!mUsingSlotsProtocol) {
- slot->mInUse = true;
+ slot.mInUse = true;
}
switch (rawEvent->code) {
case ABS_MT_POSITION_X:
- slot->mAbsMTPositionX = rawEvent->value;
- warnIfNotInUse(*rawEvent, *slot);
+ slot.mAbsMTPositionX = rawEvent->value;
+ warnIfNotInUse(*rawEvent, slot);
break;
case ABS_MT_POSITION_Y:
- slot->mAbsMTPositionY = rawEvent->value;
- warnIfNotInUse(*rawEvent, *slot);
+ slot.mAbsMTPositionY = rawEvent->value;
+ warnIfNotInUse(*rawEvent, slot);
break;
case ABS_MT_TOUCH_MAJOR:
- slot->mAbsMTTouchMajor = rawEvent->value;
+ slot.mAbsMTTouchMajor = rawEvent->value;
break;
case ABS_MT_TOUCH_MINOR:
- slot->mAbsMTTouchMinor = rawEvent->value;
- slot->mHaveAbsMTTouchMinor = true;
+ slot.mAbsMTTouchMinor = rawEvent->value;
+ slot.mHaveAbsMTTouchMinor = true;
break;
case ABS_MT_WIDTH_MAJOR:
- slot->mAbsMTWidthMajor = rawEvent->value;
+ slot.mAbsMTWidthMajor = rawEvent->value;
break;
case ABS_MT_WIDTH_MINOR:
- slot->mAbsMTWidthMinor = rawEvent->value;
- slot->mHaveAbsMTWidthMinor = true;
+ slot.mAbsMTWidthMinor = rawEvent->value;
+ slot.mHaveAbsMTWidthMinor = true;
break;
case ABS_MT_ORIENTATION:
- slot->mAbsMTOrientation = rawEvent->value;
+ slot.mAbsMTOrientation = rawEvent->value;
break;
case ABS_MT_TRACKING_ID:
if (mUsingSlotsProtocol && rawEvent->value < 0) {
// The slot is no longer in use but it retains its previous contents,
// which may be reused for subsequent touches.
- slot->mInUse = false;
+ slot.mInUse = false;
} else {
- slot->mInUse = true;
- slot->mAbsMTTrackingId = rawEvent->value;
+ slot.mInUse = true;
+ slot.mAbsMTTrackingId = rawEvent->value;
}
break;
case ABS_MT_PRESSURE:
- slot->mAbsMTPressure = rawEvent->value;
+ slot.mAbsMTPressure = rawEvent->value;
break;
case ABS_MT_DISTANCE:
- slot->mAbsMTDistance = rawEvent->value;
+ slot.mAbsMTDistance = rawEvent->value;
break;
case ABS_MT_TOOL_TYPE:
- slot->mAbsMTToolType = rawEvent->value;
- slot->mHaveAbsMTToolType = true;
+ slot.mAbsMTToolType = rawEvent->value;
+ slot.mHaveAbsMTToolType = true;
break;
}
}
@@ -186,28 +176,6 @@
// --- MultiTouchMotionAccumulator::Slot ---
-MultiTouchMotionAccumulator::Slot::Slot() {
- clear();
-}
-
-void MultiTouchMotionAccumulator::Slot::clear() {
- mInUse = false;
- mHaveAbsMTTouchMinor = false;
- mHaveAbsMTWidthMinor = false;
- mHaveAbsMTToolType = false;
- mAbsMTPositionX = 0;
- mAbsMTPositionY = 0;
- mAbsMTTouchMajor = 0;
- mAbsMTTouchMinor = 0;
- mAbsMTWidthMajor = 0;
- mAbsMTWidthMinor = 0;
- mAbsMTOrientation = 0;
- mAbsMTTrackingId = -1;
- mAbsMTPressure = 0;
- mAbsMTDistance = 0;
- mAbsMTToolType = 0;
-}
-
int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
if (mHaveAbsMTToolType) {
switch (mAbsMTToolType) {
@@ -264,14 +232,14 @@
mHavePointerIds = true;
for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
- const MultiTouchMotionAccumulator::Slot* inSlot =
+ const MultiTouchMotionAccumulator::Slot& inSlot =
mMultiTouchMotionAccumulator.getSlot(inIndex);
- if (!inSlot->isInUse()) {
+ if (!inSlot.isInUse()) {
continue;
}
- if (inSlot->getToolType() == AMOTION_EVENT_TOOL_TYPE_PALM) {
- std::optional<int32_t> id = getActiveBitId(*inSlot);
+ if (inSlot.getToolType() == AMOTION_EVENT_TOOL_TYPE_PALM) {
+ std::optional<int32_t> id = getActiveBitId(inSlot);
if (id) {
outState->rawPointerData.canceledIdBits.markBit(id.value());
}
@@ -292,19 +260,19 @@
}
RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
- outPointer.x = inSlot->getX();
- outPointer.y = inSlot->getY();
- outPointer.pressure = inSlot->getPressure();
- outPointer.touchMajor = inSlot->getTouchMajor();
- outPointer.touchMinor = inSlot->getTouchMinor();
- outPointer.toolMajor = inSlot->getToolMajor();
- outPointer.toolMinor = inSlot->getToolMinor();
- outPointer.orientation = inSlot->getOrientation();
- outPointer.distance = inSlot->getDistance();
+ outPointer.x = inSlot.getX();
+ outPointer.y = inSlot.getY();
+ outPointer.pressure = inSlot.getPressure();
+ outPointer.touchMajor = inSlot.getTouchMajor();
+ outPointer.touchMinor = inSlot.getTouchMinor();
+ outPointer.toolMajor = inSlot.getToolMajor();
+ outPointer.toolMinor = inSlot.getToolMinor();
+ outPointer.orientation = inSlot.getOrientation();
+ outPointer.distance = inSlot.getDistance();
outPointer.tiltX = 0;
outPointer.tiltY = 0;
- outPointer.toolType = inSlot->getToolType();
+ outPointer.toolType = inSlot.getToolType();
if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
outPointer.toolType = mTouchButtonAccumulator.getToolType();
if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
@@ -318,12 +286,12 @@
bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE &&
(mTouchButtonAccumulator.isHovering() ||
- (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
+ (mRawPointerAxes.pressure.valid && inSlot.getPressure() <= 0));
outPointer.isHovering = isHovering;
// Assign pointer id using tracking id if available.
if (mHavePointerIds) {
- int32_t trackingId = inSlot->getTrackingId();
+ int32_t trackingId = inSlot.getTrackingId();
int32_t id = -1;
if (trackingId >= 0) {
for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty();) {
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
index b7c3457..fe8af5d 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
@@ -46,29 +46,27 @@
private:
friend class MultiTouchMotionAccumulator;
- bool mInUse;
- bool mHaveAbsMTTouchMinor;
- bool mHaveAbsMTWidthMinor;
- bool mHaveAbsMTToolType;
+ bool mInUse = false;
+ bool mHaveAbsMTTouchMinor = false;
+ bool mHaveAbsMTWidthMinor = false;
+ bool mHaveAbsMTToolType = false;
- int32_t mAbsMTPositionX;
- int32_t mAbsMTPositionY;
- int32_t mAbsMTTouchMajor;
- int32_t mAbsMTTouchMinor;
- int32_t mAbsMTWidthMajor;
- int32_t mAbsMTWidthMinor;
- int32_t mAbsMTOrientation;
- int32_t mAbsMTTrackingId;
- int32_t mAbsMTPressure;
- int32_t mAbsMTDistance;
- int32_t mAbsMTToolType;
+ int32_t mAbsMTPositionX = 0;
+ int32_t mAbsMTPositionY = 0;
+ int32_t mAbsMTTouchMajor = 0;
+ int32_t mAbsMTTouchMinor = 0;
+ int32_t mAbsMTWidthMajor = 0;
+ int32_t mAbsMTWidthMinor = 0;
+ int32_t mAbsMTOrientation = 0;
+ int32_t mAbsMTTrackingId = -1;
+ int32_t mAbsMTPressure = 0;
+ int32_t mAbsMTDistance = 0;
+ int32_t mAbsMTToolType = 0;
- Slot();
- void clear();
+ void clear() { *this = Slot(); }
};
MultiTouchMotionAccumulator();
- ~MultiTouchMotionAccumulator();
void configure(InputDeviceContext& deviceContext, size_t slotCount, bool usingSlotsProtocol);
void reset(InputDeviceContext& deviceContext);
@@ -76,13 +74,15 @@
void finishSync();
bool hasStylus() const;
- inline size_t getSlotCount() const { return mSlotCount; }
- inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
+ inline size_t getSlotCount() const { return mSlots.size(); }
+ inline const Slot& getSlot(size_t index) const {
+ LOG_ALWAYS_FATAL_IF(index < 0 || index >= mSlots.size(), "Invalid index: %zu", index);
+ return mSlots[index];
+ }
private:
int32_t mCurrentSlot;
- Slot* mSlots;
- size_t mSlotCount;
+ std::vector<Slot> mSlots;
bool mUsingSlotsProtocol;
bool mHaveStylus;
diff --git a/services/surfaceflinger/fuzzer/Android.bp b/services/surfaceflinger/fuzzer/Android.bp
index b0b6bf1..7350e09 100644
--- a/services/surfaceflinger/fuzzer/Android.bp
+++ b/services/surfaceflinger/fuzzer/Android.bp
@@ -127,3 +127,13 @@
"surfaceflinger_layer_fuzzer.cpp",
],
}
+
+cc_fuzz {
+ name: "surfaceflinger_frametracer_fuzzer",
+ defaults: [
+ "surfaceflinger_fuzz_defaults",
+ ],
+ srcs: [
+ "surfaceflinger_frametracer_fuzzer.cpp",
+ ],
+}
diff --git a/services/surfaceflinger/fuzzer/README.md b/services/surfaceflinger/fuzzer/README.md
index 78a7596..7a5f229 100644
--- a/services/surfaceflinger/fuzzer/README.md
+++ b/services/surfaceflinger/fuzzer/README.md
@@ -4,6 +4,7 @@
+ [DisplayHardware](#DisplayHardware)
+ [Scheduler](#Scheduler)
+ [Layer](#Layer)
++ [FrameTracer](#FrameTracer)
# <a name="SurfaceFlinger"></a> Fuzzer for SurfaceFlinger
@@ -93,3 +94,16 @@
$ adb sync data
$ adb shell /data/fuzz/arm64/surfaceflinger_layer_fuzzer/surfaceflinger_layer_fuzzer
```
+
+# <a name="FrameTracer"></a> Fuzzer for FrameTracer
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) surfaceflinger_frametracer_fuzzer
+```
+2. To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/surfaceflinger_frametracer_fuzzer/surfaceflinger_frametracer_fuzzer
+```
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp
new file mode 100644
index 0000000..a22a778
--- /dev/null
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <FrameTracer/FrameTracer.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <perfetto/trace/trace.pb.h>
+
+namespace android::fuzz {
+
+using namespace google::protobuf;
+
+constexpr size_t kMaxStringSize = 100;
+constexpr size_t kMinLayerIds = 1;
+constexpr size_t kMaxLayerIds = 10;
+constexpr int32_t kConfigDuration = 500;
+constexpr int32_t kBufferSize = 1024;
+constexpr int32_t kTimeOffset = 100000;
+
+class FrameTracerFuzzer {
+public:
+ FrameTracerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+ // Fuzzer is single-threaded, so no need to be thread-safe.
+ static bool wasInitialized = false;
+ if (!wasInitialized) {
+ perfetto::TracingInitArgs args;
+ args.backends = perfetto::kInProcessBackend;
+ perfetto::Tracing::Initialize(args);
+ wasInitialized = true;
+ }
+ mFrameTracer = std::make_unique<android::FrameTracer>();
+ }
+ ~FrameTracerFuzzer() { mFrameTracer.reset(); }
+ void process();
+
+private:
+ std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest();
+ void traceTimestamp();
+ std::vector<int32_t> generateLayerIds(size_t numLayerIds);
+ void traceTimestamp(std::vector<int32_t> layerIds, size_t numLayerIds);
+ void traceFence(std::vector<int32_t> layerIds, size_t numLayerIds);
+ std::unique_ptr<android::FrameTracer> mFrameTracer = nullptr;
+ FuzzedDataProvider mFdp;
+ android::FenceToFenceTimeMap mFenceFactory;
+};
+
+std::unique_ptr<perfetto::TracingSession> FrameTracerFuzzer::getTracingSessionForTest() {
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(kConfigDuration);
+ cfg.add_buffers()->set_size_kb(kBufferSize);
+ auto* dsCfg = cfg.add_data_sources()->mutable_config();
+ dsCfg->set_name(android::FrameTracer::kFrameTracerDataSource);
+
+ auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
+ tracingSession->Setup(cfg);
+ return tracingSession;
+}
+
+std::vector<int32_t> FrameTracerFuzzer::generateLayerIds(size_t numLayerIds) {
+ std::vector<int32_t> layerIds;
+ for (size_t i = 0; i < numLayerIds; ++i) {
+ layerIds.push_back(mFdp.ConsumeIntegral<int32_t>());
+ }
+ return layerIds;
+}
+
+void FrameTracerFuzzer::traceTimestamp(std::vector<int32_t> layerIds, size_t numLayerIds) {
+ int32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1));
+ mFrameTracer->traceTimestamp(layerId, mFdp.ConsumeIntegral<uint64_t>() /*bufferID*/,
+ mFdp.ConsumeIntegral<uint64_t>() /*frameNumber*/,
+ mFdp.ConsumeIntegral<nsecs_t>() /*timestamp*/,
+ android::FrameTracer::FrameEvent::UNSPECIFIED,
+ mFdp.ConsumeIntegral<nsecs_t>() /*duration*/);
+}
+
+void FrameTracerFuzzer::traceFence(std::vector<int32_t> layerIds, size_t numLayerIds) {
+ const nsecs_t signalTime = systemTime();
+ const nsecs_t startTime = signalTime + kTimeOffset;
+ auto fence = mFenceFactory.createFenceTimeForTest(android::Fence::NO_FENCE);
+ mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, signalTime);
+ int32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1));
+ mFrameTracer->traceFence(layerId, mFdp.ConsumeIntegral<uint64_t>() /*bufferID*/,
+ mFdp.ConsumeIntegral<uint64_t>() /*frameNumber*/, fence,
+ android::FrameTracer::FrameEvent::ACQUIRE_FENCE, startTime);
+}
+
+void FrameTracerFuzzer::process() {
+ mFrameTracer->registerDataSource();
+
+ auto tracingSession = getTracingSessionForTest();
+ tracingSession->StartBlocking();
+
+ size_t numLayerIds = mFdp.ConsumeIntegralInRange<size_t>(kMinLayerIds, kMaxLayerIds);
+ std::vector<int32_t> layerIds = generateLayerIds(numLayerIds);
+
+ for (auto it = layerIds.begin(); it != layerIds.end(); ++it) {
+ mFrameTracer->traceNewLayer(*it /*layerId*/,
+ mFdp.ConsumeRandomLengthString(kMaxStringSize) /*layerName*/);
+ }
+
+ traceTimestamp(layerIds, numLayerIds);
+ traceFence(layerIds, numLayerIds);
+
+ mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, systemTime());
+
+ tracingSession->StopBlocking();
+
+ for (auto it = layerIds.begin(); it != layerIds.end(); ++it) {
+ mFrameTracer->onDestroy(*it);
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FrameTracerFuzzer frameTracerFuzzer(data, size);
+ frameTracerFuzzer.process();
+ return 0;
+}
+
+} // namespace android::fuzz