/* * Copyright 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "../../InputDeviceMetricsSource.h" #include "dispatcher/LatencyTracker.h" namespace android { namespace inputdispatcher { /** * A processor of InputEventTimelines that does nothing with the provided data. */ class EmptyProcessor : public InputEventTimelineProcessor { public: /** * Just ignore the provided timeline */ void processTimeline(const InputEventTimeline& timeline) override { for (const auto& [token, connectionTimeline] : timeline.connectionTimelines) { connectionTimeline.isComplete(); } }; }; static sp getConnectionToken(FuzzedDataProvider& fdp, std::array, 10>& tokens) { const bool useExistingToken = fdp.ConsumeBool(); if (useExistingToken) { return tokens[fdp.ConsumeIntegralInRange(0ul, tokens.size() - 1)]; } return sp::make(); } extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { FuzzedDataProvider fdp(data, size); EmptyProcessor emptyProcessor; LatencyTracker tracker(&emptyProcessor); // Make some pre-defined tokens to ensure that some timelines are complete. std::array /*token*/, 10> predefinedTokens; for (size_t i = 0; i < predefinedTokens.size(); i++) { predefinedTokens[i] = sp::make(); } // Randomly invoke LatencyTracker api's until randomness is exhausted. while (fdp.remaining_bytes() > 0) { fdp.PickValueInArray>({ [&]() -> void { int32_t inputEventId = fdp.ConsumeIntegral(); int32_t isDown = fdp.ConsumeBool(); nsecs_t eventTime = fdp.ConsumeIntegral(); nsecs_t readTime = fdp.ConsumeIntegral(); const DeviceId deviceId = fdp.ConsumeIntegral(); std::set sources = { fdp.ConsumeEnum()}; tracker.trackListener(inputEventId, isDown, eventTime, readTime, deviceId, sources); }, [&]() -> void { int32_t inputEventId = fdp.ConsumeIntegral(); sp connectionToken = getConnectionToken(fdp, predefinedTokens); nsecs_t deliveryTime = fdp.ConsumeIntegral(); nsecs_t consumeTime = fdp.ConsumeIntegral(); nsecs_t finishTime = fdp.ConsumeIntegral(); tracker.trackFinishedEvent(inputEventId, connectionToken, deliveryTime, consumeTime, finishTime); }, [&]() -> void { int32_t inputEventId = fdp.ConsumeIntegral(); sp connectionToken = getConnectionToken(fdp, predefinedTokens); std::array graphicsTimeline; for (size_t i = 0; i < graphicsTimeline.size(); i++) { graphicsTimeline[i] = fdp.ConsumeIntegral(); } tracker.trackGraphicsLatency(inputEventId, connectionToken, graphicsTimeline); }, })(); } return 0; } } // namespace inputdispatcher } // namespace android