File: FuzzedInputStream.h

package info (click to toggle)
android-platform-tools 35.0.2-1~exp6
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 211,716 kB
  • sloc: cpp: 995,749; java: 290,495; ansic: 145,647; xml: 58,531; python: 39,608; sh: 14,500; javascript: 5,198; asm: 4,866; makefile: 3,115; yacc: 769; awk: 368; ruby: 183; sql: 140; perl: 88; lex: 67
file content (204 lines) | stat: -rw-r--r-- 8,058 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 * Copyright 2023 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 <fuzzer/FuzzedDataProvider.h>

namespace android {

namespace {
static constexpr int32_t MAX_RANDOM_POINTERS = 4;
static constexpr int32_t MAX_RANDOM_DEVICES = 4;
} // namespace

int getFuzzedMotionAction(FuzzedDataProvider& fdp) {
    int actionMasked = fdp.PickValueInArray<int>({
            AMOTION_EVENT_ACTION_DOWN, AMOTION_EVENT_ACTION_UP, AMOTION_EVENT_ACTION_MOVE,
            AMOTION_EVENT_ACTION_HOVER_ENTER, AMOTION_EVENT_ACTION_HOVER_MOVE,
            AMOTION_EVENT_ACTION_HOVER_EXIT, AMOTION_EVENT_ACTION_CANCEL,
            // do not inject AMOTION_EVENT_ACTION_OUTSIDE,
            AMOTION_EVENT_ACTION_SCROLL, AMOTION_EVENT_ACTION_POINTER_DOWN,
            AMOTION_EVENT_ACTION_POINTER_UP,
            // do not send buttons until verifier supports them
            // AMOTION_EVENT_ACTION_BUTTON_PRESS,
            // AMOTION_EVENT_ACTION_BUTTON_RELEASE,
    });
    switch (actionMasked) {
        case AMOTION_EVENT_ACTION_POINTER_DOWN:
        case AMOTION_EVENT_ACTION_POINTER_UP: {
            const int32_t index = fdp.ConsumeIntegralInRange(0, MAX_RANDOM_POINTERS - 1);
            const int32_t action =
                    actionMasked | (index << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
            return action;
        }
        default:
            return actionMasked;
    }
}

/**
 * For now, focus on the 3 main sources.
 */
int getFuzzedSource(FuzzedDataProvider& fdp) {
    return fdp.PickValueInArray<int>({
            // AINPUT_SOURCE_UNKNOWN,
            // AINPUT_SOURCE_KEYBOARD,
            // AINPUT_SOURCE_DPAD,
            // AINPUT_SOURCE_GAMEPAD,
            AINPUT_SOURCE_TOUCHSCREEN, AINPUT_SOURCE_MOUSE, AINPUT_SOURCE_STYLUS,
            // AINPUT_SOURCE_BLUETOOTH_STYLUS,
            // AINPUT_SOURCE_TRACKBALL,
            // AINPUT_SOURCE_MOUSE_RELATIVE,
            // AINPUT_SOURCE_TOUCHPAD,
            // AINPUT_SOURCE_TOUCH_NAVIGATION,
            // AINPUT_SOURCE_JOYSTICK,
            // AINPUT_SOURCE_HDMI,
            // AINPUT_SOURCE_SENSOR,
            // AINPUT_SOURCE_ROTARY_ENCODER,
            // AINPUT_SOURCE_ANY,
    });
}

int getFuzzedButtonState(FuzzedDataProvider& fdp) {
    return fdp.PickValueInArray<int>({
            0,
            // AMOTION_EVENT_BUTTON_PRIMARY,
            // AMOTION_EVENT_BUTTON_SECONDARY,
            // AMOTION_EVENT_BUTTON_TERTIARY,
            // AMOTION_EVENT_BUTTON_BACK,
            // AMOTION_EVENT_BUTTON_FORWARD,
            // AMOTION_EVENT_BUTTON_STYLUS_PRIMARY,
            // AMOTION_EVENT_BUTTON_STYLUS_SECONDARY,
    });
}

int32_t getFuzzedFlags(FuzzedDataProvider& fdp, int32_t action) {
    constexpr std::array<int32_t, 4> FLAGS{
            AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
            AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED,
            AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT,
            AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE,
    };

    int32_t flags = 0;
    for (size_t i = 0; i < fdp.ConsumeIntegralInRange(size_t(0), FLAGS.size()); i++) {
        flags |= fdp.PickValueInArray<int32_t>(FLAGS);
    }
    if (action == AMOTION_EVENT_ACTION_CANCEL) {
        flags |= AMOTION_EVENT_FLAG_CANCELED;
    }
    if (MotionEvent::getActionMasked(action) == AMOTION_EVENT_ACTION_POINTER_UP) {
        if (fdp.ConsumeBool()) {
            flags |= AMOTION_EVENT_FLAG_CANCELED;
        }
    }
    return flags;
}

int32_t getFuzzedPointerCount(FuzzedDataProvider& fdp, int32_t action) {
    switch (MotionEvent::getActionMasked(action)) {
        case AMOTION_EVENT_ACTION_DOWN:
        case AMOTION_EVENT_ACTION_UP: {
            return 1;
        }
        case AMOTION_EVENT_ACTION_OUTSIDE:
        case AMOTION_EVENT_ACTION_CANCEL:
        case AMOTION_EVENT_ACTION_MOVE:
            return fdp.ConsumeIntegralInRange<int32_t>(1, MAX_RANDOM_POINTERS);
        case AMOTION_EVENT_ACTION_HOVER_ENTER:
        case AMOTION_EVENT_ACTION_HOVER_MOVE:
        case AMOTION_EVENT_ACTION_HOVER_EXIT:
            return 1;
        case AMOTION_EVENT_ACTION_SCROLL:
            return 1;
        case AMOTION_EVENT_ACTION_POINTER_DOWN:
        case AMOTION_EVENT_ACTION_POINTER_UP: {
            const uint8_t actionIndex = MotionEvent::getActionIndex(action);
            const int32_t count =
                    std::max(actionIndex + 1,
                             fdp.ConsumeIntegralInRange<int32_t>(1, MAX_RANDOM_POINTERS));
            // Need to have at least 2 pointers
            return std::max(2, count);
        }
        case AMOTION_EVENT_ACTION_BUTTON_PRESS:
        case AMOTION_EVENT_ACTION_BUTTON_RELEASE: {
            return 1;
        }
    }
    return 1;
}

ToolType getToolType(int32_t source) {
    switch (source) {
        case AINPUT_SOURCE_TOUCHSCREEN:
            return ToolType::FINGER;
        case AINPUT_SOURCE_MOUSE:
            return ToolType::MOUSE;
        case AINPUT_SOURCE_STYLUS:
            return ToolType::STYLUS;
    }
    return ToolType::UNKNOWN;
}

inline nsecs_t now() {
    return systemTime(SYSTEM_TIME_MONOTONIC);
}

NotifyMotionArgs generateFuzzedMotionArgs(IdGenerator& idGenerator, FuzzedDataProvider& fdp,
                                          int32_t maxDisplays) {
    // Create a basic motion event for testing
    const int32_t source = getFuzzedSource(fdp);
    const ToolType toolType = getToolType(source);
    const int32_t action = getFuzzedMotionAction(fdp);
    const int32_t pointerCount = getFuzzedPointerCount(fdp, action);
    std::vector<PointerProperties> pointerProperties;
    std::vector<PointerCoords> pointerCoords;
    for (int i = 0; i < pointerCount; i++) {
        PointerProperties properties{};
        properties.id = i;
        properties.toolType = toolType;
        pointerProperties.push_back(properties);

        PointerCoords coords{};
        coords.setAxisValue(AMOTION_EVENT_AXIS_X, fdp.ConsumeIntegralInRange<int>(-1000, 1000));
        coords.setAxisValue(AMOTION_EVENT_AXIS_Y, fdp.ConsumeIntegralInRange<int>(-1000, 1000));
        coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1);
        pointerCoords.push_back(coords);
    }

    const int32_t displayId = fdp.ConsumeIntegralInRange<int32_t>(0, maxDisplays - 1);
    const int32_t deviceId = fdp.ConsumeIntegralInRange<int32_t>(0, MAX_RANDOM_DEVICES - 1);

    // Current time +- 5 seconds
    const nsecs_t currentTime = now();
    const nsecs_t downTime =
            fdp.ConsumeIntegralInRange<nsecs_t>(currentTime - 5E9, currentTime + 5E9);
    const nsecs_t readTime = downTime;
    const nsecs_t eventTime = fdp.ConsumeIntegralInRange<nsecs_t>(downTime, downTime + 1E9);

    const float cursorX = fdp.ConsumeIntegralInRange<int>(-10000, 10000);
    const float cursorY = fdp.ConsumeIntegralInRange<int>(-10000, 10000);
    return NotifyMotionArgs(idGenerator.nextId(), eventTime, readTime, deviceId, source, displayId,
                            POLICY_FLAG_PASS_TO_USER, action,
                            /*actionButton=*/fdp.ConsumeIntegral<int32_t>(),
                            getFuzzedFlags(fdp, action), AMETA_NONE, getFuzzedButtonState(fdp),
                            MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount,
                            pointerProperties.data(), pointerCoords.data(),
                            /*xPrecision=*/0,
                            /*yPrecision=*/0, cursorX, cursorY, downTime,
                            /*videoFrames=*/{});
}

} // namespace android