diff options
34 files changed, 580 insertions, 336 deletions
diff --git a/include/input/InputConsumerNoResampling.h b/include/input/InputConsumerNoResampling.h index 9e48b0872d..c7b1970149 100644 --- a/include/input/InputConsumerNoResampling.h +++ b/include/input/InputConsumerNoResampling.h @@ -24,7 +24,7 @@ namespace android { /** * An interface to receive batched input events. Even if you don't want batching, you still have to * use this interface, and some of the events will be batched if your implementation is slow to - * handle the incoming input. + * handle the incoming input. The events received by these callbacks are never null. */ class InputConsumerCallbacks { public: diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index 6185b7baf8..c57c9cdd62 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -441,14 +441,6 @@ status_t BBinder::unlinkToDeath( return INVALID_OPERATION; } -status_t BBinder::addFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>&) { - return INVALID_OPERATION; -} - -status_t BBinder::removeFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>&) { - return INVALID_OPERATION; -} - status_t BBinder::dump(int /*fd*/, const Vector<String16>& /*args*/) { return NO_ERROR; diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 59c5be75ac..6594aa6309 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -557,14 +557,6 @@ void BpBinder::sendObituary() } } -status_t BpBinder::addFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>&) { - return INVALID_OPERATION; -} - -status_t BpBinder::removeFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>&) { - return INVALID_OPERATION; -} - void BpBinder::reportOneDeath(const Obituary& obit) { sp<DeathRecipient> recipient = obit.recipient.promote(); diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 3f70e8c104..e8fe555ab3 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -1585,10 +1585,15 @@ status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership) { fdVariant = borrowed_fd(fd); } if (!mAllowFds) { + ALOGE("FDs are not allowed in this parcel. Both the service and the client must set " + "the FileDescriptorTransportMode and agree on the support."); return FDS_NOT_ALLOWED; } switch (rpcFields->mSession->getFileDescriptorTransportMode()) { case RpcSession::FileDescriptorTransportMode::NONE: { + ALOGE("FDs are not allowed in this RpcSession. Both the service and the client " + "must set " + "the FileDescriptorTransportMode and agree on the support."); return FDS_NOT_ALLOWED; } case RpcSession::FileDescriptorTransportMode::UNIX: diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h index 802a3bcd06..135be89c6c 100644 --- a/libs/binder/include/binder/Binder.h +++ b/libs/binder/include/binder/Binder.h @@ -50,13 +50,6 @@ public: void* cookie = nullptr, uint32_t flags = 0, wp<DeathRecipient>* outRecipient = nullptr); - // Placeholders to test if adding virtual functions here breaks things. - // Will be replaced by an actual API once things are verified to work. - LIBBINDER_EXPORTED virtual status_t addFrozenStateChangeCallback( - const wp<FrozenStateChangeCallback>& callback); - LIBBINDER_EXPORTED virtual status_t removeFrozenStateChangeCallback( - const wp<FrozenStateChangeCallback>& callback); - LIBBINDER_EXPORTED virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie, object_cleanup_func func) final; diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h index 0f52f6df52..d7f74c4152 100644 --- a/libs/binder/include/binder/BpBinder.h +++ b/libs/binder/include/binder/BpBinder.h @@ -66,12 +66,6 @@ public: void* cookie = nullptr, uint32_t flags = 0, wp<DeathRecipient>* outRecipient = nullptr); - [[nodiscard]] virtual status_t addFrozenStateChangeCallback( - const wp<FrozenStateChangeCallback>& recipient); - - [[nodiscard]] virtual status_t removeFrozenStateChangeCallback( - const wp<FrozenStateChangeCallback>& recipient); - LIBBINDER_EXPORTED virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie, object_cleanup_func func) final; diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h index 62d7354387..4eb1c082e2 100644 --- a/libs/binder/include/binder/IBinder.h +++ b/libs/binder/include/binder/IBinder.h @@ -102,6 +102,10 @@ public: */ virtual const String16& getInterfaceDescriptor() const = 0; + /** + * Last known alive status, from last call. May be arbitrarily stale. + * May be incorrect if a service returns an incorrect status code. + */ virtual bool isBinderAlive() const = 0; virtual status_t pingBinder() = 0; virtual status_t dump(int fd, const Vector<String16>& args) = 0; @@ -198,14 +202,9 @@ public: virtual void binderDied(const wp<IBinder>& who) = 0; }; - class FrozenStateChangeCallback : public virtual RefBase { - public: - virtual void onStateChanged(const wp<IBinder>& who, bool isFrozen) = 0; - }; - -#if defined(__clang__) -#pragma clang diagnostic pop -#endif + #if defined(__clang__) + #pragma clang diagnostic pop + #endif /** * Register the @a recipient for a notification if this binder @@ -254,12 +253,6 @@ public: uint32_t flags = 0, wp<DeathRecipient>* outRecipient = nullptr) = 0; - // Placeholders. See Binder.h for details. - [[nodiscard]] virtual status_t addFrozenStateChangeCallback( - const wp<FrozenStateChangeCallback>& callback) = 0; - [[nodiscard]] virtual status_t removeFrozenStateChangeCallback( - const wp<FrozenStateChangeCallback>& callback) = 0; - virtual bool checkSubclass(const void* subclassID) const; typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie); diff --git a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h index cf7dc1a510..bfba79ffc0 100644 --- a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h +++ b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h @@ -264,7 +264,7 @@ class PersistableBundle { } } - bool getBoolean(const std::string& key, bool* _Nonnull val) { + bool getBoolean(const std::string& key, bool* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return APersistableBundle_getBoolean(mPBundle, key.c_str(), val); } else { @@ -272,7 +272,7 @@ class PersistableBundle { } } - bool getInt(const std::string& key, int32_t* _Nonnull val) { + bool getInt(const std::string& key, int32_t* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return APersistableBundle_getInt(mPBundle, key.c_str(), val); } else { @@ -280,7 +280,7 @@ class PersistableBundle { } } - bool getLong(const std::string& key, int64_t* _Nonnull val) { + bool getLong(const std::string& key, int64_t* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return APersistableBundle_getLong(mPBundle, key.c_str(), val); } else { @@ -288,7 +288,7 @@ class PersistableBundle { } } - bool getDouble(const std::string& key, double* _Nonnull val) { + bool getDouble(const std::string& key, double* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return APersistableBundle_getDouble(mPBundle, key.c_str(), val); } else { @@ -300,7 +300,7 @@ class PersistableBundle { return (char*)malloc(bufferSizeBytes); } - bool getString(const std::string& key, std::string* _Nonnull val) { + bool getString(const std::string& key, std::string* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { char* outString = nullptr; bool ret = APersistableBundle_getString(mPBundle, key.c_str(), &outString, @@ -318,7 +318,7 @@ class PersistableBundle { bool getVecInternal(int32_t (*_Nonnull getVec)(const APersistableBundle* _Nonnull, const char* _Nonnull, T* _Nullable, int32_t), const APersistableBundle* _Nonnull pBundle, const char* _Nonnull key, - std::vector<T>* _Nonnull vec) { + std::vector<T>* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { int32_t bytes = 0; // call first with nullptr to get required size in bytes @@ -340,28 +340,28 @@ class PersistableBundle { return false; } - bool getBooleanVector(const std::string& key, std::vector<bool>* _Nonnull vec) { + bool getBooleanVector(const std::string& key, std::vector<bool>* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getVecInternal<bool>(&APersistableBundle_getBooleanVector, mPBundle, key.c_str(), vec); } return false; } - bool getIntVector(const std::string& key, std::vector<int32_t>* _Nonnull vec) { + bool getIntVector(const std::string& key, std::vector<int32_t>* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getVecInternal<int32_t>(&APersistableBundle_getIntVector, mPBundle, key.c_str(), vec); } return false; } - bool getLongVector(const std::string& key, std::vector<int64_t>* _Nonnull vec) { + bool getLongVector(const std::string& key, std::vector<int64_t>* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getVecInternal<int64_t>(&APersistableBundle_getLongVector, mPBundle, key.c_str(), vec); } return false; } - bool getDoubleVector(const std::string& key, std::vector<double>* _Nonnull vec) { + bool getDoubleVector(const std::string& key, std::vector<double>* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getVecInternal<double>(&APersistableBundle_getDoubleVector, mPBundle, key.c_str(), vec); @@ -372,7 +372,7 @@ class PersistableBundle { // Takes ownership of and frees the char** and its elements. // Creates a new set or vector based on the array of char*. template <typename T> - T moveStringsInternal(char* _Nullable* _Nonnull strings, int32_t bufferSizeBytes) { + T moveStringsInternal(char* _Nullable* _Nonnull strings, int32_t bufferSizeBytes) const { if (strings && bufferSizeBytes > 0) { int32_t num = bufferSizeBytes / sizeof(char*); T ret; @@ -386,7 +386,7 @@ class PersistableBundle { return T(); } - bool getStringVector(const std::string& key, std::vector<std::string>* _Nonnull vec) { + bool getStringVector(const std::string& key, std::vector<std::string>* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { int32_t bytes = APersistableBundle_getStringVector(mPBundle, key.c_str(), nullptr, 0, &stringAllocator, nullptr); @@ -403,7 +403,7 @@ class PersistableBundle { return false; } - bool getPersistableBundle(const std::string& key, PersistableBundle* _Nonnull val) { + bool getPersistableBundle(const std::string& key, PersistableBundle* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { APersistableBundle* bundle = nullptr; bool ret = APersistableBundle_getPersistableBundle(mPBundle, key.c_str(), &bundle); @@ -422,7 +422,7 @@ class PersistableBundle { int32_t bufferSizeBytes, APersistableBundle_stringAllocator stringAllocator, void* _Nullable), - const APersistableBundle* _Nonnull pBundle) { + const APersistableBundle* _Nonnull pBundle) const { // call first with nullptr to get required size in bytes int32_t bytes = getTypedKeys(pBundle, nullptr, 0, &stringAllocator, nullptr); if (bytes > 0) { @@ -435,84 +435,84 @@ class PersistableBundle { return {}; } - std::set<std::string> getBooleanKeys() { + std::set<std::string> getBooleanKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getBooleanKeys, mPBundle); } else { return {}; } } - std::set<std::string> getIntKeys() { + std::set<std::string> getIntKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getIntKeys, mPBundle); } else { return {}; } } - std::set<std::string> getLongKeys() { + std::set<std::string> getLongKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getLongKeys, mPBundle); } else { return {}; } } - std::set<std::string> getDoubleKeys() { + std::set<std::string> getDoubleKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getDoubleKeys, mPBundle); } else { return {}; } } - std::set<std::string> getStringKeys() { + std::set<std::string> getStringKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getStringKeys, mPBundle); } else { return {}; } } - std::set<std::string> getBooleanVectorKeys() { + std::set<std::string> getBooleanVectorKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getBooleanVectorKeys, mPBundle); } else { return {}; } } - std::set<std::string> getIntVectorKeys() { + std::set<std::string> getIntVectorKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getIntVectorKeys, mPBundle); } else { return {}; } } - std::set<std::string> getLongVectorKeys() { + std::set<std::string> getLongVectorKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getLongVectorKeys, mPBundle); } else { return {}; } } - std::set<std::string> getDoubleVectorKeys() { + std::set<std::string> getDoubleVectorKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getDoubleVectorKeys, mPBundle); } else { return {}; } } - std::set<std::string> getStringVectorKeys() { + std::set<std::string> getStringVectorKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getStringVectorKeys, mPBundle); } else { return {}; } } - std::set<std::string> getPersistableBundleKeys() { + std::set<std::string> getPersistableBundleKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getPersistableBundleKeys, mPBundle); } else { return {}; } } - std::set<std::string> getMonKeys() { + std::set<std::string> getMonKeys() const { // :P return {"c(o,o)b", "c(o,o)b"}; } diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig index a2192cbdc4..96f8b0518f 100644 --- a/libs/input/input_flags.aconfig +++ b/libs/input/input_flags.aconfig @@ -15,13 +15,6 @@ flag { bug: "271455682" } -flag { - name: "enable_gestures_library_timer_provider" - namespace: "input" - description: "Set to true to enable timer support for the touchpad Gestures library" - bug: "297192727" - } - flag { name: "enable_input_event_tracing" namespace: "input" diff --git a/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp b/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp index f49469ccca..e7106135fd 100644 --- a/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp @@ -52,7 +52,7 @@ struct PublishMotionArgs { const int32_t action; const nsecs_t downTime; const uint32_t seq; - const int32_t eventId; + int32_t eventId; const int32_t deviceId = 1; const uint32_t source = AINPUT_SOURCE_TOUCHSCREEN; const ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT; @@ -291,6 +291,7 @@ protected: void publishAndConsumeKeyEvent(); void publishAndConsumeMotionStream(); void publishAndConsumeMotionDown(nsecs_t downTime); + void publishAndConsumeSinglePointerMultipleSamples(const size_t nSamples); void publishAndConsumeBatchedMotionMove(nsecs_t downTime); void publishAndConsumeFocusEvent(); void publishAndConsumeCaptureEvent(); @@ -298,6 +299,7 @@ protected: void publishAndConsumeTouchModeEvent(); void publishAndConsumeMotionEvent(int32_t action, nsecs_t downTime, const std::vector<Pointer>& pointers); + void TearDown() override { // Destroy the consumer, flushing any of the pending ack's. sendMessage(LooperMessage::DESTROY_CONSUMER); @@ -519,6 +521,123 @@ void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionDown(nsec {Pointer{.id = 0, .x = 20, .y = 30}}); } +/* + * Decompose a potential multi-sampled MotionEvent into multiple MotionEvents + * with a single sample. + */ +std::vector<MotionEvent> splitBatchedMotionEvent(const MotionEvent& batchedMotionEvent) { + std::vector<MotionEvent> singleMotionEvents; + const size_t batchSize = batchedMotionEvent.getHistorySize() + 1; + for (size_t i = 0; i < batchSize; ++i) { + MotionEvent singleMotionEvent; + singleMotionEvent + .initialize(batchedMotionEvent.getId(), batchedMotionEvent.getDeviceId(), + batchedMotionEvent.getSource(), batchedMotionEvent.getDisplayId(), + batchedMotionEvent.getHmac(), batchedMotionEvent.getAction(), + batchedMotionEvent.getActionButton(), batchedMotionEvent.getFlags(), + batchedMotionEvent.getEdgeFlags(), batchedMotionEvent.getMetaState(), + batchedMotionEvent.getButtonState(), + batchedMotionEvent.getClassification(), + batchedMotionEvent.getTransform(), batchedMotionEvent.getXPrecision(), + batchedMotionEvent.getYPrecision(), + batchedMotionEvent.getRawXCursorPosition(), + batchedMotionEvent.getRawYCursorPosition(), + batchedMotionEvent.getRawTransform(), batchedMotionEvent.getDownTime(), + batchedMotionEvent.getHistoricalEventTime(/*historicalIndex=*/i), + batchedMotionEvent.getPointerCount(), + batchedMotionEvent.getPointerProperties(), + (batchedMotionEvent.getSamplePointerCoords() + i)); + singleMotionEvents.push_back(singleMotionEvent); + } + return singleMotionEvents; +} + +/* + * Simulates a single pointer touching the screen and leaving it there for a period of time. + * Publishes a DOWN event and consumes it right away. Then, publishes a sequence of MOVE + * samples for the same pointer, and waits until it has been consumed. Splits batched MotionEvents + * into individual samples. Checks the consumed MotionEvents against the published ones. + * This test is non-deterministic because it depends on the timing of arrival of events to the + * socket. + * + * @param nSamples The number of MOVE samples to publish before attempting consumption. + */ +void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeSinglePointerMultipleSamples( + const size_t nSamples) { + const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC); + const Pointer pointer(0, 20, 30); + + const PublishMotionArgs argsDown(AMOTION_EVENT_ACTION_DOWN, downTime, {pointer}, mSeq); + const nsecs_t publishTimeOfDown = systemTime(SYSTEM_TIME_MONOTONIC); + publishMotionEvent(*mPublisher, argsDown); + + // Consume the DOWN event. + ASSERT_TRUE(mMotionEvents.popWithTimeout(TIMEOUT).has_value()); + + verifyFinishedSignal(*mPublisher, mSeq, publishTimeOfDown); + + std::vector<nsecs_t> publishTimes; + std::vector<PublishMotionArgs> argsMoves; + std::queue<uint32_t> publishedSequenceNumbers; + + // Block Looper to increase the chance of batching events + { + std::scoped_lock l(mLock); + mLooperMayProceed = false; + } + sendMessage(LooperMessage::BLOCK_LOOPER); + { + std::unique_lock l(mLock); + mNotifyLooperWaiting.wait(l, [this] { return mLooperIsBlocked; }); + } + + uint32_t firstSampleId; + for (size_t i = 0; i < nSamples; ++i) { + publishedSequenceNumbers.push(++mSeq); + PublishMotionArgs argsMove(AMOTION_EVENT_ACTION_MOVE, downTime, {pointer}, mSeq); + // A batched MotionEvent only has a single event id, currently determined when the + // MotionEvent is initialized. Therefore, to pass the eventId comparisons inside + // verifyArgsEqualToEvent, we need to override the event id of the published args to match + // the event id of the first sample inside the MotionEvent. + if (i == 0) { + firstSampleId = argsMove.eventId; + } + argsMove.eventId = firstSampleId; + publishTimes.push_back(systemTime(SYSTEM_TIME_MONOTONIC)); + argsMoves.push_back(argsMove); + publishMotionEvent(*mPublisher, argsMove); + } + + std::vector<MotionEvent> singleSampledMotionEvents; + + // Unblock Looper + { + std::scoped_lock l(mLock); + mLooperMayProceed = true; + } + mNotifyLooperMayProceed.notify_all(); + + // We have no control over the socket behavior, so the consumer can receive + // the motion as a batched event, or as a sequence of multiple single-sample MotionEvents (or a + // mix of those) + while (singleSampledMotionEvents.size() != nSamples) { + const std::optional<std::unique_ptr<MotionEvent>> batchedMotionEvent = + mMotionEvents.popWithTimeout(TIMEOUT); + // The events received by these calls are never null + std::vector<MotionEvent> splitMotionEvents = splitBatchedMotionEvent(**batchedMotionEvent); + singleSampledMotionEvents.insert(singleSampledMotionEvents.end(), splitMotionEvents.begin(), + splitMotionEvents.end()); + } + + // Consumer can choose to finish events in any order. For simplicity, + // we verify the events in sequence (since that is how the test is implemented). + for (size_t i = 0; i < nSamples; ++i) { + verifyArgsEqualToEvent(argsMoves[i], singleSampledMotionEvents[i]); + verifyFinishedSignal(*mPublisher, publishedSequenceNumbers.front(), publishTimes[i]); + publishedSequenceNumbers.pop(); + } +} + void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeBatchedMotionMove( nsecs_t downTime) { uint32_t seq = mSeq++; @@ -814,4 +933,8 @@ TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMultipleEvents_EndToEnd ASSERT_NO_FATAL_FAILURE(publishAndConsumeTouchModeEvent()); } +TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishAndConsumeSinglePointer) { + publishAndConsumeSinglePointerMultipleSamples(3); +} + } // namespace android diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp index 52612870ab..dd78049b16 100644 --- a/libs/nativewindow/AHardwareBuffer.cpp +++ b/libs/nativewindow/AHardwareBuffer.cpp @@ -300,7 +300,9 @@ int AHardwareBuffer_lockPlanes(AHardwareBuffer* buffer, uint64_t usage, if (result == 0) { outPlanes->planeCount = 3; outPlanes->planes[0].data = yuvData.y; - if (format == AHARDWAREBUFFER_FORMAT_YCbCr_P010) { + // P010 is word-aligned 10-bit semiplaner, and YCbCr_422_I is a single interleaved plane + if (format == AHARDWAREBUFFER_FORMAT_YCbCr_P010 || + format == AHARDWAREBUFFER_FORMAT_YCbCr_422_I) { outPlanes->planes[0].pixelStride = 2; } else { outPlanes->planes[0].pixelStride = 1; diff --git a/libs/tracing_perfetto/Android.bp b/libs/tracing_perfetto/Android.bp index 3a4c869e46..b5c56c5c52 100644 --- a/libs/tracing_perfetto/Android.bp +++ b/libs/tracing_perfetto/Android.bp @@ -40,6 +40,7 @@ cc_library_shared { ], shared_libs: [ + "libbase", "libcutils", "libperfetto_c", "android.os.flags-aconfig-cc-host", diff --git a/libs/tracing_perfetto/include/trace_result.h b/libs/tracing_perfetto/include/trace_result.h deleted file mode 100644 index f7581fc0fb..0000000000 --- a/libs/tracing_perfetto/include/trace_result.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2024 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. - */ - -#ifndef TRACE_RESULT_H -#define TRACE_RESULT_H - -namespace tracing_perfetto { - -enum class Result { - SUCCESS, - NOT_SUPPORTED, - INVALID_INPUT, -}; - -} - -#endif // TRACE_RESULT_H diff --git a/libs/tracing_perfetto/include/tracing_perfetto.h b/libs/tracing_perfetto/include/tracing_perfetto.h index 2c1c2a49e7..0b2b0af59d 100644 --- a/libs/tracing_perfetto/include/tracing_perfetto.h +++ b/libs/tracing_perfetto/include/tracing_perfetto.h @@ -19,35 +19,32 @@ #include <stdint.h> -#include "trace_result.h" - namespace tracing_perfetto { void registerWithPerfetto(bool test = false); -Result traceBegin(uint64_t category, const char* name); +void traceBegin(uint64_t category, const char* name); -Result traceEnd(uint64_t category); +void traceEnd(uint64_t category); -Result traceAsyncBegin(uint64_t category, const char* name, int32_t cookie); +void traceAsyncBegin(uint64_t category, const char* name, int32_t cookie); -Result traceAsyncEnd(uint64_t category, const char* name, int32_t cookie); +void traceAsyncEnd(uint64_t category, const char* name, int32_t cookie); -Result traceAsyncBeginForTrack(uint64_t category, const char* name, +void traceAsyncBeginForTrack(uint64_t category, const char* name, const char* trackName, int32_t cookie); -Result traceAsyncEndForTrack(uint64_t category, const char* trackName, +void traceAsyncEndForTrack(uint64_t category, const char* trackName, int32_t cookie); -Result traceInstant(uint64_t category, const char* name); +void traceInstant(uint64_t category, const char* name); -Result traceInstantForTrack(uint64_t category, const char* trackName, +void traceInstantForTrack(uint64_t category, const char* trackName, const char* name); -Result traceCounter(uint64_t category, const char* name, int64_t value); +void traceCounter(uint64_t category, const char* name, int64_t value); bool isTagEnabled(uint64_t category); - } // namespace tracing_perfetto #endif // TRACING_PERFETTO_H diff --git a/libs/tracing_perfetto/tests/Android.bp b/libs/tracing_perfetto/tests/Android.bp index a35b0e0c83..d203467783 100644 --- a/libs/tracing_perfetto/tests/Android.bp +++ b/libs/tracing_perfetto/tests/Android.bp @@ -26,6 +26,7 @@ cc_test { static_libs: [ "libflagtest", "libgmock", + "perfetto_trace_protos", ], cflags: [ "-Wall", @@ -35,6 +36,8 @@ cc_test { "android.os.flags-aconfig-cc-host", "libbase", "libperfetto_c", + "liblog", + "libprotobuf-cpp-lite", "libtracing_perfetto", ], srcs: [ diff --git a/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp b/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp index 7716b9a316..e9fee2e6cf 100644 --- a/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp +++ b/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp @@ -16,10 +16,10 @@ #include "tracing_perfetto.h" -#include <thread> - #include <android_os.h> #include <flag_macros.h> +#include <thread> +#include <unistd.h> #include "gtest/gtest.h" #include "perfetto/public/abi/data_source_abi.h" @@ -45,67 +45,182 @@ #include "trace_categories.h" #include "utils.h" +#include "protos/perfetto/trace/trace.pb.h" +#include "protos/perfetto/trace/trace_packet.pb.h" +#include "protos/perfetto/trace/interned_data/interned_data.pb.h" + +#include <fstream> +#include <iterator> namespace tracing_perfetto { -using ::perfetto::shlib::test_utils::AllFieldsWithId; -using ::perfetto::shlib::test_utils::FieldView; -using ::perfetto::shlib::test_utils::IdFieldView; -using ::perfetto::shlib::test_utils::MsgField; -using ::perfetto::shlib::test_utils::PbField; -using ::perfetto::shlib::test_utils::StringField; +using ::perfetto::protos::Trace; +using ::perfetto::protos::TracePacket; +using ::perfetto::protos::EventCategory; +using ::perfetto::protos::EventName; +using ::perfetto::protos::FtraceEvent; +using ::perfetto::protos::FtraceEventBundle; +using ::perfetto::protos::InternedData; + using ::perfetto::shlib::test_utils::TracingSession; -using ::perfetto::shlib::test_utils::VarIntField; -using ::testing::_; -using ::testing::ElementsAre; -using ::testing::UnorderedElementsAre; const auto PERFETTO_SDK_TRACING = ACONFIG_FLAG(android::os, perfetto_sdk_tracing); +// TODO(b/303199244): Add tests for all the library functions. class TracingPerfettoTest : public testing::Test { protected: void SetUp() override { - tracing_perfetto::registerWithPerfetto(true /* test */); + tracing_perfetto::registerWithPerfetto(false /* test */); } }; -// TODO(b/303199244): Add tests for all the library functions. - -TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstant, - REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) { - TracingSession tracing_session = - TracingSession::Builder().set_data_source_name("track_event").Build(); - tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, ""); - +Trace stopSession(TracingSession& tracing_session) { + tracing_session.FlushBlocking(5000); tracing_session.StopBlocking(); std::vector<uint8_t> data = tracing_session.ReadBlocking(); + std::string data_string(data.begin(), data.end()); + + perfetto::protos::Trace trace; + trace.ParseFromString(data_string); + + return trace; +} + +void verifyTrackEvent(const Trace& trace, const std::string expected_category, + const std::string& expected_name) { bool found = false; - for (struct PerfettoPbDecoderField trace_field : FieldView(data)) { - ASSERT_THAT(trace_field, PbField(perfetto_protos_Trace_packet_field_number, - MsgField(_))); - IdFieldView track_event( - trace_field, perfetto_protos_TracePacket_track_event_field_number); - if (track_event.size() == 0) { - continue; + for (const TracePacket& packet: trace.packet()) { + if (packet.has_track_event() && packet.has_interned_data()) { + + const InternedData& interned_data = packet.interned_data(); + if (interned_data.event_categories_size() > 0) { + const EventCategory& event_category = packet.interned_data().event_categories(0); + if (event_category.name() == expected_category) { + found = true; + } + } + + if (interned_data.event_names_size() > 0) { + const EventName& event_name = packet.interned_data().event_names(0); + if (event_name.name() == expected_name) { + found &= true; + } + } + + if (found) { + break; + } + } + } + EXPECT_TRUE(found); +} + +void verifyAtraceEvent(const Trace& trace, const std::string& expected_name) { + std::string expected_print_buf = "I|" + std::to_string(gettid()) + "|" + expected_name + "\n"; + + bool found = false; + for (const TracePacket& packet: trace.packet()) { + if (packet.has_ftrace_events()) { + const FtraceEventBundle& ftrace_events_bundle = packet.ftrace_events(); + + if (ftrace_events_bundle.event_size() > 0) { + const FtraceEvent& ftrace_event = ftrace_events_bundle.event(0); + if (ftrace_event.has_print() && (ftrace_event.print().buf() == expected_print_buf)) { + found = true; + break; + } + } } - found = true; - IdFieldView cat_iid_fields( - track_event.front(), - perfetto_protos_TrackEvent_category_iids_field_number); - ASSERT_THAT(cat_iid_fields, ElementsAre(VarIntField(_))); - uint64_t cat_iid = cat_iid_fields.front().value.integer64; - EXPECT_THAT( - trace_field, - AllFieldsWithId( - perfetto_protos_TracePacket_interned_data_field_number, - ElementsAre(AllFieldsWithId( - perfetto_protos_InternedData_event_categories_field_number, - ElementsAre(MsgField(UnorderedElementsAre( - PbField(perfetto_protos_EventCategory_iid_field_number, - VarIntField(cat_iid)), - PbField(perfetto_protos_EventCategory_name_field_number, - StringField("input"))))))))); } EXPECT_TRUE(found); } -} // namespace tracing_perfetto
\ No newline at end of file +TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfetto, + REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) { + std::string event_category = "input"; + std::string event_name = "traceInstantWithPerfetto"; + + TracingSession tracing_session = + TracingSession::Builder().add_enabled_category(event_category).Build(); + + tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str()); + + Trace trace = stopSession(tracing_session); + + verifyTrackEvent(trace, event_category, event_name); +} + +TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithAtrace, + REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) { + std::string event_category = "input"; + std::string event_name = "traceInstantWithAtrace"; + + TracingSession tracing_session = + TracingSession::Builder().add_atrace_category(event_category).Build(); + + tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str()); + + Trace trace = stopSession(tracing_session); + + verifyAtraceEvent(trace, event_name); +} + +TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfettoAndAtrace, + REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) { + std::string event_category = "input"; + std::string event_name = "traceInstantWithPerfettoAndAtrace"; + + TracingSession tracing_session = + TracingSession::Builder() + .add_atrace_category(event_category) + .add_enabled_category(event_category).Build(); + + tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str()); + + Trace trace = stopSession(tracing_session); + + verifyAtraceEvent(trace, event_name); +} + +TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfettoAndAtraceAndPreferTrackEvent, + REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) { + std::string event_category = "input"; + std::string event_name = "traceInstantWithPerfettoAndAtraceAndPreferTrackEvent"; + + TracingSession tracing_session = + TracingSession::Builder() + .add_atrace_category(event_category) + .add_atrace_category_prefer_sdk(event_category) + .add_enabled_category(event_category).Build(); + + tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str()); + + Trace trace = stopSession(tracing_session); + + verifyTrackEvent(trace, event_category, event_name); +} + +TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfettoAndAtraceConcurrently, + REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) { + std::string event_category = "input"; + std::string event_name = "traceInstantWithPerfettoAndAtraceConcurrently"; + + TracingSession perfetto_tracing_session = + TracingSession::Builder() + .add_atrace_category(event_category) + .add_atrace_category_prefer_sdk(event_category) + .add_enabled_category(event_category).Build(); + + TracingSession atrace_tracing_session = + TracingSession::Builder() + .add_atrace_category(event_category) + .add_enabled_category(event_category).Build(); + + tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str()); + + Trace atrace_trace = stopSession(atrace_tracing_session); + Trace perfetto_trace = stopSession(perfetto_tracing_session); + + verifyAtraceEvent(atrace_trace, event_name); + verifyAtraceEvent(perfetto_trace, event_name); +} +} // namespace tracing_perfetto diff --git a/libs/tracing_perfetto/tests/utils.cpp b/libs/tracing_perfetto/tests/utils.cpp index 9c4202808a..8c4d4a8925 100644 --- a/libs/tracing_perfetto/tests/utils.cpp +++ b/libs/tracing_perfetto/tests/utils.cpp @@ -26,6 +26,11 @@ #include "perfetto/public/protos/config/track_event/track_event_config.pzc.h" #include "perfetto/public/tracing_session.h" +#include "protos/perfetto/config/ftrace/ftrace_config.pb.h" +#include "protos/perfetto/config/track_event/track_event_config.pb.h" +#include "protos/perfetto/config/data_source_config.pb.h" +#include "protos/perfetto/config/trace_config.pb.h" + namespace perfetto { namespace shlib { namespace test_utils { @@ -44,63 +49,54 @@ std::string ToHexChars(uint8_t val) { } // namespace TracingSession TracingSession::Builder::Build() { - struct PerfettoPbMsgWriter writer; - struct PerfettoHeapBuffer* hb = PerfettoHeapBufferCreate(&writer.writer); + perfetto::protos::TraceConfig trace_config; + trace_config.add_buffers()->set_size_kb(1024); - struct perfetto_protos_TraceConfig cfg; - PerfettoPbMsgInit(&cfg.msg, &writer); + auto* track_event_ds_config = trace_config.add_data_sources()->mutable_config(); + auto* ftrace_ds_config = trace_config.add_data_sources()->mutable_config(); - { - struct perfetto_protos_TraceConfig_BufferConfig buffers; - perfetto_protos_TraceConfig_begin_buffers(&cfg, &buffers); + track_event_ds_config->set_name("track_event"); + track_event_ds_config->set_target_buffer(0); + + ftrace_ds_config->set_name("linux.ftrace"); + ftrace_ds_config->set_target_buffer(0); - perfetto_protos_TraceConfig_BufferConfig_set_size_kb(&buffers, 1024); + { + auto* ftrace_config = ftrace_ds_config->mutable_ftrace_config(); + if (!atrace_categories_.empty()) { + ftrace_config->add_ftrace_events("ftrace/print"); + for (const std::string& cat : atrace_categories_) { + ftrace_config->add_atrace_categories(cat); + } - perfetto_protos_TraceConfig_end_buffers(&cfg, &buffers); + for (const std::string& cat : atrace_categories_prefer_sdk_) { + ftrace_config->add_atrace_categories_prefer_sdk(cat); + } + } } { - struct perfetto_protos_TraceConfig_DataSource data_sources; - perfetto_protos_TraceConfig_begin_data_sources(&cfg, &data_sources); - - { - struct perfetto_protos_DataSourceConfig ds_cfg; - perfetto_protos_TraceConfig_DataSource_begin_config(&data_sources, - &ds_cfg); - - perfetto_protos_DataSourceConfig_set_cstr_name(&ds_cfg, - data_source_name_.c_str()); - if (!enabled_categories_.empty() && !disabled_categories_.empty()) { - perfetto_protos_TrackEventConfig te_cfg; - perfetto_protos_DataSourceConfig_begin_track_event_config(&ds_cfg, - &te_cfg); - for (const std::string& cat : enabled_categories_) { - perfetto_protos_TrackEventConfig_set_enabled_categories( - &te_cfg, cat.data(), cat.size()); - } - for (const std::string& cat : disabled_categories_) { - perfetto_protos_TrackEventConfig_set_disabled_categories( - &te_cfg, cat.data(), cat.size()); - } - perfetto_protos_DataSourceConfig_end_track_event_config(&ds_cfg, - &te_cfg); + auto* track_event_config = track_event_ds_config->mutable_track_event_config(); + if (!enabled_categories_.empty() || !disabled_categories_.empty()) { + for (const std::string& cat : enabled_categories_) { + track_event_config->add_enabled_categories(cat); } - perfetto_protos_TraceConfig_DataSource_end_config(&data_sources, &ds_cfg); + for (const std::string& cat : disabled_categories_) { + track_event_config->add_disabled_categories(cat); + } } - - perfetto_protos_TraceConfig_end_data_sources(&cfg, &data_sources); } - size_t cfg_size = PerfettoStreamWriterGetWrittenSize(&writer.writer); - std::unique_ptr<uint8_t[]> ser(new uint8_t[cfg_size]); - PerfettoHeapBufferCopyInto(hb, &writer.writer, ser.get(), cfg_size); - PerfettoHeapBufferDestroy(hb, &writer.writer); struct PerfettoTracingSessionImpl* ts = - PerfettoTracingSessionCreate(PERFETTO_BACKEND_IN_PROCESS); + PerfettoTracingSessionCreate(PERFETTO_BACKEND_SYSTEM); + + std::string trace_config_string; + trace_config.SerializeToString(&trace_config_string); - PerfettoTracingSessionSetup(ts, ser.get(), cfg_size); + PerfettoTracingSessionSetup(ts, trace_config_string.data(), trace_config_string.length()); + // Fails to start here PerfettoTracingSessionStartBlocking(ts); return TracingSession::Adopt(ts); diff --git a/libs/tracing_perfetto/tests/utils.h b/libs/tracing_perfetto/tests/utils.h index 4353554963..8edb4143ee 100644 --- a/libs/tracing_perfetto/tests/utils.h +++ b/libs/tracing_perfetto/tests/utils.h @@ -74,10 +74,6 @@ class TracingSession { class Builder { public: Builder() = default; - Builder& set_data_source_name(std::string data_source_name) { - data_source_name_ = std::move(data_source_name); - return *this; - } Builder& add_enabled_category(std::string category) { enabled_categories_.push_back(std::move(category)); return *this; @@ -86,12 +82,21 @@ class TracingSession { disabled_categories_.push_back(std::move(category)); return *this; } + Builder& add_atrace_category(std::string category) { + atrace_categories_.push_back(std::move(category)); + return *this; + } + Builder& add_atrace_category_prefer_sdk(std::string category) { + atrace_categories_prefer_sdk_.push_back(std::move(category)); + return *this; + } TracingSession Build(); private: - std::string data_source_name_; std::vector<std::string> enabled_categories_; std::vector<std::string> disabled_categories_; + std::vector<std::string> atrace_categories_; + std::vector<std::string> atrace_categories_prefer_sdk_; }; static TracingSession Adopt(struct PerfettoTracingSessionImpl*); diff --git a/libs/tracing_perfetto/tracing_perfetto.cpp b/libs/tracing_perfetto/tracing_perfetto.cpp index 6f716eea9a..fc5336de68 100644 --- a/libs/tracing_perfetto/tracing_perfetto.cpp +++ b/libs/tracing_perfetto/tracing_perfetto.cpp @@ -28,116 +28,112 @@ void registerWithPerfetto(bool test) { internal::registerWithPerfetto(test); } -Result traceBegin(uint64_t category, const char* name) { +void traceBegin(uint64_t category, const char* name) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - if (perfettoTeCategory != nullptr) { - return internal::perfettoTraceBegin(*perfettoTeCategory, name); - } else { + + if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_begin(category, name); - return Result::SUCCESS; + } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { + internal::perfettoTraceBegin(*perfettoTeCategory, name); } } -Result traceEnd(uint64_t category) { +void traceEnd(uint64_t category) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - if (perfettoTeCategory != nullptr) { - return internal::perfettoTraceEnd(*perfettoTeCategory); - } else { + + if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_end(category); - return Result::SUCCESS; + } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { + internal::perfettoTraceEnd(*perfettoTeCategory); } } -Result traceAsyncBegin(uint64_t category, const char* name, int32_t cookie) { +void traceAsyncBegin(uint64_t category, const char* name, int32_t cookie) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - if (perfettoTeCategory != nullptr) { - return internal::perfettoTraceAsyncBegin(*perfettoTeCategory, name, cookie); - } else { + + if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_async_begin(category, name, cookie); - return Result::SUCCESS; + } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { + internal::perfettoTraceAsyncBegin(*perfettoTeCategory, name, cookie); } } -Result traceAsyncEnd(uint64_t category, const char* name, int32_t cookie) { +void traceAsyncEnd(uint64_t category, const char* name, int32_t cookie) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - if (perfettoTeCategory != nullptr) { - return internal::perfettoTraceAsyncEnd(*perfettoTeCategory, name, cookie); - } else { + + if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_async_end(category, name, cookie); - return Result::SUCCESS; + } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { + internal::perfettoTraceAsyncEnd(*perfettoTeCategory, name, cookie); } } -Result traceAsyncBeginForTrack(uint64_t category, const char* name, +void traceAsyncBeginForTrack(uint64_t category, const char* name, const char* trackName, int32_t cookie) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - if (perfettoTeCategory != nullptr) { - return internal::perfettoTraceAsyncBeginForTrack(*perfettoTeCategory, name, trackName, cookie); - } else { + + if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_async_for_track_begin(category, trackName, name, cookie); - return Result::SUCCESS; + } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { + internal::perfettoTraceAsyncBeginForTrack(*perfettoTeCategory, name, trackName, cookie); } } -Result traceAsyncEndForTrack(uint64_t category, const char* trackName, +void traceAsyncEndForTrack(uint64_t category, const char* trackName, int32_t cookie) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - if (perfettoTeCategory != nullptr) { - return internal::perfettoTraceAsyncEndForTrack(*perfettoTeCategory, trackName, cookie); - } else { + + if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_async_for_track_end(category, trackName, cookie); - return Result::SUCCESS; + } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { + internal::perfettoTraceAsyncEndForTrack(*perfettoTeCategory, trackName, cookie); } } -Result traceInstant(uint64_t category, const char* name) { +void traceInstant(uint64_t category, const char* name) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - if (perfettoTeCategory != nullptr) { - return internal::perfettoTraceInstant(*perfettoTeCategory, name); - } else { + + if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_instant(category, name); - return Result::SUCCESS; + } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { + internal::perfettoTraceInstant(*perfettoTeCategory, name); } } -Result traceInstantForTrack(uint64_t category, const char* trackName, +void traceInstantForTrack(uint64_t category, const char* trackName, const char* name) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - if (perfettoTeCategory != nullptr) { - return internal::perfettoTraceInstantForTrack(*perfettoTeCategory, trackName, name); - } else { + + if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_instant_for_track(category, trackName, name); - return Result::SUCCESS; + } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { + internal::perfettoTraceInstantForTrack(*perfettoTeCategory, trackName, name); } } -Result traceCounter(uint64_t category, const char* name, int64_t value) { +void traceCounter(uint64_t category, const char* name, int64_t value) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - if (perfettoTeCategory != nullptr) { - return internal::perfettoTraceCounter(*perfettoTeCategory, name, value); - } else { + + if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_int64(category, name, value); - return Result::SUCCESS; + } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { + internal::perfettoTraceCounter(*perfettoTeCategory, name, value); } } bool isTagEnabled(uint64_t category) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - if (perfettoTeCategory != nullptr) { - return true; - } else { - return (atrace_get_enabled_tags() & category) != 0; - } + return internal::isPerfettoCategoryEnabled(perfettoTeCategory) + || atrace_is_tag_enabled(category); } - } // namespace tracing_perfetto diff --git a/libs/tracing_perfetto/tracing_perfetto_internal.cpp b/libs/tracing_perfetto/tracing_perfetto_internal.cpp index 758ace63ab..9a0042aee5 100644 --- a/libs/tracing_perfetto/tracing_perfetto_internal.cpp +++ b/libs/tracing_perfetto/tracing_perfetto_internal.cpp @@ -44,13 +44,13 @@ C(rro, "rro", "RRO category") \ C(thermal, "thermal", "Thermal category") -#include "tracing_perfetto_internal.h" - -#include <inttypes.h> - +#include <atomic> #include <mutex> #include <android_os.h> +#include <android-base/properties.h> +#include <cutils/trace.h> +#include <inttypes.h> #include "perfetto/public/compiler.h" #include "perfetto/public/producer.h" @@ -58,19 +58,42 @@ #include "perfetto/public/te_macros.h" #include "perfetto/public/track_event.h" #include "trace_categories.h" -#include "trace_result.h" +#include "tracing_perfetto_internal.h" + +#ifdef __BIONIC__ +#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ +#include <sys/_system_properties.h> +#endif namespace tracing_perfetto { namespace internal { namespace { - PERFETTO_TE_CATEGORIES_DECLARE(FRAMEWORK_CATEGORIES); PERFETTO_TE_CATEGORIES_DEFINE(FRAMEWORK_CATEGORIES); -std::atomic_bool is_perfetto_registered = false; +static constexpr char kPreferFlagProperty[] = "debug.atrace.prefer_sdk"; +static std::atomic<const prop_info*> prefer_property_info = nullptr; +static std::atomic_uint32_t last_prefer_seq_num = 0; +static std::atomic_uint64_t prefer_flags = 0; + +static const prop_info* system_property_find(const char* name [[maybe_unused]]) { + #ifdef __BIONIC__ + return __system_property_find(name); + #endif + + return nullptr; +} + +static uint32_t system_property_serial(const prop_info* pi [[maybe_unused]]) { + #ifdef __BIONIC__ + return __system_property_serial(pi); + #endif + + return last_prefer_seq_num; +} struct PerfettoTeCategory* toCategory(uint64_t inCategory) { switch (inCategory) { @@ -137,8 +160,60 @@ struct PerfettoTeCategory* toCategory(uint64_t inCategory) { } // namespace -bool isPerfettoRegistered() { - return is_perfetto_registered; +bool isPerfettoCategoryEnabled(PerfettoTeCategory* category) { + return category != nullptr; +} + +/** + * Updates the cached |prefer_flags|. + * + * We cache the prefer_flags because reading it on every trace event is expensive. + * The cache is invalidated when a sys_prop sequence number changes. + */ +void updatePreferFlags() { + if (!prefer_property_info.load(std::memory_order_acquire)) { + auto* new_prefer_property_info = system_property_find(kPreferFlagProperty); + prefer_flags.store(android::base::GetIntProperty(kPreferFlagProperty, 0), + std::memory_order_relaxed); + + if (!new_prefer_property_info) { + // This should never happen. If it does, we fail gracefully and end up reading the property + // traced event. + return; + } + + last_prefer_seq_num = system_property_serial(new_prefer_property_info); + prefer_property_info.store(new_prefer_property_info, std::memory_order_release); + } + + uint32_t prefer_seq_num = system_property_serial(prefer_property_info); + if (prefer_seq_num != last_prefer_seq_num.load(std::memory_order_acquire)) { + prefer_flags.store(android::base::GetIntProperty(kPreferFlagProperty, 0), + std::memory_order_relaxed); + last_prefer_seq_num.store(prefer_seq_num, std::memory_order_release); + } +} + +bool shouldPreferAtrace(PerfettoTeCategory *perfettoCategory, uint64_t atraceCategory) { + // There are 3 cases: + // 1. Atrace is not enabled. + if (!atrace_is_tag_enabled(atraceCategory)) { + return false; + } + + // 2. Atrace is enabled but perfetto is not enabled. + if (!isPerfettoCategoryEnabled(perfettoCategory)) { + return true; + } + + // Update prefer_flags before checking it below + updatePreferFlags(); + + // 3. Atrace and perfetto are enabled. + // Even though this category is enabled for track events, the config mandates that we downgrade + // it to atrace if the same atrace category is currently enabled. This prevents missing the + // event from a concurrent session that needs the same category in atrace. + return (atraceCategory & prefer_flags.load(std::memory_order_relaxed)) == 0; } struct PerfettoTeCategory* toPerfettoCategory(uint64_t category) { @@ -148,7 +223,7 @@ struct PerfettoTeCategory* toPerfettoCategory(uint64_t category) { } bool enabled = PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT( - (*perfettoCategory).enabled, PERFETTO_MEMORY_ORDER_RELAXED)); + (*perfettoCategory).enabled, PERFETTO_MEMORY_ORDER_RELAXED)); return enabled ? perfettoCategory : nullptr; } @@ -164,70 +239,57 @@ void registerWithPerfetto(bool test) { PerfettoProducerInit(args); PerfettoTeInit(); PERFETTO_TE_REGISTER_CATEGORIES(FRAMEWORK_CATEGORIES); - is_perfetto_registered = true; }); } -Result perfettoTraceBegin(const struct PerfettoTeCategory& category, const char* name) { +void perfettoTraceBegin(const struct PerfettoTeCategory& category, const char* name) { PERFETTO_TE(category, PERFETTO_TE_SLICE_BEGIN(name)); - return Result::SUCCESS; } -Result perfettoTraceEnd(const struct PerfettoTeCategory& category) { +void perfettoTraceEnd(const struct PerfettoTeCategory& category) { PERFETTO_TE(category, PERFETTO_TE_SLICE_END()); - return Result::SUCCESS; } -Result perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory& category, const char* name, +void perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory& category, const char* name, const char* trackName, uint64_t cookie) { PERFETTO_TE( category, PERFETTO_TE_SLICE_BEGIN(name), PERFETTO_TE_NAMED_TRACK(trackName, cookie, PerfettoTeProcessTrackUuid())); - return Result::SUCCESS; } -Result perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory& category, +void perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory& category, const char* trackName, uint64_t cookie) { PERFETTO_TE( category, PERFETTO_TE_SLICE_END(), PERFETTO_TE_NAMED_TRACK(trackName, cookie, PerfettoTeProcessTrackUuid())); - return Result::SUCCESS; } -Result perfettoTraceAsyncBegin(const struct PerfettoTeCategory& category, const char* name, +void perfettoTraceAsyncBegin(const struct PerfettoTeCategory& category, const char* name, uint64_t cookie) { - return perfettoTraceAsyncBeginForTrack(category, name, name, cookie); + perfettoTraceAsyncBeginForTrack(category, name, name, cookie); } -Result perfettoTraceAsyncEnd(const struct PerfettoTeCategory& category, const char* name, +void perfettoTraceAsyncEnd(const struct PerfettoTeCategory& category, const char* name, uint64_t cookie) { - return perfettoTraceAsyncEndForTrack(category, name, cookie); + perfettoTraceAsyncEndForTrack(category, name, cookie); } -Result perfettoTraceInstant(const struct PerfettoTeCategory& category, const char* name) { +void perfettoTraceInstant(const struct PerfettoTeCategory& category, const char* name) { PERFETTO_TE(category, PERFETTO_TE_INSTANT(name)); - return Result::SUCCESS; } -Result perfettoTraceInstantForTrack(const struct PerfettoTeCategory& category, +void perfettoTraceInstantForTrack(const struct PerfettoTeCategory& category, const char* trackName, const char* name) { PERFETTO_TE( category, PERFETTO_TE_INSTANT(name), PERFETTO_TE_NAMED_TRACK(trackName, 1, PerfettoTeProcessTrackUuid())); - return Result::SUCCESS; } -Result perfettoTraceCounter(const struct PerfettoTeCategory& category, +void perfettoTraceCounter(const struct PerfettoTeCategory& category, [[maybe_unused]] const char* name, int64_t value) { PERFETTO_TE(category, PERFETTO_TE_COUNTER(), PERFETTO_TE_INT_COUNTER(value)); - return Result::SUCCESS; -} - -uint64_t getDefaultCategories() { - return TRACE_CATEGORIES; } - } // namespace internal } // namespace tracing_perfetto diff --git a/libs/tracing_perfetto/tracing_perfetto_internal.h b/libs/tracing_perfetto/tracing_perfetto_internal.h index 79e4b8f1b4..3e1ac2a112 100644 --- a/libs/tracing_perfetto/tracing_perfetto_internal.h +++ b/libs/tracing_perfetto/tracing_perfetto_internal.h @@ -19,7 +19,6 @@ #include <stdint.h> -#include "include/trace_result.h" #include "perfetto/public/te_category_macros.h" namespace tracing_perfetto { @@ -32,31 +31,33 @@ struct PerfettoTeCategory* toPerfettoCategory(uint64_t category); void registerWithPerfetto(bool test = false); -Result perfettoTraceBegin(const struct PerfettoTeCategory& category, const char* name); +void perfettoTraceBegin(const struct PerfettoTeCategory& category, const char* name); -Result perfettoTraceEnd(const struct PerfettoTeCategory& category); +void perfettoTraceEnd(const struct PerfettoTeCategory& category); -Result perfettoTraceAsyncBegin(const struct PerfettoTeCategory& category, const char* name, +void perfettoTraceAsyncBegin(const struct PerfettoTeCategory& category, const char* name, uint64_t cookie); -Result perfettoTraceAsyncEnd(const struct PerfettoTeCategory& category, const char* name, +void perfettoTraceAsyncEnd(const struct PerfettoTeCategory& category, const char* name, uint64_t cookie); -Result perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory& category, const char* name, +void perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory& category, const char* name, const char* trackName, uint64_t cookie); -Result perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory& category, +void perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory& category, const char* trackName, uint64_t cookie); -Result perfettoTraceInstant(const struct PerfettoTeCategory& category, const char* name); +void perfettoTraceInstant(const struct PerfettoTeCategory& category, const char* name); -Result perfettoTraceInstantForTrack(const struct PerfettoTeCategory& category, +void perfettoTraceInstantForTrack(const struct PerfettoTeCategory& category, const char* trackName, const char* name); -Result perfettoTraceCounter(const struct PerfettoTeCategory& category, const char* name, +void perfettoTraceCounter(const struct PerfettoTeCategory& category, const char* name, int64_t value); -uint64_t getDefaultCategories(); +bool isPerfettoCategoryEnabled(PerfettoTeCategory *perfettoTeCategory); + +bool shouldPreferAtrace(PerfettoTeCategory *perfettoTeCategory, uint64_t category); } // namespace internal diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp index daab636c59..5c5fd3fb5f 100644 --- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp @@ -258,11 +258,9 @@ TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext, // 2) TouchpadInputMapper is stored as a unique_ptr and not moved. mGestureInterpreter->SetPropProvider(const_cast<GesturesPropProvider*>(&gesturePropProvider), &mPropertyProvider); - if (input_flags::enable_gestures_library_timer_provider()) { - mGestureInterpreter->SetTimerProvider(const_cast<GesturesTimerProvider*>( - &kGestureTimerProvider), - &mTimerProvider); - } + mGestureInterpreter->SetTimerProvider(const_cast<GesturesTimerProvider*>( + &kGestureTimerProvider), + &mTimerProvider); mGestureInterpreter->SetCallback(gestureInterpreterCallback, this); } @@ -300,12 +298,8 @@ void TouchpadInputMapper::dump(std::string& dump) { dump += addLinePrefix(mGestureConverter.dump(), INDENT4); dump += INDENT3 "Gesture properties:\n"; dump += addLinePrefix(mPropertyProvider.dump(), INDENT4); - if (input_flags::enable_gestures_library_timer_provider()) { - dump += INDENT3 "Timer provider:\n"; - dump += addLinePrefix(mTimerProvider.dump(), INDENT4); - } else { - dump += INDENT3 "Timer provider: disabled by flag\n"; - } + dump += INDENT3 "Timer provider:\n"; + dump += addLinePrefix(mTimerProvider.dump(), INDENT4); dump += INDENT3 "Captured event converter:\n"; dump += addLinePrefix(mCapturedEventConverter.dump(), INDENT4); dump += StringPrintf(INDENT3 "DisplayId: %s\n", @@ -468,9 +462,6 @@ std::list<NotifyArgs> TouchpadInputMapper::sendHardwareState(nsecs_t when, nsecs } std::list<NotifyArgs> TouchpadInputMapper::timeoutExpired(nsecs_t when) { - if (!input_flags::enable_gestures_library_timer_provider()) { - return {}; - } mTimerProvider.triggerCallbacks(when); return processGestures(when, when); } diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp index da56014530..334c104faf 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp @@ -211,7 +211,7 @@ void PowerAdvisor::sendHintSessionHint(SessionHint hint) { return; } SFTRACE_CALL(); - if (sTraceHintSessionData) ATRACE_INT("Session hint", static_cast<int>(hint)); + if (sTraceHintSessionData) SFTRACE_INT("Session hint", static_cast<int>(hint)); { std::scoped_lock lock(mHintSessionMutex); if (!ensurePowerHintSessionRunning()) { @@ -298,7 +298,7 @@ void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) { SFTRACE_CALL(); { mTargetDuration = targetDuration; - if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns()); + if (sTraceHintSessionData) SFTRACE_INT64("Time target", targetDuration.ns()); if (targetDuration == mLastTargetDurationSent) return; std::scoped_lock lock(mHintSessionMutex); if (!ensurePowerHintSessionRunning()) { diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h index bc4a41bf84..1076b2b79b 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h @@ -300,7 +300,7 @@ private: bool mSessionConfigSupported = true; bool mFirstConfigSupportCheck = true; - // Whether we should emit ATRACE_INT data for hint sessions + // Whether we should emit SFTRACE_INT data for hint sessions static const bool sTraceHintSessionData; // Default target duration for the hint session diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index 55505650e3..2a0ee5a993 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -359,7 +359,11 @@ void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) { void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) { std::scoped_lock lock(mMutex); - mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime); + if (CC_UNLIKELY(acquireFenceTime == Fence::SIGNAL_TIME_PENDING)) { + mActuals.endTime = mActualQueueTime; + } else { + mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime); + } } void SurfaceFrame::setDropTime(nsecs_t dropTime) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 86c7d165e8..a6d2b1529a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -3060,6 +3060,8 @@ void Layer::releasePreviousBuffer() { callReleaseBufferCallback(mDrawingState.releaseBufferListener, mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber, mDrawingState.acquireFence); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->removeTimeRecord(layerId, mDrawingState.frameNumber); decrementPendingBufferCount(); if (mDrawingState.bufferSurfaceFrameTX != nullptr && mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) { @@ -3238,7 +3240,7 @@ void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerPro return static_cast<nsecs_t>(0); }(); - if (ATRACE_ENABLED() && presentTime > 0) { + if (SFTRACE_ENABLED() && presentTime > 0) { const auto presentIn = TimePoint::fromNs(presentTime) - TimePoint::now(); SFTRACE_FORMAT_INSTANT("presentIn %s", to_string(presentIn).c_str()); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d3b56f89d1..52f169ebee 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -1265,7 +1265,7 @@ private: const std::string mBlastTransactionName{"BufferTX - " + mName}; // This integer is incremented everytime a buffer arrives at the server for this layer, // and decremented when a buffer is dropped or latched. When changed the integer is exported - // to systrace with ATRACE_INT and mBlastTransactionName. This way when debugging perf it is + // to systrace with SFTRACE_INT and mBlastTransactionName. This way when debugging perf it is // possible to see when a buffer arrived at the server, and in which frame it latched. // // You can understand the trace this way: diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index 0b17c8495c..a20cf9a787 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -1065,7 +1065,7 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme ALOGV("%s: overriding to %s for uid=%d", __func__, to_string(overrideFps).c_str(), uid); SFTRACE_FORMAT_INSTANT("%s: overriding to %s for uid=%d", __func__, to_string(overrideFps).c_str(), uid); - if (ATRACE_ENABLED() && FlagManager::getInstance().trace_frame_rate_override()) { + if (SFTRACE_ENABLED() && FlagManager::getInstance().trace_frame_rate_override()) { std::stringstream ss; ss << "FrameRateOverride " << uid; SFTRACE_INT(ss.str().c_str(), overrideFps.getIntValue()); diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp index 8dae3ca0a3..900bce0aa9 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp +++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp @@ -45,7 +45,7 @@ ScheduleResult getExpectedCallbackTime(nsecs_t nextVsyncTime, } void traceEntry(const VSyncDispatchTimerQueueEntry& entry, nsecs_t now) { - if (!ATRACE_ENABLED() || !entry.wakeupTime().has_value() || !entry.targetVsync().has_value()) { + if (!SFTRACE_ENABLED() || !entry.wakeupTime().has_value() || !entry.targetVsync().has_value()) { return; } diff --git a/services/surfaceflinger/Scheduler/src/Timer.cpp b/services/surfaceflinger/Scheduler/src/Timer.cpp index fba3d58db5..20c58eb52f 100644 --- a/services/surfaceflinger/Scheduler/src/Timer.cpp +++ b/services/surfaceflinger/Scheduler/src/Timer.cpp @@ -188,7 +188,7 @@ bool Timer::dispatch() { int nfds = epoll_wait(mEpollFd, events, DispatchType::MAX_DISPATCH_TYPE, -1); setDebugState(DebugState::Running); - if (ATRACE_ENABLED()) { + if (SFTRACE_ENABLED()) { ftl::Concat trace("TimerIteration #", iteration++); SFTRACE_NAME(trace.c_str()); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d00e762606..c25c7bc2a1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3320,9 +3320,9 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, }); } - // Even though ATRACE_INT64 already checks if tracing is enabled, it doesn't prevent the + // Even though SFTRACE_INT64 already checks if tracing is enabled, it doesn't prevent the // side-effect of getTotalSize(), so we check that again here - if (ATRACE_ENABLED()) { + if (SFTRACE_ENABLED()) { // getTotalSize returns the total number of buffers that were allocated by SurfaceFlinger SFTRACE_INT64("Total Buffer Size", GraphicBufferAllocator::get().getTotalSize()); } diff --git a/services/surfaceflinger/TracedOrdinal.h b/services/surfaceflinger/TracedOrdinal.h index eba1ecf760..51f33a6988 100644 --- a/services/surfaceflinger/TracedOrdinal.h +++ b/services/surfaceflinger/TracedOrdinal.h @@ -79,7 +79,7 @@ public: private: void trace() { - if (CC_LIKELY(!ATRACE_ENABLED())) { + if (CC_LIKELY(!SFTRACE_ENABLED())) { return; } diff --git a/services/surfaceflinger/common/include/common/trace.h b/services/surfaceflinger/common/include/common/trace.h index c13cdde90d..344359ed7d 100644 --- a/services/surfaceflinger/common/include/common/trace.h +++ b/services/surfaceflinger/common/include/common/trace.h @@ -20,6 +20,10 @@ #include <cutils/trace.h> #include <stdint.h> +#ifndef ATRACE_TAG +#define ATRACE_TAG ATRACE_TAG_GRAPHICS +#endif + #define SFTRACE_ENABLED() ATRACE_ENABLED() #define SFTRACE_BEGIN(name) ATRACE_BEGIN(name) #define SFTRACE_END() ATRACE_END() diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index 25437ca856..9be0fc38b3 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -479,6 +479,16 @@ TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceAfterQueue) { EXPECT_EQ(surfaceFrame->getActuals().endTime, 456); } +TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceUnsignaled) { + auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, sLayerIdOne, + "acquireFenceAfterQueue", + "acquireFenceAfterQueue", + /*isBuffer*/ true, sGameMode); + surfaceFrame->setActualQueueTime(123); + surfaceFrame->setAcquireFenceTime(Fence::SIGNAL_TIME_PENDING); + EXPECT_EQ(surfaceFrame->getActuals().endTime, 123); +} + TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceBeforeQueue) { auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, sLayerIdOne, "acquireFenceAfterQueue", |