Loading services/inputflinger/dispatcher/InputDispatcher.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -3899,6 +3899,13 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { args->downTime, args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0); if (args->id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID && IdGenerator::getSource(args->id) == IdGenerator::Source::INPUT_READER && !mInputFilterEnabled) { const bool isDown = args->action == AMOTION_EVENT_ACTION_DOWN; mLatencyTracker.trackListener(args->id, isDown, args->eventTime, args->readTime); } needWake = enqueueInboundEventLocked(std::move(newEntry)); mLock.unlock(); } // release lock Loading services/inputflinger/dispatcher/LatencyTracker.cpp +10 −19 Original line number Diff line number Diff line Loading @@ -50,13 +50,12 @@ static bool isMatureEvent(nsecs_t eventTime, nsecs_t now) { * key-value pair. Equivalent to the imaginary std api std::multimap::erase(key, value). */ template <typename K, typename V> static void eraseByKeyAndValue(std::multimap<K, V>& map, K key, V value) { auto iterpair = map.equal_range(key); for (auto it = iterpair.first; it != iterpair.second; ++it) { static void eraseByValue(std::multimap<K, V>& map, const V& value) { for (auto it = map.begin(); it != map.end();) { if (it->second == value) { map.erase(it); break; it = map.erase(it); } else { it++; } } } Loading @@ -76,9 +75,7 @@ void LatencyTracker::trackListener(int32_t inputEventId, bool isDown, nsecs_t ev // confuse us by reporting the rest of the timeline for one of them. This should happen // rarely, so we won't lose much data mTimelines.erase(it); // In case we have another input event with a different id and at the same eventTime, // only erase this specific inputEventId. eraseByKeyAndValue(mEventTimes, eventTime, inputEventId); eraseByValue(mEventTimes, inputEventId); return; } mTimelines.emplace(inputEventId, InputEventTimeline(isDown, eventTime, readTime)); Loading @@ -90,7 +87,8 @@ void LatencyTracker::trackFinishedEvent(int32_t inputEventId, const sp<IBinder>& nsecs_t finishTime) { const auto it = mTimelines.find(inputEventId); if (it == mTimelines.end()) { // It's possible that an app sends a bad (or late)'Finish' signal, since it's free to do // This could happen if we erased this event when duplicate events were detected. It's // also possible that an app sent a bad (or late) 'Finish' signal, since it's free to do // anything in its process. Just drop the report and move on. return; } Loading Loading @@ -120,7 +118,8 @@ void LatencyTracker::trackGraphicsLatency( std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline) { const auto it = mTimelines.find(inputEventId); if (it == mTimelines.end()) { // It's possible that an app sends a bad (or late) 'Timeline' signal, since it's free to do // This could happen if we erased this event when duplicate events were detected. It's // also possible that an app sent a bad (or late) 'Timeline' signal, since it's free to do // anything in its process. Just drop the report and move on. return; } Loading Loading @@ -166,14 +165,6 @@ void LatencyTracker::reportAndPruneMatureRecords(nsecs_t newEventTime) { } } void LatencyTracker::reportNow() { for (const auto& [inputEventId, timeline] : mTimelines) { mTimelineProcessor->processTimeline(timeline); } mTimelines.clear(); mEventTimes.clear(); } std::string LatencyTracker::dump(const char* prefix) { return StringPrintf("%sLatencyTracker:\n", prefix) + StringPrintf("%s mTimelines.size() = %zu\n", prefix, mTimelines.size()) + Loading services/inputflinger/dispatcher/LatencyTracker.h +6 −8 Original line number Diff line number Diff line Loading @@ -43,6 +43,12 @@ public: LatencyTracker(InputEventTimelineProcessor* processor); /** * Start keeping track of an event identified by inputEventId. This must be called first. * If duplicate events are encountered (events that have the same eventId), none of them will be * tracked. This is because there is not enough information to correctly track them. The api's * 'trackFinishedEvent' and 'trackGraphicsLatency' only contain the inputEventId, and not the * eventTime. Even if eventTime was provided, there would still be a possibility of having * duplicate events that happen to have the same eventTime and inputEventId. Therefore, we * must drop all duplicate data. */ void trackListener(int32_t inputEventId, bool isDown, nsecs_t eventTime, nsecs_t readTime); void trackFinishedEvent(int32_t inputEventId, const sp<IBinder>& connectionToken, Loading @@ -50,14 +56,6 @@ public: void trackGraphicsLatency(int32_t inputEventId, const sp<IBinder>& connectionToken, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline); /** * Report all collected events immediately, even if some of them are currently incomplete * and may receive 'trackFinishedEvent' or 'trackGraphicsLatency' calls in the future. * This is useful for tests. Otherwise, tests would have to inject additional "future" events, * which is not convenient. */ void reportNow(); std::string dump(const char* prefix); private: Loading services/inputflinger/tests/LatencyTracker_test.cpp +45 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "../dispatcher/LatencyTracker.h" #include <android-base/properties.h> #include <binder/Binder.h> #include <gtest/gtest.h> #include <inttypes.h> Loading @@ -23,11 +24,16 @@ #define TAG "LatencyTracker_test" using android::base::HwTimeoutMultiplier; using android::inputdispatcher::InputEventTimeline; using android::inputdispatcher::LatencyTracker; namespace android::inputdispatcher { const std::chrono::duration ANR_TIMEOUT = std::chrono::milliseconds( android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS * HwTimeoutMultiplier()); InputEventTimeline getTestTimeline() { InputEventTimeline t( /*isDown*/ true, Loading Loading @@ -57,6 +63,8 @@ protected: } void TearDown() override {} void triggerEventReporting(nsecs_t lastEventTime); void assertReceivedTimeline(const InputEventTimeline& timeline); /** * Timelines can be received in any order (order is not guaranteed). So if we are expecting more Loading @@ -72,8 +80,17 @@ private: std::deque<InputEventTimeline> mReceivedTimelines; }; /** * Send an event that would trigger the reporting of all of the events that are at least as old as * the provided 'lastEventTime'. */ void LatencyTrackerTest::triggerEventReporting(nsecs_t lastEventTime) { const nsecs_t triggerEventTime = lastEventTime + std::chrono::nanoseconds(ANR_TIMEOUT).count() + 1; mTracker->trackListener(1 /*inputEventId*/, true /*isDown*/, triggerEventTime, 3 /*readTime*/); } void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& timeline) { mTracker->reportNow(); ASSERT_FALSE(mReceivedTimelines.empty()); const InputEventTimeline& t = mReceivedTimelines.front(); ASSERT_EQ(timeline, t); Loading @@ -88,7 +105,6 @@ void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& timeli * equal element in B, and for every element in B there is an equal element in A. */ void LatencyTrackerTest::assertReceivedTimelines(const std::vector<InputEventTimeline>& timelines) { mTracker->reportNow(); ASSERT_EQ(timelines.size(), mReceivedTimelines.size()); for (const InputEventTimeline& expectedTimeline : timelines) { bool found = false; Loading Loading @@ -121,6 +137,7 @@ void LatencyTrackerTest::assertReceivedTimelines(const std::vector<InputEventTim */ TEST_F(LatencyTrackerTest, TrackListener_DoesNotTriggerReporting) { mTracker->trackListener(1 /*inputEventId*/, false /*isDown*/, 2 /*eventTime*/, 3 /*readTime*/); triggerEventReporting(2 /*eventTime*/); assertReceivedTimeline(InputEventTimeline{false, 2, 3}); } Loading @@ -130,6 +147,7 @@ TEST_F(LatencyTrackerTest, TrackListener_DoesNotTriggerReporting) { TEST_F(LatencyTrackerTest, TrackFinishedEvent_DoesNotTriggerReporting) { mTracker->trackFinishedEvent(1 /*inputEventId*/, connection1, 2 /*deliveryTime*/, 3 /*consumeTime*/, 4 /*finishTime*/); triggerEventReporting(4 /*eventTime*/); assertReceivedTimelines({}); } Loading @@ -141,6 +159,7 @@ TEST_F(LatencyTrackerTest, TrackGraphicsLatency_DoesNotTriggerReporting) { graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2; graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3; mTracker->trackGraphicsLatency(1 /*inputEventId*/, connection2, graphicsTimeline); triggerEventReporting(3 /*eventTime*/); assertReceivedTimelines({}); } Loading @@ -155,9 +174,30 @@ TEST_F(LatencyTrackerTest, TrackAllParameters_ReportsFullTimeline) { expectedCT.consumeTime, expectedCT.finishTime); mTracker->trackGraphicsLatency(inputEventId, connectionToken, expectedCT.graphicsTimeline); triggerEventReporting(expected.eventTime); assertReceivedTimeline(expected); } /** * Send 2 events with the same inputEventId, but different eventTime's. Ensure that no crash occurs, * and that the tracker drops such events completely. */ TEST_F(LatencyTrackerTest, WhenDuplicateEventsAreReported_DoesNotCrash) { constexpr nsecs_t inputEventId = 1; constexpr nsecs_t readTime = 3; // does not matter for this test constexpr bool isDown = true; // does not matter for this test // In the following 2 calls to trackListener, the inputEventId's are the same, but event times // are different. mTracker->trackListener(inputEventId, isDown, 1 /*eventTime*/, readTime); mTracker->trackListener(inputEventId, isDown, 2 /*eventTime*/, readTime); triggerEventReporting(2 /*eventTime*/); // Since we sent duplicate input events, the tracker should just delete all of them, because it // does not have enough information to properly track them. assertReceivedTimelines({}); } TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) { constexpr int32_t inputEventId1 = 1; InputEventTimeline timeline1( Loading Loading @@ -204,6 +244,7 @@ TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) { mTracker->trackGraphicsLatency(inputEventId2, connection2, connectionTimeline2.graphicsTimeline); // Now both events should be completed triggerEventReporting(timeline2.eventTime); assertReceivedTimelines({timeline1, timeline2}); } Loading @@ -228,6 +269,7 @@ TEST_F(LatencyTrackerTest, IncompleteEvents_AreHandledConsistently) { mTracker->trackGraphicsLatency(1 /*inputEventId*/, token, expectedCT.graphicsTimeline); expectedTimelines[0].connectionTimelines.emplace(token, std::move(expectedCT)); triggerEventReporting(timeline.eventTime); assertReceivedTimelines(expectedTimelines); } Loading @@ -246,6 +288,7 @@ TEST_F(LatencyTrackerTest, EventsAreTracked_WhenTrackListenerIsCalledFirst) { mTracker->trackGraphicsLatency(inputEventId, connection1, expectedCT.graphicsTimeline); mTracker->trackListener(inputEventId, expected.isDown, expected.eventTime, expected.readTime); triggerEventReporting(expected.eventTime); assertReceivedTimeline( InputEventTimeline{expected.isDown, expected.eventTime, expected.readTime}); } Loading services/inputflinger/tests/fuzzers/Android.bp 0 → 100644 +45 −0 Original line number Diff line number Diff line // Copyright (C) 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. package { // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" // to get the below license kinds: // SPDX-license-identifier-Apache-2.0 default_applicable_licenses: ["frameworks_native_license"], } cc_fuzz { name: "inputflinger_latencytracker_fuzzer", defaults: [ "inputflinger_defaults", ], include_dirs: [ "frameworks/native/services/inputflinger", ], shared_libs: [ "libbase", "libbinder", "liblog", "libui", "libutils", "libinput", "libinputflinger", ], srcs: [ "LatencyTrackerFuzzer.cpp", ], } Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -3899,6 +3899,13 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { args->downTime, args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0); if (args->id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID && IdGenerator::getSource(args->id) == IdGenerator::Source::INPUT_READER && !mInputFilterEnabled) { const bool isDown = args->action == AMOTION_EVENT_ACTION_DOWN; mLatencyTracker.trackListener(args->id, isDown, args->eventTime, args->readTime); } needWake = enqueueInboundEventLocked(std::move(newEntry)); mLock.unlock(); } // release lock Loading
services/inputflinger/dispatcher/LatencyTracker.cpp +10 −19 Original line number Diff line number Diff line Loading @@ -50,13 +50,12 @@ static bool isMatureEvent(nsecs_t eventTime, nsecs_t now) { * key-value pair. Equivalent to the imaginary std api std::multimap::erase(key, value). */ template <typename K, typename V> static void eraseByKeyAndValue(std::multimap<K, V>& map, K key, V value) { auto iterpair = map.equal_range(key); for (auto it = iterpair.first; it != iterpair.second; ++it) { static void eraseByValue(std::multimap<K, V>& map, const V& value) { for (auto it = map.begin(); it != map.end();) { if (it->second == value) { map.erase(it); break; it = map.erase(it); } else { it++; } } } Loading @@ -76,9 +75,7 @@ void LatencyTracker::trackListener(int32_t inputEventId, bool isDown, nsecs_t ev // confuse us by reporting the rest of the timeline for one of them. This should happen // rarely, so we won't lose much data mTimelines.erase(it); // In case we have another input event with a different id and at the same eventTime, // only erase this specific inputEventId. eraseByKeyAndValue(mEventTimes, eventTime, inputEventId); eraseByValue(mEventTimes, inputEventId); return; } mTimelines.emplace(inputEventId, InputEventTimeline(isDown, eventTime, readTime)); Loading @@ -90,7 +87,8 @@ void LatencyTracker::trackFinishedEvent(int32_t inputEventId, const sp<IBinder>& nsecs_t finishTime) { const auto it = mTimelines.find(inputEventId); if (it == mTimelines.end()) { // It's possible that an app sends a bad (or late)'Finish' signal, since it's free to do // This could happen if we erased this event when duplicate events were detected. It's // also possible that an app sent a bad (or late) 'Finish' signal, since it's free to do // anything in its process. Just drop the report and move on. return; } Loading Loading @@ -120,7 +118,8 @@ void LatencyTracker::trackGraphicsLatency( std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline) { const auto it = mTimelines.find(inputEventId); if (it == mTimelines.end()) { // It's possible that an app sends a bad (or late) 'Timeline' signal, since it's free to do // This could happen if we erased this event when duplicate events were detected. It's // also possible that an app sent a bad (or late) 'Timeline' signal, since it's free to do // anything in its process. Just drop the report and move on. return; } Loading Loading @@ -166,14 +165,6 @@ void LatencyTracker::reportAndPruneMatureRecords(nsecs_t newEventTime) { } } void LatencyTracker::reportNow() { for (const auto& [inputEventId, timeline] : mTimelines) { mTimelineProcessor->processTimeline(timeline); } mTimelines.clear(); mEventTimes.clear(); } std::string LatencyTracker::dump(const char* prefix) { return StringPrintf("%sLatencyTracker:\n", prefix) + StringPrintf("%s mTimelines.size() = %zu\n", prefix, mTimelines.size()) + Loading
services/inputflinger/dispatcher/LatencyTracker.h +6 −8 Original line number Diff line number Diff line Loading @@ -43,6 +43,12 @@ public: LatencyTracker(InputEventTimelineProcessor* processor); /** * Start keeping track of an event identified by inputEventId. This must be called first. * If duplicate events are encountered (events that have the same eventId), none of them will be * tracked. This is because there is not enough information to correctly track them. The api's * 'trackFinishedEvent' and 'trackGraphicsLatency' only contain the inputEventId, and not the * eventTime. Even if eventTime was provided, there would still be a possibility of having * duplicate events that happen to have the same eventTime and inputEventId. Therefore, we * must drop all duplicate data. */ void trackListener(int32_t inputEventId, bool isDown, nsecs_t eventTime, nsecs_t readTime); void trackFinishedEvent(int32_t inputEventId, const sp<IBinder>& connectionToken, Loading @@ -50,14 +56,6 @@ public: void trackGraphicsLatency(int32_t inputEventId, const sp<IBinder>& connectionToken, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline); /** * Report all collected events immediately, even if some of them are currently incomplete * and may receive 'trackFinishedEvent' or 'trackGraphicsLatency' calls in the future. * This is useful for tests. Otherwise, tests would have to inject additional "future" events, * which is not convenient. */ void reportNow(); std::string dump(const char* prefix); private: Loading
services/inputflinger/tests/LatencyTracker_test.cpp +45 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "../dispatcher/LatencyTracker.h" #include <android-base/properties.h> #include <binder/Binder.h> #include <gtest/gtest.h> #include <inttypes.h> Loading @@ -23,11 +24,16 @@ #define TAG "LatencyTracker_test" using android::base::HwTimeoutMultiplier; using android::inputdispatcher::InputEventTimeline; using android::inputdispatcher::LatencyTracker; namespace android::inputdispatcher { const std::chrono::duration ANR_TIMEOUT = std::chrono::milliseconds( android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS * HwTimeoutMultiplier()); InputEventTimeline getTestTimeline() { InputEventTimeline t( /*isDown*/ true, Loading Loading @@ -57,6 +63,8 @@ protected: } void TearDown() override {} void triggerEventReporting(nsecs_t lastEventTime); void assertReceivedTimeline(const InputEventTimeline& timeline); /** * Timelines can be received in any order (order is not guaranteed). So if we are expecting more Loading @@ -72,8 +80,17 @@ private: std::deque<InputEventTimeline> mReceivedTimelines; }; /** * Send an event that would trigger the reporting of all of the events that are at least as old as * the provided 'lastEventTime'. */ void LatencyTrackerTest::triggerEventReporting(nsecs_t lastEventTime) { const nsecs_t triggerEventTime = lastEventTime + std::chrono::nanoseconds(ANR_TIMEOUT).count() + 1; mTracker->trackListener(1 /*inputEventId*/, true /*isDown*/, triggerEventTime, 3 /*readTime*/); } void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& timeline) { mTracker->reportNow(); ASSERT_FALSE(mReceivedTimelines.empty()); const InputEventTimeline& t = mReceivedTimelines.front(); ASSERT_EQ(timeline, t); Loading @@ -88,7 +105,6 @@ void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& timeli * equal element in B, and for every element in B there is an equal element in A. */ void LatencyTrackerTest::assertReceivedTimelines(const std::vector<InputEventTimeline>& timelines) { mTracker->reportNow(); ASSERT_EQ(timelines.size(), mReceivedTimelines.size()); for (const InputEventTimeline& expectedTimeline : timelines) { bool found = false; Loading Loading @@ -121,6 +137,7 @@ void LatencyTrackerTest::assertReceivedTimelines(const std::vector<InputEventTim */ TEST_F(LatencyTrackerTest, TrackListener_DoesNotTriggerReporting) { mTracker->trackListener(1 /*inputEventId*/, false /*isDown*/, 2 /*eventTime*/, 3 /*readTime*/); triggerEventReporting(2 /*eventTime*/); assertReceivedTimeline(InputEventTimeline{false, 2, 3}); } Loading @@ -130,6 +147,7 @@ TEST_F(LatencyTrackerTest, TrackListener_DoesNotTriggerReporting) { TEST_F(LatencyTrackerTest, TrackFinishedEvent_DoesNotTriggerReporting) { mTracker->trackFinishedEvent(1 /*inputEventId*/, connection1, 2 /*deliveryTime*/, 3 /*consumeTime*/, 4 /*finishTime*/); triggerEventReporting(4 /*eventTime*/); assertReceivedTimelines({}); } Loading @@ -141,6 +159,7 @@ TEST_F(LatencyTrackerTest, TrackGraphicsLatency_DoesNotTriggerReporting) { graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2; graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3; mTracker->trackGraphicsLatency(1 /*inputEventId*/, connection2, graphicsTimeline); triggerEventReporting(3 /*eventTime*/); assertReceivedTimelines({}); } Loading @@ -155,9 +174,30 @@ TEST_F(LatencyTrackerTest, TrackAllParameters_ReportsFullTimeline) { expectedCT.consumeTime, expectedCT.finishTime); mTracker->trackGraphicsLatency(inputEventId, connectionToken, expectedCT.graphicsTimeline); triggerEventReporting(expected.eventTime); assertReceivedTimeline(expected); } /** * Send 2 events with the same inputEventId, but different eventTime's. Ensure that no crash occurs, * and that the tracker drops such events completely. */ TEST_F(LatencyTrackerTest, WhenDuplicateEventsAreReported_DoesNotCrash) { constexpr nsecs_t inputEventId = 1; constexpr nsecs_t readTime = 3; // does not matter for this test constexpr bool isDown = true; // does not matter for this test // In the following 2 calls to trackListener, the inputEventId's are the same, but event times // are different. mTracker->trackListener(inputEventId, isDown, 1 /*eventTime*/, readTime); mTracker->trackListener(inputEventId, isDown, 2 /*eventTime*/, readTime); triggerEventReporting(2 /*eventTime*/); // Since we sent duplicate input events, the tracker should just delete all of them, because it // does not have enough information to properly track them. assertReceivedTimelines({}); } TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) { constexpr int32_t inputEventId1 = 1; InputEventTimeline timeline1( Loading Loading @@ -204,6 +244,7 @@ TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) { mTracker->trackGraphicsLatency(inputEventId2, connection2, connectionTimeline2.graphicsTimeline); // Now both events should be completed triggerEventReporting(timeline2.eventTime); assertReceivedTimelines({timeline1, timeline2}); } Loading @@ -228,6 +269,7 @@ TEST_F(LatencyTrackerTest, IncompleteEvents_AreHandledConsistently) { mTracker->trackGraphicsLatency(1 /*inputEventId*/, token, expectedCT.graphicsTimeline); expectedTimelines[0].connectionTimelines.emplace(token, std::move(expectedCT)); triggerEventReporting(timeline.eventTime); assertReceivedTimelines(expectedTimelines); } Loading @@ -246,6 +288,7 @@ TEST_F(LatencyTrackerTest, EventsAreTracked_WhenTrackListenerIsCalledFirst) { mTracker->trackGraphicsLatency(inputEventId, connection1, expectedCT.graphicsTimeline); mTracker->trackListener(inputEventId, expected.isDown, expected.eventTime, expected.readTime); triggerEventReporting(expected.eventTime); assertReceivedTimeline( InputEventTimeline{expected.isDown, expected.eventTime, expected.readTime}); } Loading
services/inputflinger/tests/fuzzers/Android.bp 0 → 100644 +45 −0 Original line number Diff line number Diff line // Copyright (C) 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. package { // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" // to get the below license kinds: // SPDX-license-identifier-Apache-2.0 default_applicable_licenses: ["frameworks_native_license"], } cc_fuzz { name: "inputflinger_latencytracker_fuzzer", defaults: [ "inputflinger_defaults", ], include_dirs: [ "frameworks/native/services/inputflinger", ], shared_libs: [ "libbase", "libbinder", "liblog", "libui", "libutils", "libinput", "libinputflinger", ], srcs: [ "LatencyTrackerFuzzer.cpp", ], }