• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <fuzzer/FuzzedDataProvider.h>
18 
19 namespace android {
20 
21 namespace {
22 static constexpr int32_t MAX_RANDOM_POINTERS = 4;
23 static constexpr int32_t MAX_RANDOM_DEVICES = 4;
24 } // namespace
25 
getFuzzedMotionAction(FuzzedDataProvider & fdp)26 int getFuzzedMotionAction(FuzzedDataProvider& fdp) {
27     int actionMasked = fdp.PickValueInArray<int>({
28             AMOTION_EVENT_ACTION_DOWN, AMOTION_EVENT_ACTION_UP, AMOTION_EVENT_ACTION_MOVE,
29             AMOTION_EVENT_ACTION_HOVER_ENTER, AMOTION_EVENT_ACTION_HOVER_MOVE,
30             AMOTION_EVENT_ACTION_HOVER_EXIT, AMOTION_EVENT_ACTION_CANCEL,
31             // do not inject AMOTION_EVENT_ACTION_OUTSIDE,
32             AMOTION_EVENT_ACTION_SCROLL, AMOTION_EVENT_ACTION_POINTER_DOWN,
33             AMOTION_EVENT_ACTION_POINTER_UP,
34             // do not send buttons until verifier supports them
35             // AMOTION_EVENT_ACTION_BUTTON_PRESS,
36             // AMOTION_EVENT_ACTION_BUTTON_RELEASE,
37     });
38     switch (actionMasked) {
39         case AMOTION_EVENT_ACTION_POINTER_DOWN:
40         case AMOTION_EVENT_ACTION_POINTER_UP: {
41             const int32_t index = fdp.ConsumeIntegralInRange(0, MAX_RANDOM_POINTERS - 1);
42             const int32_t action =
43                     actionMasked | (index << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
44             return action;
45         }
46         default:
47             return actionMasked;
48     }
49 }
50 
51 /**
52  * For now, focus on the 3 main sources.
53  */
getFuzzedSource(FuzzedDataProvider & fdp)54 int getFuzzedSource(FuzzedDataProvider& fdp) {
55     return fdp.PickValueInArray<int>({
56             // AINPUT_SOURCE_UNKNOWN,
57             // AINPUT_SOURCE_KEYBOARD,
58             // AINPUT_SOURCE_DPAD,
59             // AINPUT_SOURCE_GAMEPAD,
60             AINPUT_SOURCE_TOUCHSCREEN, AINPUT_SOURCE_MOUSE, AINPUT_SOURCE_STYLUS,
61             // AINPUT_SOURCE_BLUETOOTH_STYLUS,
62             // AINPUT_SOURCE_TRACKBALL,
63             // AINPUT_SOURCE_MOUSE_RELATIVE,
64             // AINPUT_SOURCE_TOUCHPAD,
65             // AINPUT_SOURCE_TOUCH_NAVIGATION,
66             // AINPUT_SOURCE_JOYSTICK,
67             // AINPUT_SOURCE_HDMI,
68             // AINPUT_SOURCE_SENSOR,
69             // AINPUT_SOURCE_ROTARY_ENCODER,
70             // AINPUT_SOURCE_ANY,
71     });
72 }
73 
getFuzzedButtonState(FuzzedDataProvider & fdp)74 int getFuzzedButtonState(FuzzedDataProvider& fdp) {
75     return fdp.PickValueInArray<int>({
76             0,
77             // AMOTION_EVENT_BUTTON_PRIMARY,
78             // AMOTION_EVENT_BUTTON_SECONDARY,
79             // AMOTION_EVENT_BUTTON_TERTIARY,
80             // AMOTION_EVENT_BUTTON_BACK,
81             // AMOTION_EVENT_BUTTON_FORWARD,
82             // AMOTION_EVENT_BUTTON_STYLUS_PRIMARY,
83             // AMOTION_EVENT_BUTTON_STYLUS_SECONDARY,
84     });
85 }
86 
getFuzzedFlags(FuzzedDataProvider & fdp,int32_t action)87 int32_t getFuzzedFlags(FuzzedDataProvider& fdp, int32_t action) {
88     constexpr std::array<int32_t, 4> FLAGS{
89             AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
90             AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED,
91             AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT,
92             AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE,
93     };
94 
95     int32_t flags = 0;
96     for (size_t i = 0; i < fdp.ConsumeIntegralInRange(size_t(0), FLAGS.size()); i++) {
97         flags |= fdp.PickValueInArray<int32_t>(FLAGS);
98     }
99     if (action == AMOTION_EVENT_ACTION_CANCEL) {
100         flags |= AMOTION_EVENT_FLAG_CANCELED;
101     }
102     if (MotionEvent::getActionMasked(action) == AMOTION_EVENT_ACTION_POINTER_UP) {
103         if (fdp.ConsumeBool()) {
104             flags |= AMOTION_EVENT_FLAG_CANCELED;
105         }
106     }
107     return flags;
108 }
109 
getFuzzedPointerCount(FuzzedDataProvider & fdp,int32_t action)110 int32_t getFuzzedPointerCount(FuzzedDataProvider& fdp, int32_t action) {
111     switch (MotionEvent::getActionMasked(action)) {
112         case AMOTION_EVENT_ACTION_DOWN:
113         case AMOTION_EVENT_ACTION_UP: {
114             return 1;
115         }
116         case AMOTION_EVENT_ACTION_OUTSIDE:
117         case AMOTION_EVENT_ACTION_CANCEL:
118         case AMOTION_EVENT_ACTION_MOVE:
119             return fdp.ConsumeIntegralInRange<int32_t>(1, MAX_RANDOM_POINTERS);
120         case AMOTION_EVENT_ACTION_HOVER_ENTER:
121         case AMOTION_EVENT_ACTION_HOVER_MOVE:
122         case AMOTION_EVENT_ACTION_HOVER_EXIT:
123             return 1;
124         case AMOTION_EVENT_ACTION_SCROLL:
125             return 1;
126         case AMOTION_EVENT_ACTION_POINTER_DOWN:
127         case AMOTION_EVENT_ACTION_POINTER_UP: {
128             const uint8_t actionIndex = MotionEvent::getActionIndex(action);
129             const int32_t count =
130                     std::max(actionIndex + 1,
131                              fdp.ConsumeIntegralInRange<int32_t>(1, MAX_RANDOM_POINTERS));
132             // Need to have at least 2 pointers
133             return std::max(2, count);
134         }
135         case AMOTION_EVENT_ACTION_BUTTON_PRESS:
136         case AMOTION_EVENT_ACTION_BUTTON_RELEASE: {
137             return 1;
138         }
139     }
140     return 1;
141 }
142 
getToolType(int32_t source)143 ToolType getToolType(int32_t source) {
144     switch (source) {
145         case AINPUT_SOURCE_TOUCHSCREEN:
146             return ToolType::FINGER;
147         case AINPUT_SOURCE_MOUSE:
148             return ToolType::MOUSE;
149         case AINPUT_SOURCE_STYLUS:
150             return ToolType::STYLUS;
151     }
152     return ToolType::UNKNOWN;
153 }
154 
now()155 inline nsecs_t now() {
156     return systemTime(SYSTEM_TIME_MONOTONIC);
157 }
158 
generateFuzzedMotionArgs(IdGenerator & idGenerator,FuzzedDataProvider & fdp,int32_t maxDisplays)159 NotifyMotionArgs generateFuzzedMotionArgs(IdGenerator& idGenerator, FuzzedDataProvider& fdp,
160                                           int32_t maxDisplays) {
161     // Create a basic motion event for testing
162     const int32_t source = getFuzzedSource(fdp);
163     const ToolType toolType = getToolType(source);
164     const int32_t action = getFuzzedMotionAction(fdp);
165     const int32_t pointerCount = getFuzzedPointerCount(fdp, action);
166     std::vector<PointerProperties> pointerProperties;
167     std::vector<PointerCoords> pointerCoords;
168     for (int i = 0; i < pointerCount; i++) {
169         PointerProperties properties{};
170         properties.id = i;
171         properties.toolType = toolType;
172         pointerProperties.push_back(properties);
173 
174         PointerCoords coords{};
175         coords.setAxisValue(AMOTION_EVENT_AXIS_X, fdp.ConsumeIntegralInRange<int>(-1000, 1000));
176         coords.setAxisValue(AMOTION_EVENT_AXIS_Y, fdp.ConsumeIntegralInRange<int>(-1000, 1000));
177         coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1);
178         pointerCoords.push_back(coords);
179     }
180 
181     const ui::LogicalDisplayId displayId{fdp.ConsumeIntegralInRange<int32_t>(0, maxDisplays - 1)};
182     const int32_t deviceId = fdp.ConsumeIntegralInRange<int32_t>(0, MAX_RANDOM_DEVICES - 1);
183 
184     // Current time +- 5 seconds
185     const nsecs_t currentTime = now();
186     const nsecs_t downTime =
187             fdp.ConsumeIntegralInRange<nsecs_t>(currentTime - 5E9, currentTime + 5E9);
188     const nsecs_t readTime = downTime;
189     const nsecs_t eventTime = fdp.ConsumeIntegralInRange<nsecs_t>(downTime, downTime + 1E9);
190 
191     const float cursorX = fdp.ConsumeIntegralInRange<int>(-10000, 10000);
192     const float cursorY = fdp.ConsumeIntegralInRange<int>(-10000, 10000);
193     return NotifyMotionArgs(idGenerator.nextId(), eventTime, readTime, deviceId, source, displayId,
194                             POLICY_FLAG_PASS_TO_USER, action,
195                             /*actionButton=*/fdp.ConsumeIntegral<int32_t>(),
196                             getFuzzedFlags(fdp, action), AMETA_NONE, getFuzzedButtonState(fdp),
197                             MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount,
198                             pointerProperties.data(), pointerCoords.data(),
199                             /*xPrecision=*/0,
200                             /*yPrecision=*/0, cursorX, cursorY, downTime,
201                             /*videoFrames=*/{});
202 }
203 
204 } // namespace android
205