1 /*
2 * Copyright (C) 2019 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 <benchmark/benchmark.h>
18
19 #include <android/os/IInputConstants.h>
20 #include <binder/Binder.h>
21 #include "../dispatcher/InputDispatcher.h"
22 #include "../tests/FakeApplicationHandle.h"
23 #include "../tests/FakeInputDispatcherPolicy.h"
24 #include "../tests/FakeWindows.h"
25
26 using android::base::Result;
27 using android::gui::WindowInfo;
28 using android::os::IInputConstants;
29 using android::os::InputEventInjectionResult;
30 using android::os::InputEventInjectionSync;
31
32 namespace android::inputdispatcher {
33
34 namespace {
35
36 // An arbitrary device id.
37 constexpr DeviceId DEVICE_ID = 1;
38
39 // An arbitrary display id
40 constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
41
42 static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 5s;
43
now()44 static nsecs_t now() {
45 return systemTime(SYSTEM_TIME_MONOTONIC);
46 }
47
generateMotionEvent()48 static MotionEvent generateMotionEvent() {
49 PointerProperties pointerProperties[1];
50 PointerCoords pointerCoords[1];
51
52 pointerProperties[0].clear();
53 pointerProperties[0].id = 0;
54 pointerProperties[0].toolType = ToolType::FINGER;
55
56 pointerCoords[0].clear();
57 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
58 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 100);
59
60 const nsecs_t currentTime = now();
61
62 ui::Transform identityTransform;
63 MotionEvent event;
64 event.initialize(IInputConstants::INVALID_INPUT_EVENT_ID, DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
65 ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN,
66 /* actionButton */ 0, /* flags */ 0,
67 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
68 identityTransform, /* xPrecision */ 0,
69 /* yPrecision */ 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
70 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, currentTime,
71 currentTime,
72 /*pointerCount*/ 1, pointerProperties, pointerCoords);
73 return event;
74 }
75
generateMotionArgs()76 static NotifyMotionArgs generateMotionArgs() {
77 PointerProperties pointerProperties[1];
78 PointerCoords pointerCoords[1];
79
80 pointerProperties[0].clear();
81 pointerProperties[0].id = 0;
82 pointerProperties[0].toolType = ToolType::FINGER;
83
84 pointerCoords[0].clear();
85 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
86 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 100);
87
88 const nsecs_t currentTime = now();
89 // Define a valid motion event.
90 NotifyMotionArgs args(IInputConstants::INVALID_INPUT_EVENT_ID, currentTime, currentTime,
91 DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
92 POLICY_FLAG_PASS_TO_USER, AMOTION_EVENT_ACTION_DOWN,
93 /* actionButton */ 0, /* flags */ 0, AMETA_NONE, /* buttonState */ 0,
94 MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
95 pointerProperties, pointerCoords,
96 /* xPrecision */ 0, /* yPrecision */ 0,
97 AMOTION_EVENT_INVALID_CURSOR_POSITION,
98 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
99
100 return args;
101 }
102
benchmarkNotifyMotion(benchmark::State & state)103 static void benchmarkNotifyMotion(benchmark::State& state) {
104 // Create dispatcher
105 FakeInputDispatcherPolicy fakePolicy;
106 auto dispatcher = std::make_unique<InputDispatcher>(fakePolicy);
107 dispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
108 dispatcher->start();
109
110 // Create a window that will receive motion events
111 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
112 sp<FakeWindowHandle> window =
113 sp<FakeWindowHandle>::make(application, dispatcher, "Fake Window", DISPLAY_ID);
114
115 dispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
116
117 NotifyMotionArgs motionArgs = generateMotionArgs();
118
119 for (auto _ : state) {
120 // Send ACTION_DOWN
121 motionArgs.action = AMOTION_EVENT_ACTION_DOWN;
122 motionArgs.downTime = now();
123 motionArgs.eventTime = motionArgs.downTime;
124 dispatcher->notifyMotion(motionArgs);
125
126 // Send ACTION_UP
127 motionArgs.action = AMOTION_EVENT_ACTION_UP;
128 motionArgs.eventTime = now();
129 dispatcher->notifyMotion(motionArgs);
130
131 window->consumeMotionEvent();
132 window->consumeMotionEvent();
133 }
134
135 dispatcher->stop();
136 }
137
benchmarkInjectMotion(benchmark::State & state)138 static void benchmarkInjectMotion(benchmark::State& state) {
139 // Create dispatcher
140 FakeInputDispatcherPolicy fakePolicy;
141 auto dispatcher = std::make_unique<InputDispatcher>(fakePolicy);
142 dispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
143 dispatcher->start();
144
145 // Create a window that will receive motion events
146 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
147 sp<FakeWindowHandle> window =
148 sp<FakeWindowHandle>::make(application, dispatcher, "Fake Window", DISPLAY_ID);
149
150 dispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
151
152 for (auto _ : state) {
153 MotionEvent event = generateMotionEvent();
154 // Send ACTION_DOWN
155 dispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
156 INJECT_EVENT_TIMEOUT,
157 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
158
159 // Send ACTION_UP
160 event.setAction(AMOTION_EVENT_ACTION_UP);
161 dispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
162 INJECT_EVENT_TIMEOUT,
163 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
164
165 window->consumeMotionEvent();
166 window->consumeMotionEvent();
167 }
168
169 dispatcher->stop();
170 }
171
benchmarkOnWindowInfosChanged(benchmark::State & state)172 static void benchmarkOnWindowInfosChanged(benchmark::State& state) {
173 // Create dispatcher
174 FakeInputDispatcherPolicy fakePolicy;
175 auto dispatcher = std::make_unique<InputDispatcher>(fakePolicy);
176 dispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
177 dispatcher->start();
178
179 // Create a window
180 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
181 sp<FakeWindowHandle> window =
182 sp<FakeWindowHandle>::make(application, dispatcher, "Fake Window", DISPLAY_ID);
183
184 std::vector<gui::WindowInfo> windowInfos{*window->getInfo()};
185 gui::DisplayInfo info;
186 info.displayId = window->getInfo()->displayId;
187 std::vector<gui::DisplayInfo> displayInfos{info};
188
189 for (auto _ : state) {
190 dispatcher->onWindowInfosChanged(
191 {windowInfos, displayInfos, /*vsyncId=*/0, /*timestamp=*/0});
192 dispatcher->onWindowInfosChanged(
193 {/*windowInfos=*/{}, /*displayInfos=*/{}, /*vsyncId=*/{}, /*timestamp=*/0});
194 }
195 dispatcher->stop();
196 }
197
198 } // namespace
199
200 BENCHMARK(benchmarkNotifyMotion);
201 BENCHMARK(benchmarkInjectMotion);
202 BENCHMARK(benchmarkOnWindowInfosChanged);
203
204 } // namespace android::inputdispatcher
205
206 BENCHMARK_MAIN();
207