diff options
| -rw-r--r-- | include/input/InputTransport.h | 13 | ||||
| -rw-r--r-- | libs/input/InputTransport.cpp | 106 | ||||
| -rw-r--r-- | libs/input/tests/StructLayout_test.cpp | 3 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderEngine/ProgramCache.cpp | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 10 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceTracing.cpp | 46 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceTracing.h | 9 |
7 files changed, 169 insertions, 20 deletions
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 1ea2c2cc07..ecdc075ac8 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -41,6 +41,13 @@ namespace android { * * Note that this structure is used for IPCs so its layout must be identical * on 64 and 32 bit processes. This is tested in StructLayout_test.cpp. + * + * Since the struct must be aligned to an 8-byte boundary, there could be uninitialized bytes + * in-between the defined fields. This padding data should be explicitly accounted for by adding + * "empty" fields into the struct. This data is memset to zero before sending the struct across + * the socket. Adding the explicit fields ensures that the memset is not optimized away by the + * compiler. When a new field is added to the struct, the corresponding change + * in StructLayout_test should be made. */ struct InputMessage { enum { @@ -61,6 +68,7 @@ struct InputMessage { union Body { struct Key { uint32_t seq; + uint32_t empty1; nsecs_t eventTime __attribute__((aligned(8))); int32_t deviceId; int32_t source; @@ -71,6 +79,7 @@ struct InputMessage { int32_t scanCode; int32_t metaState; int32_t repeatCount; + uint32_t empty2; nsecs_t downTime __attribute__((aligned(8))); inline size_t size() const { @@ -80,6 +89,7 @@ struct InputMessage { struct Motion { uint32_t seq; + uint32_t empty1; nsecs_t eventTime __attribute__((aligned(8))); int32_t deviceId; int32_t source; @@ -90,12 +100,14 @@ struct InputMessage { int32_t metaState; int32_t buttonState; int32_t edgeFlags; + uint32_t empty2; nsecs_t downTime __attribute__((aligned(8))); float xOffset; float yOffset; float xPrecision; float yPrecision; uint32_t pointerCount; + uint32_t empty3; // Note that PointerCoords requires 8 byte alignment. struct Pointer { PointerProperties properties; @@ -126,6 +138,7 @@ struct InputMessage { bool isValid(size_t actualSize) const; size_t size() const; + void getSanitizedCopy(InputMessage* msg) const; }; /* diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index aa0bf17ca3..03f593f8b2 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -96,6 +96,106 @@ size_t InputMessage::size() const { return sizeof(Header); } +/** + * There could be non-zero bytes in-between InputMessage fields. Force-initialize the entire + * memory to zero, then only copy the valid bytes on a per-field basis. + */ +void InputMessage::getSanitizedCopy(InputMessage* msg) const { + memset(msg, 0, sizeof(*msg)); + + // Write the header + msg->header.type = header.type; + + // Write the body + switch(header.type) { + case InputMessage::TYPE_KEY: { + // uint32_t seq + msg->body.key.seq = body.key.seq; + // nsecs_t eventTime + msg->body.key.eventTime = body.key.eventTime; + // int32_t deviceId + msg->body.key.deviceId = body.key.deviceId; + // int32_t source + msg->body.key.source = body.key.source; + // int32_t displayId + msg->body.key.displayId = body.key.displayId; + // int32_t action + msg->body.key.action = body.key.action; + // int32_t flags + msg->body.key.flags = body.key.flags; + // int32_t keyCode + msg->body.key.keyCode = body.key.keyCode; + // int32_t scanCode + msg->body.key.scanCode = body.key.scanCode; + // int32_t metaState + msg->body.key.metaState = body.key.metaState; + // int32_t repeatCount + msg->body.key.repeatCount = body.key.repeatCount; + // nsecs_t downTime + msg->body.key.downTime = body.key.downTime; + break; + } + case InputMessage::TYPE_MOTION: { + // uint32_t seq + msg->body.motion.seq = body.motion.seq; + // nsecs_t eventTime + msg->body.motion.eventTime = body.motion.eventTime; + // int32_t deviceId + msg->body.motion.deviceId = body.motion.deviceId; + // int32_t source + msg->body.motion.source = body.motion.source; + // int32_t displayId + msg->body.motion.displayId = body.motion.displayId; + // int32_t action + msg->body.motion.action = body.motion.action; + // int32_t actionButton + msg->body.motion.actionButton = body.motion.actionButton; + // int32_t flags + msg->body.motion.flags = body.motion.flags; + // int32_t metaState + msg->body.motion.metaState = body.motion.metaState; + // int32_t buttonState + msg->body.motion.buttonState = body.motion.buttonState; + // int32_t edgeFlags + msg->body.motion.edgeFlags = body.motion.edgeFlags; + // nsecs_t downTime + msg->body.motion.downTime = body.motion.downTime; + // float xOffset + msg->body.motion.xOffset = body.motion.xOffset; + // float yOffset + msg->body.motion.yOffset = body.motion.yOffset; + // float xPrecision + msg->body.motion.xPrecision = body.motion.xPrecision; + // float yPrecision + msg->body.motion.yPrecision = body.motion.yPrecision; + // uint32_t pointerCount + msg->body.motion.pointerCount = body.motion.pointerCount; + //struct Pointer pointers[MAX_POINTERS] + for (size_t i = 0; i < body.motion.pointerCount; i++) { + // PointerProperties properties + msg->body.motion.pointers[i].properties.id = body.motion.pointers[i].properties.id; + msg->body.motion.pointers[i].properties.toolType = + body.motion.pointers[i].properties.toolType, + // PointerCoords coords + msg->body.motion.pointers[i].coords.bits = body.motion.pointers[i].coords.bits; + const uint32_t count = BitSet64::count(body.motion.pointers[i].coords.bits); + memcpy(&msg->body.motion.pointers[i].coords.values[0], + &body.motion.pointers[i].coords.values[0], + count * (sizeof(body.motion.pointers[i].coords.values[0]))); + } + break; + } + case InputMessage::TYPE_FINISHED: { + msg->body.finished.seq = body.finished.seq; + msg->body.finished.handled = body.finished.handled; + break; + } + default: { + LOG_FATAL("Unexpected message type %i", header.type); + break; + } + } +} // --- InputChannel --- @@ -149,10 +249,12 @@ status_t InputChannel::openInputChannelPair(const std::string& name, } status_t InputChannel::sendMessage(const InputMessage* msg) { - size_t msgLength = msg->size(); + const size_t msgLength = msg->size(); + InputMessage cleanMsg; + msg->getSanitizedCopy(&cleanMsg); ssize_t nWrite; do { - nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); + nWrite = ::send(mFd, &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); } while (nWrite == -1 && errno == EINTR); if (nWrite < 0) { diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp index d19f3b8066..12a67828ac 100644 --- a/libs/input/tests/StructLayout_test.cpp +++ b/libs/input/tests/StructLayout_test.cpp @@ -65,6 +65,9 @@ void TestInputMessageAlignment() { CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 76); CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 80); CHECK_OFFSET(InputMessage::Body::Motion, pointers, 88); + + CHECK_OFFSET(InputMessage::Body::Finished, seq, 0); + CHECK_OFFSET(InputMessage::Body::Finished, handled, 4); } } // namespace android diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index fe992f13b6..2073b05453 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -220,7 +220,7 @@ void ProgramCache::generateEOTF(Formatter& fs, const Key& needs) { const highp float c2 = (2413.0 / 4096.0) * 32.0; const highp float c3 = (2392.0 / 4096.0) * 32.0; - highp vec3 tmp = pow(color, 1.0 / vec3(m2)); + highp vec3 tmp = pow(clamp(color, 0.0, 1.0), 1.0 / vec3(m2)); tmp = max(tmp - c1, 0.0) / (c2 - c3 * tmp); return pow(tmp, 1.0 / vec3(m1)); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e693dd28dd..82bf19f12f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4433,6 +4433,12 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, result.append("\n"); /* + * Tracing state + */ + mTracing.dump(result); + result.append("\n"); + + /* * HWC layer minidump */ for (size_t d = 0; d < mDisplays.size(); d++) { @@ -4779,12 +4785,12 @@ status_t SurfaceFlinger::onTransact( case 1025: { // Set layer tracing n = data.readInt32(); if (n) { - ALOGV("LayerTracing enabled"); + ALOGD("LayerTracing enabled"); mTracing.enable(); doTracing("tracing.enable"); reply->writeInt32(NO_ERROR); } else { - ALOGV("LayerTracing disabled"); + ALOGD("LayerTracing disabled"); status_t err = mTracing.disable(); reply->writeInt32(err); } diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp index f8c466ea19..67dcd06187 100644 --- a/services/surfaceflinger/SurfaceTracing.cpp +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -27,52 +27,67 @@ namespace android { void SurfaceTracing::enable() { + ATRACE_CALL(); + std::lock_guard<std::mutex> protoGuard(mTraceMutex); + if (mEnabled) { return; } - ATRACE_CALL(); mEnabled = true; - std::lock_guard<std::mutex> protoGuard(mTraceMutex); - mTrace.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 | - LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L); + mTrace = std::make_unique<LayersTraceFileProto>(); + mTrace->set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 | + LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L); } status_t SurfaceTracing::disable() { + ATRACE_CALL(); + std::lock_guard<std::mutex> protoGuard(mTraceMutex); + if (!mEnabled) { return NO_ERROR; } - ATRACE_CALL(); - std::lock_guard<std::mutex> protoGuard(mTraceMutex); mEnabled = false; status_t err(writeProtoFileLocked()); ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied"); ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields"); - mTrace.Clear(); + mTrace.reset(); return err; } -bool SurfaceTracing::isEnabled() { +bool SurfaceTracing::isEnabled() const { + std::lock_guard<std::mutex> protoGuard(mTraceMutex); return mEnabled; } void SurfaceTracing::traceLayers(const char* where, LayersProto layers) { std::lock_guard<std::mutex> protoGuard(mTraceMutex); - - LayersTraceProto* entry = mTrace.add_entry(); + if (!mEnabled) { + return; + } + LayersTraceProto* entry = mTrace->add_entry(); entry->set_elapsed_realtime_nanos(elapsedRealtimeNano()); entry->set_where(where); entry->mutable_layers()->Swap(&layers); + + constexpr int maxBufferedEntryCount = 3600; + if (mTrace->entry_size() >= maxBufferedEntryCount) { + // TODO: flush buffered entries without disabling tracing + ALOGE("too many buffered frames; force disable tracing"); + mEnabled = false; + writeProtoFileLocked(); + mTrace.reset(); + } } status_t SurfaceTracing::writeProtoFileLocked() { ATRACE_CALL(); - if (!mTrace.IsInitialized()) { + if (!mTrace->IsInitialized()) { return NOT_ENOUGH_DATA; } std::string output; - if (!mTrace.SerializeToString(&output)) { + if (!mTrace->SerializeToString(&output)) { return PERMISSION_DENIED; } if (!android::base::WriteStringToFile(output, mOutputFileName, true)) { @@ -82,4 +97,11 @@ status_t SurfaceTracing::writeProtoFileLocked() { return NO_ERROR; } +void SurfaceTracing::dump(String8& result) const { + std::lock_guard<std::mutex> protoGuard(mTraceMutex); + + result.appendFormat("Tracing state: %s\n", mEnabled ? "enabled" : "disabled"); + result.appendFormat(" number of entries: %d\n", mTrace ? mTrace->entry_size() : 0); +} + } // namespace android diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h index 590ab9680f..fd8cb82a9b 100644 --- a/services/surfaceflinger/SurfaceTracing.h +++ b/services/surfaceflinger/SurfaceTracing.h @@ -18,7 +18,9 @@ #include <layerproto/LayerProtoHeader.h> #include <utils/Errors.h> +#include <utils/String8.h> +#include <memory> #include <mutex> using namespace android::surfaceflinger; @@ -32,9 +34,10 @@ class SurfaceTracing { public: void enable(); status_t disable(); - bool isEnabled(); + bool isEnabled() const; void traceLayers(const char* where, LayersProto); + void dump(String8& result) const; private: static constexpr auto DEFAULT_FILENAME = "/data/misc/wmtrace/layers_trace.pb"; @@ -43,8 +46,8 @@ private: bool mEnabled = false; std::string mOutputFileName = DEFAULT_FILENAME; - std::mutex mTraceMutex; - LayersTraceFileProto mTrace; + mutable std::mutex mTraceMutex; + std::unique_ptr<LayersTraceFileProto> mTrace; }; } // namespace android |