1 /*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <fuzzer/FuzzedDataProvider.h>
18 #include <linux/input.h>
19
20 #include "../../InputDeviceMetricsSource.h"
21 #include "dispatcher/LatencyTracker.h"
22
23 namespace android {
24
25 namespace inputdispatcher {
26
27 /**
28 * A processor of InputEventTimelines that does nothing with the provided data.
29 */
30 class EmptyProcessor : public InputEventTimelineProcessor {
31 public:
32 /**
33 * Just ignore the provided timeline
34 */
processTimeline(const InputEventTimeline & timeline)35 void processTimeline(const InputEventTimeline& timeline) override {
36 for (const auto& [token, connectionTimeline] : timeline.connectionTimelines) {
37 connectionTimeline.isComplete();
38 }
39 };
40 };
41
getConnectionToken(FuzzedDataProvider & fdp,std::array<sp<IBinder>,10> & tokens)42 static sp<IBinder> getConnectionToken(FuzzedDataProvider& fdp,
43 std::array<sp<IBinder>, 10>& tokens) {
44 const bool useExistingToken = fdp.ConsumeBool();
45 if (useExistingToken) {
46 return tokens[fdp.ConsumeIntegralInRange<size_t>(0ul, tokens.size() - 1)];
47 }
48 return sp<BBinder>::make();
49 }
50
LLVMFuzzerTestOneInput(uint8_t * data,size_t size)51 extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
52 FuzzedDataProvider fdp(data, size);
53
54 EmptyProcessor emptyProcessor;
55 LatencyTracker tracker(&emptyProcessor);
56
57 // Make some pre-defined tokens to ensure that some timelines are complete.
58 std::array<sp<IBinder> /*token*/, 10> predefinedTokens;
59 for (size_t i = 0; i < predefinedTokens.size(); i++) {
60 predefinedTokens[i] = sp<BBinder>::make();
61 }
62
63 // Randomly invoke LatencyTracker api's until randomness is exhausted.
64 while (fdp.remaining_bytes() > 0) {
65 fdp.PickValueInArray<std::function<void()>>({
66 [&]() -> void {
67 int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
68 int32_t isDown = fdp.ConsumeBool();
69 nsecs_t eventTime = fdp.ConsumeIntegral<nsecs_t>();
70 nsecs_t readTime = fdp.ConsumeIntegral<nsecs_t>();
71 const DeviceId deviceId = fdp.ConsumeIntegral<int32_t>();
72 std::set<InputDeviceUsageSource> sources = {
73 fdp.ConsumeEnum<InputDeviceUsageSource>()};
74 tracker.trackListener(inputEventId, isDown, eventTime, readTime, deviceId,
75 sources);
76 },
77 [&]() -> void {
78 int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
79 sp<IBinder> connectionToken = getConnectionToken(fdp, predefinedTokens);
80 nsecs_t deliveryTime = fdp.ConsumeIntegral<nsecs_t>();
81 nsecs_t consumeTime = fdp.ConsumeIntegral<nsecs_t>();
82 nsecs_t finishTime = fdp.ConsumeIntegral<nsecs_t>();
83 tracker.trackFinishedEvent(inputEventId, connectionToken, deliveryTime,
84 consumeTime, finishTime);
85 },
86 [&]() -> void {
87 int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
88 sp<IBinder> connectionToken = getConnectionToken(fdp, predefinedTokens);
89 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
90 for (size_t i = 0; i < graphicsTimeline.size(); i++) {
91 graphicsTimeline[i] = fdp.ConsumeIntegral<nsecs_t>();
92 }
93 tracker.trackGraphicsLatency(inputEventId, connectionToken, graphicsTimeline);
94 },
95 })();
96 }
97
98 return 0;
99 }
100
101 } // namespace inputdispatcher
102
103 } // namespace android