xref: /aosp_15_r20/frameworks/native/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright 2023 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 <limits>
18 #include <memory>
19 #include <string>
20 #include <vector>
21 
22 #include <linux/input-event-codes.h>
23 
24 #include <InputDevice.h>
25 #include <InputReaderBase.h>
26 #include <MapperHelpers.h>
27 #include <TouchpadInputMapper.h>
28 
29 namespace android {
30 
31 namespace {
32 
setAxisInfo(ThreadSafeFuzzedDataProvider & fdp,FuzzEventHub & eventHub,int32_t id,int axis)33 void setAxisInfo(ThreadSafeFuzzedDataProvider& fdp, FuzzEventHub& eventHub, int32_t id, int axis) {
34     if (fdp.ConsumeBool()) {
35         eventHub.setAbsoluteAxisInfo(id, axis,
36                                      RawAbsoluteAxisInfo{
37                                              .minValue = fdp.ConsumeIntegral<int32_t>(),
38                                              .maxValue = fdp.ConsumeIntegral<int32_t>(),
39                                              .flat = fdp.ConsumeIntegral<int32_t>(),
40                                              .fuzz = fdp.ConsumeIntegral<int32_t>(),
41                                              .resolution = fdp.ConsumeIntegral<int32_t>(),
42                                      });
43     }
44 }
45 
setAxisInfos(ThreadSafeFuzzedDataProvider & fdp,FuzzEventHub & eventHub,int32_t id)46 void setAxisInfos(ThreadSafeFuzzedDataProvider& fdp, FuzzEventHub& eventHub, int32_t id) {
47     setAxisInfo(fdp, eventHub, id, ABS_MT_SLOT);
48     setAxisInfo(fdp, eventHub, id, ABS_MT_POSITION_X);
49     setAxisInfo(fdp, eventHub, id, ABS_MT_POSITION_Y);
50     setAxisInfo(fdp, eventHub, id, ABS_MT_PRESSURE);
51     setAxisInfo(fdp, eventHub, id, ABS_MT_ORIENTATION);
52     setAxisInfo(fdp, eventHub, id, ABS_MT_TOUCH_MAJOR);
53     setAxisInfo(fdp, eventHub, id, ABS_MT_TOUCH_MINOR);
54     setAxisInfo(fdp, eventHub, id, ABS_MT_WIDTH_MAJOR);
55     setAxisInfo(fdp, eventHub, id, ABS_MT_WIDTH_MINOR);
56 }
57 
58 const std::vector<std::string> boolPropertiesToFuzz = {
59         "gestureProp.Compute_Surface_Area_from_Pressure",
60         "gestureProp.Drumroll_Suppression_Enable",
61         "gestureProp.Fling_Buffer_Suppress_Zero_Length_Scrolls",
62         "gestureProp.Stationary_Wiggle_Filter_Enabled",
63 };
64 const std::vector<std::string> doublePropertiesToFuzz = {
65         "gestureProp.Fake_Timestamp_Delta",
66         "gestureProp.Finger_Moving_Energy",
67         "gestureProp.Finger_Moving_Hysteresis",
68         "gestureProp.IIR_a1",
69         "gestureProp.IIR_a2",
70         "gestureProp.IIR_b0",
71         "gestureProp.IIR_b1",
72         "gestureProp.IIR_b2",
73         "gestureProp.IIR_b3",
74         "gestureProp.Max_Allowed_Pressure_Change_Per_Sec",
75         "gestureProp.Max_Hysteresis_Pressure_Per_Sec",
76         "gestureProp.Max_Stationary_Move_Speed",
77         "gestureProp.Max_Stationary_Move_Speed_Hysteresis",
78         "gestureProp.Max_Stationary_Move_Suppress_Distance",
79         "gestureProp.Multiple_Palm_Width",
80         "gestureProp.Palm_Edge_Zone_Width",
81         "gestureProp.Palm_Eval_Timeout",
82         "gestureProp.Palm_Pressure",
83         "gestureProp.Palm_Width",
84         "gestureProp.Pressure_Calibration_Offset",
85         "gestureProp.Pressure_Calibration_Slope",
86         "gestureProp.Tap_Exclusion_Border_Width",
87         "gestureProp.Touchpad_Device_Output_Bias_on_X-Axis",
88         "gestureProp.Touchpad_Device_Output_Bias_on_Y-Axis",
89         "gestureProp.Two_Finger_Vertical_Close_Distance_Thresh",
90 };
91 
setDeviceSpecificConfig(ThreadSafeFuzzedDataProvider & fdp,FuzzEventHub & eventHub)92 void setDeviceSpecificConfig(ThreadSafeFuzzedDataProvider& fdp, FuzzEventHub& eventHub) {
93     // There are a great many gesture properties offered by the Gestures library, all of which could
94     // potentially be set in Input Device Configuration files. Maintaining a complete list is
95     // impractical, so instead we only fuzz properties which are used in at least one IDC file, or
96     // which are likely to be used in future (e.g. ones for controlling palm rejection).
97 
98     if (fdp.ConsumeBool()) {
99         eventHub.addProperty("gestureProp.Touchpad_Stack_Version",
100                              std::to_string(fdp.ConsumeIntegral<int>()));
101     }
102 
103     for (auto& propertyName : boolPropertiesToFuzz) {
104         if (fdp.ConsumeBool()) {
105             eventHub.addProperty(propertyName, fdp.ConsumeBool() ? "1" : "0");
106         }
107     }
108 
109     for (auto& propertyName : doublePropertiesToFuzz) {
110         if (fdp.ConsumeBool()) {
111             eventHub.addProperty(propertyName, std::to_string(fdp.ConsumeFloatingPoint<double>()));
112         }
113     }
114 
115     if (fdp.ConsumeBool()) {
116         eventHub.addProperty("gestureProp." + fdp.ConsumeRandomLengthString(),
117                              std::to_string(fdp.ConsumeIntegral<int>()));
118     }
119 }
120 
setTouchpadSettings(ThreadSafeFuzzedDataProvider & fdp,InputReaderConfiguration & config)121 void setTouchpadSettings(ThreadSafeFuzzedDataProvider& fdp, InputReaderConfiguration& config) {
122     config.touchpadPointerSpeed = fdp.ConsumeIntegralInRange(-7, 7);
123     config.touchpadNaturalScrollingEnabled = fdp.ConsumeBool();
124     config.touchpadTapToClickEnabled = fdp.ConsumeBool();
125     config.touchpadTapDraggingEnabled = fdp.ConsumeBool();
126     config.touchpadRightClickZoneEnabled = fdp.ConsumeBool();
127 
128     config.pointerCaptureRequest.window = fdp.ConsumeBool() ? sp<BBinder>::make() : nullptr;
129     config.pointerCaptureRequest.seq = fdp.ConsumeIntegral<uint32_t>();
130 }
131 
132 } // namespace
133 
LLVMFuzzerTestOneInput(uint8_t * data,size_t size)134 extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
135     std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp =
136             std::make_shared<ThreadSafeFuzzedDataProvider>(data, size);
137 
138     // Create mocked objects to support the fuzzed input mapper.
139     std::shared_ptr<FuzzEventHub> eventHub = std::make_shared<FuzzEventHub>(fdp);
140     FuzzInputReaderContext context(eventHub, fdp);
141     InputDevice device = getFuzzedInputDevice(*fdp, &context);
142 
143     setAxisInfos(*fdp, *eventHub.get(), device.getId());
144     setDeviceSpecificConfig(*fdp, *eventHub.get());
145 
146     InputReaderConfiguration policyConfig;
147     // Some settings are fuzzed here, as well as in the main loop, to provide randomized data to the
148     // TouchpadInputMapper constructor.
149     setTouchpadSettings(*fdp, policyConfig);
150     TouchpadInputMapper& mapper =
151             getMapperForDevice<ThreadSafeFuzzedDataProvider, TouchpadInputMapper>(*fdp, device,
152                                                                                   policyConfig);
153 
154     // Loop through mapper operations until randomness is exhausted.
155     while (fdp->remaining_bytes() > 0) {
156         fdp->PickValueInArray<std::function<void()>>({
157                 [&]() -> void {
158                     std::string dump;
159                     mapper.dump(dump);
160                 },
161                 [&]() -> void {
162                     InputDeviceInfo info;
163                     mapper.populateDeviceInfo(info);
164                 },
165                 [&]() -> void { mapper.getSources(); },
166                 [&]() -> void {
167                     setTouchpadSettings(*fdp, policyConfig);
168                     std::list<NotifyArgs> unused =
169                             mapper.reconfigure(fdp->ConsumeIntegral<nsecs_t>(), policyConfig,
170                                                InputReaderConfiguration::Change(
171                                                        fdp->ConsumeIntegral<uint32_t>()));
172                 },
173                 [&]() -> void {
174                     std::list<NotifyArgs> unused = mapper.reset(fdp->ConsumeIntegral<nsecs_t>());
175                 },
176                 [&]() -> void {
177                     RawEvent event = getFuzzedRawEvent(*fdp);
178                     std::list<NotifyArgs> unused = mapper.process(event);
179                 },
180         })();
181     }
182 
183     return 0;
184 }
185 
186 } // namespace android
187