blob: 4a6efa67a77ab357fbe80668b792d1236eb364a1 [file] [log] [blame]
Siarhei Vishniakou473174e2017-12-27 16:44:42 -08001/*
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#define LOG_TAG "InputClassifier"
18
19#include "InputClassifier.h"
20
21#include <algorithm>
Siarhei Vishniakoua028c442019-02-04 14:33:23 -080022#include <android-base/stringprintf.h>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080023#include <cmath>
24#include <inttypes.h>
25#include <log/log.h>
26#if defined(__linux__)
27 #include <pthread.h>
28#endif
29#include <server_configurable_flags/get_flags.h>
Siarhei Vishniakoua028c442019-02-04 14:33:23 -080030#include <unordered_set>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080031
32#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
33
Siarhei Vishniakoua028c442019-02-04 14:33:23 -080034#define INDENT1 " "
35#define INDENT2 " "
36#define INDENT3 " "
37#define INDENT4 " "
38#define INDENT5 " "
39
40using android::base::StringPrintf;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080041using android::hardware::hidl_bitfield;
42using android::hardware::hidl_vec;
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -080043using android::hardware::Return;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080044using namespace android::hardware::input;
45
46namespace android {
47
48static constexpr bool DEBUG = false;
49
50// Category (=namespace) name for the input settings that are applied at boot time
51static const char* INPUT_NATIVE_BOOT = "input_native_boot";
52// Feature flag name for the deep press feature
53static const char* DEEP_PRESS_ENABLED = "deep_press_enabled";
54
55//Max number of elements to store in mEvents.
56static constexpr size_t MAX_EVENTS = 5;
57
58template<class K, class V>
59static V getValueForKey(const std::unordered_map<K, V>& map, K key, V defaultValue) {
60 auto it = map.find(key);
61 if (it == map.end()) {
62 return defaultValue;
63 }
64 return it->second;
65}
66
67static common::V1_0::Source getSource(uint32_t source) {
68 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_UNKNOWN) ==
69 common::V1_0::Source::UNKNOWN, "SOURCE_UNKNOWN mismatch");
70 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_KEYBOARD) ==
71 common::V1_0::Source::KEYBOARD, "SOURCE_KEYBOARD mismatch");
72 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_DPAD) ==
73 common::V1_0::Source::DPAD, "SOURCE_DPAD mismatch");
74 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_GAMEPAD) ==
75 common::V1_0::Source::GAMEPAD, "SOURCE_GAMEPAD mismatch");
76 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHSCREEN) ==
77 common::V1_0::Source::TOUCHSCREEN, "SOURCE_TOUCHSCREEN mismatch");
78 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE) ==
79 common::V1_0::Source::MOUSE, "SOURCE_MOUSE mismatch");
80 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_STYLUS) ==
81 common::V1_0::Source::STYLUS, "SOURCE_STYLUS mismatch");
82 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_BLUETOOTH_STYLUS) ==
83 common::V1_0::Source::BLUETOOTH_STYLUS, "SOURCE_BLUETOOTH_STYLUS mismatch");
84 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TRACKBALL) ==
85 common::V1_0::Source::TRACKBALL, "SOURCE_TRACKBALL mismatch");
86 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE_RELATIVE) ==
87 common::V1_0::Source::MOUSE_RELATIVE, "SOURCE_MOUSE_RELATIVE mismatch");
88 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHPAD) ==
89 common::V1_0::Source::TOUCHPAD, "SOURCE_TOUCHPAD mismatch");
90 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCH_NAVIGATION) ==
91 common::V1_0::Source::TOUCH_NAVIGATION, "SOURCE_TOUCH_NAVIGATION mismatch");
92 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_JOYSTICK) ==
93 common::V1_0::Source::JOYSTICK, "SOURCE_JOYSTICK mismatch");
94 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ROTARY_ENCODER) ==
95 common::V1_0::Source::ROTARY_ENCODER, "SOURCE_ROTARY_ENCODER mismatch");
96 static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ANY) ==
97 common::V1_0::Source::ANY, "SOURCE_ANY mismatch");
98 return static_cast<common::V1_0::Source>(source);
99}
100
101static common::V1_0::Action getAction(int32_t actionMasked) {
102 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_DOWN) ==
103 common::V1_0::Action::DOWN, "ACTION_DOWN mismatch");
104 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_UP) ==
105 common::V1_0::Action::UP, "ACTION_UP mismatch");
106 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_MOVE) ==
107 common::V1_0::Action::MOVE, "ACTION_MOVE mismatch");
108 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_CANCEL) ==
109 common::V1_0::Action::CANCEL, "ACTION_CANCEL mismatch");
110 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_OUTSIDE) ==
111 common::V1_0::Action::OUTSIDE, "ACTION_OUTSIDE mismatch");
112 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_DOWN) ==
113 common::V1_0::Action::POINTER_DOWN, "ACTION_POINTER_DOWN mismatch");
114 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_UP) ==
115 common::V1_0::Action::POINTER_UP, "ACTION_POINTER_UP mismatch");
116 static_assert(static_cast<common::V1_0::Action>( AMOTION_EVENT_ACTION_HOVER_MOVE) ==
117 common::V1_0::Action::HOVER_MOVE, "ACTION_HOVER_MOVE mismatch");
118 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_SCROLL) ==
119 common::V1_0::Action::SCROLL, "ACTION_SCROLL mismatch");
120 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_ENTER) ==
121 common::V1_0::Action::HOVER_ENTER, "ACTION_HOVER_ENTER mismatch");
122 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_EXIT) ==
123 common::V1_0::Action::HOVER_EXIT, "ACTION_HOVER_EXIT mismatch");
124 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_PRESS) ==
125 common::V1_0::Action::BUTTON_PRESS, "ACTION_BUTTON_PRESS mismatch");
126 static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_RELEASE) ==
127 common::V1_0::Action::BUTTON_RELEASE, "ACTION_BUTTON_RELEASE mismatch");
128 return static_cast<common::V1_0::Action>(actionMasked);
129}
130
131static common::V1_0::Button getActionButton(int32_t actionButton) {
132 static_assert(static_cast<common::V1_0::Button>(0) ==
133 common::V1_0::Button::NONE, "BUTTON_NONE mismatch");
134 static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_PRIMARY) ==
135 common::V1_0::Button::PRIMARY, "BUTTON_PRIMARY mismatch");
136 static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_SECONDARY) ==
137 common::V1_0::Button::SECONDARY, "BUTTON_SECONDARY mismatch");
138 static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_TERTIARY) ==
139 common::V1_0::Button::TERTIARY, "BUTTON_TERTIARY mismatch");
140 static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_BACK) ==
141 common::V1_0::Button::BACK, "BUTTON_BACK mismatch");
142 static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_FORWARD) ==
143 common::V1_0::Button::FORWARD, "BUTTON_FORWARD mismatch");
144 static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) ==
145 common::V1_0::Button::STYLUS_PRIMARY, "BUTTON_STYLUS_PRIMARY mismatch");
146 static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY) ==
147 common::V1_0::Button::STYLUS_SECONDARY, "BUTTON_STYLUS_SECONDARY mismatch");
148 return static_cast<common::V1_0::Button>(actionButton);
149}
150
151static hidl_bitfield<common::V1_0::Flag> getFlags(int32_t flags) {
152 static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED) ==
153 common::V1_0::Flag::WINDOW_IS_OBSCURED);
154 static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE) ==
155 common::V1_0::Flag::IS_GENERATED_GESTURE);
156 static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_TAINTED) ==
157 common::V1_0::Flag::TAINTED);
158 return static_cast<hidl_bitfield<common::V1_0::Flag>>(flags);
159}
160
161static hidl_bitfield<common::V1_0::PolicyFlag> getPolicyFlags(int32_t flags) {
162 static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_WAKE) ==
163 common::V1_0::PolicyFlag::WAKE);
164 static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_VIRTUAL) ==
165 common::V1_0::PolicyFlag::VIRTUAL);
166 static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FUNCTION) ==
167 common::V1_0::PolicyFlag::FUNCTION);
168 static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_GESTURE) ==
169 common::V1_0::PolicyFlag::GESTURE);
170 static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INJECTED) ==
171 common::V1_0::PolicyFlag::INJECTED);
172 static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_TRUSTED) ==
173 common::V1_0::PolicyFlag::TRUSTED);
174 static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FILTERED) ==
175 common::V1_0::PolicyFlag::FILTERED);
176 static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_DISABLE_KEY_REPEAT) ==
177 common::V1_0::PolicyFlag::DISABLE_KEY_REPEAT);
178 static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INTERACTIVE) ==
179 common::V1_0::PolicyFlag::INTERACTIVE);
180 static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_PASS_TO_USER) ==
181 common::V1_0::PolicyFlag::PASS_TO_USER);
182 return static_cast<hidl_bitfield<common::V1_0::PolicyFlag>>(flags);
183}
184
185static hidl_bitfield<common::V1_0::EdgeFlag> getEdgeFlags(int32_t flags) {
186 static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_NONE) ==
187 common::V1_0::EdgeFlag::NONE);
188 static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_TOP) ==
189 common::V1_0::EdgeFlag::TOP);
190 static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_BOTTOM) ==
191 common::V1_0::EdgeFlag::BOTTOM);
192 static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_LEFT) ==
193 common::V1_0::EdgeFlag::LEFT);
194 static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_RIGHT) ==
195 common::V1_0::EdgeFlag::RIGHT);
196 return static_cast<hidl_bitfield<common::V1_0::EdgeFlag>>(flags);
197}
198
199static hidl_bitfield<common::V1_0::Meta> getMetastate(int32_t state) {
200 static_assert(static_cast<common::V1_0::Meta>(AMETA_NONE) ==
201 common::V1_0::Meta::NONE);
202 static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_ON) ==
203 common::V1_0::Meta::ALT_ON);
204 static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_LEFT_ON) ==
205 common::V1_0::Meta::ALT_LEFT_ON);
206 static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_RIGHT_ON) ==
207 common::V1_0::Meta::ALT_RIGHT_ON);
208 static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_ON) ==
209 common::V1_0::Meta::SHIFT_ON);
210 static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_LEFT_ON) ==
211 common::V1_0::Meta::SHIFT_LEFT_ON);
212 static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_RIGHT_ON) ==
213 common::V1_0::Meta::SHIFT_RIGHT_ON);
214 static_assert(static_cast<common::V1_0::Meta>(AMETA_SYM_ON) ==
215 common::V1_0::Meta::SYM_ON);
216 static_assert(static_cast<common::V1_0::Meta>(AMETA_FUNCTION_ON) ==
217 common::V1_0::Meta::FUNCTION_ON);
218 static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_ON) ==
219 common::V1_0::Meta::CTRL_ON);
220 static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_LEFT_ON) ==
221 common::V1_0::Meta::CTRL_LEFT_ON);
222 static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_RIGHT_ON) ==
223 common::V1_0::Meta::CTRL_RIGHT_ON);
224 static_assert(static_cast<common::V1_0::Meta>(AMETA_META_ON) ==
225 common::V1_0::Meta::META_ON);
226 static_assert(static_cast<common::V1_0::Meta>(AMETA_META_LEFT_ON) ==
227 common::V1_0::Meta::META_LEFT_ON);
228 static_assert(static_cast<common::V1_0::Meta>(AMETA_META_RIGHT_ON) ==
229 common::V1_0::Meta::META_RIGHT_ON);
230 static_assert(static_cast<common::V1_0::Meta>(AMETA_CAPS_LOCK_ON) ==
231 common::V1_0::Meta::CAPS_LOCK_ON);
232 static_assert(static_cast<common::V1_0::Meta>(AMETA_NUM_LOCK_ON) ==
233 common::V1_0::Meta::NUM_LOCK_ON);
234 static_assert(static_cast<common::V1_0::Meta>(AMETA_SCROLL_LOCK_ON) ==
235 common::V1_0::Meta::SCROLL_LOCK_ON);
236 return static_cast<hidl_bitfield<common::V1_0::Meta>>(state);
237}
238
239static hidl_bitfield<common::V1_0::Button> getButtonState(int32_t buttonState) {
240 // No need for static_assert here.
241 // The button values have already been asserted in getActionButton(..) above
242 return static_cast<hidl_bitfield<common::V1_0::Button>>(buttonState);
243}
244
245static common::V1_0::ToolType getToolType(int32_t toolType) {
246 static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_UNKNOWN) ==
247 common::V1_0::ToolType::UNKNOWN);
248 static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_FINGER) ==
249 common::V1_0::ToolType::FINGER);
250 static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_STYLUS) ==
251 common::V1_0::ToolType::STYLUS);
252 static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_MOUSE) ==
253 common::V1_0::ToolType::MOUSE);
254 static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_ERASER) ==
255 common::V1_0::ToolType::ERASER);
256 return static_cast<common::V1_0::ToolType>(toolType);
257}
258
259static common::V1_0::Axis getAxis(uint64_t axis) {
260 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_X) ==
261 common::V1_0::Axis::X);
262 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Y) ==
263 common::V1_0::Axis::Y);
264 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_PRESSURE) ==
265 common::V1_0::Axis::PRESSURE);
266 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SIZE) ==
267 common::V1_0::Axis::SIZE);
268 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MAJOR) ==
269 common::V1_0::Axis::TOUCH_MAJOR);
270 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MINOR) ==
271 common::V1_0::Axis::TOUCH_MINOR);
272 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MAJOR) ==
273 common::V1_0::Axis::TOOL_MAJOR);
274 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MINOR) ==
275 common::V1_0::Axis::TOOL_MINOR);
276 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_ORIENTATION) ==
277 common::V1_0::Axis::ORIENTATION);
278 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_VSCROLL) ==
279 common::V1_0::Axis::VSCROLL);
280 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HSCROLL) ==
281 common::V1_0::Axis::HSCROLL);
282 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Z) ==
283 common::V1_0::Axis::Z);
284 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RX) ==
285 common::V1_0::Axis::RX);
286 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RY) ==
287 common::V1_0::Axis::RY);
288 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RZ) ==
289 common::V1_0::Axis::RZ);
290 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_X) ==
291 common::V1_0::Axis::HAT_X);
292 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_Y) ==
293 common::V1_0::Axis::HAT_Y);
294 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_LTRIGGER) ==
295 common::V1_0::Axis::LTRIGGER);
296 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RTRIGGER) ==
297 common::V1_0::Axis::RTRIGGER);
298 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_THROTTLE) ==
299 common::V1_0::Axis::THROTTLE);
300 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RUDDER) ==
301 common::V1_0::Axis::RUDDER);
302 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_WHEEL) ==
303 common::V1_0::Axis::WHEEL);
304 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GAS) ==
305 common::V1_0::Axis::GAS);
306 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_BRAKE) ==
307 common::V1_0::Axis::BRAKE);
308 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_DISTANCE) ==
309 common::V1_0::Axis::DISTANCE);
310 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TILT) ==
311 common::V1_0::Axis::TILT);
312 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SCROLL) ==
313 common::V1_0::Axis::SCROLL);
314 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_X) ==
315 common::V1_0::Axis::RELATIVE_X);
316 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_Y) ==
317 common::V1_0::Axis::RELATIVE_Y);
318 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_1) ==
319 common::V1_0::Axis::GENERIC_1);
320 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_2) ==
321 common::V1_0::Axis::GENERIC_2);
322 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_3) ==
323 common::V1_0::Axis::GENERIC_3);
324 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_4) ==
325 common::V1_0::Axis::GENERIC_4);
326 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_5) ==
327 common::V1_0::Axis::GENERIC_5);
328 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_6) ==
329 common::V1_0::Axis::GENERIC_6);
330 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_7) ==
331 common::V1_0::Axis::GENERIC_7);
332 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_8) ==
333 common::V1_0::Axis::GENERIC_8);
334 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_9) ==
335 common::V1_0::Axis::GENERIC_9);
336 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_10) ==
337 common::V1_0::Axis::GENERIC_10);
338 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_11) ==
339 common::V1_0::Axis::GENERIC_11);
340 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_12) ==
341 common::V1_0::Axis::GENERIC_12);
342 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_13) ==
343 common::V1_0::Axis::GENERIC_13);
344 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_14) ==
345 common::V1_0::Axis::GENERIC_14);
346 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_15) ==
347 common::V1_0::Axis::GENERIC_15);
348 static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_16) ==
349 common::V1_0::Axis::GENERIC_16);
350 return static_cast<common::V1_0::Axis>(axis);
351}
352
353static common::V1_0::VideoFrame getHalVideoFrame(const TouchVideoFrame& frame) {
354 common::V1_0::VideoFrame out;
355 out.width = frame.getWidth();
356 out.height = frame.getHeight();
357 out.data = frame.getData();
358 struct timeval timestamp = frame.getTimestamp();
359 out.timestamp = seconds_to_nanoseconds(timestamp.tv_sec) +
360 microseconds_to_nanoseconds(timestamp.tv_usec);
361 return out;
362}
363
364static std::vector<common::V1_0::VideoFrame> convertVideoFrames(
365 const std::vector<TouchVideoFrame>& frames) {
366 std::vector<common::V1_0::VideoFrame> out;
367 for (const TouchVideoFrame& frame : frames) {
368 out.push_back(getHalVideoFrame(frame));
369 }
370 return out;
371}
372
373static uint8_t getActionIndex(int32_t action) {
374 return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
375 AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
376}
377
378static void getHidlPropertiesAndCoords(const NotifyMotionArgs& args,
379 std::vector<common::V1_0::PointerProperties>* outPointerProperties,
380 std::vector<common::V1_0::PointerCoords>* outPointerCoords) {
381 outPointerProperties->reserve(args.pointerCount);
382 outPointerCoords->reserve(args.pointerCount);
383 for (size_t i = 0; i < args.pointerCount; i++) {
384 common::V1_0::PointerProperties properties;
385 properties.id = args.pointerProperties[i].id;
386 properties.toolType = getToolType(args.pointerProperties[i].toolType);
387 outPointerProperties->push_back(properties);
388
389 common::V1_0::PointerCoords coords;
390 BitSet64 bits (args.pointerCoords[i].bits);
391 std::vector<float> values;
392 size_t index = 0;
393 while (!bits.isEmpty()) {
394 uint32_t axis = bits.clearFirstMarkedBit();
395 coords.bits |= 1 << static_cast<uint64_t>(getAxis(axis));
396 float value = args.pointerCoords[i].values[index++];
397 values.push_back(value);
398 }
399 coords.values = values;
400 outPointerCoords->push_back(coords);
401 }
402}
403
404static common::V1_0::MotionEvent getMotionEvent(const NotifyMotionArgs& args) {
405 common::V1_0::MotionEvent event;
406 event.deviceId = args.deviceId;
407 event.source = getSource(args.source);
408 event.displayId = args.displayId;
409 event.downTime = args.downTime;
410 event.eventTime = args.eventTime;
411 event.action = getAction(args.action & AMOTION_EVENT_ACTION_MASK);
412 event.actionIndex = getActionIndex(args.action);
413 event.actionButton = getActionButton(args.actionButton);
414 event.flags = getFlags(args.flags);
415 event.policyFlags = getPolicyFlags(args.policyFlags);
416 event.edgeFlags = getEdgeFlags(args.edgeFlags);
417 event.metaState = getMetastate(args.metaState);
418 event.buttonState = getButtonState(args.buttonState);
419 event.xPrecision = args.xPrecision;
420 event.yPrecision = args.yPrecision;
421
422 std::vector<common::V1_0::PointerProperties> pointerProperties;
423 std::vector<common::V1_0::PointerCoords> pointerCoords;
424 getHidlPropertiesAndCoords(args, /*out*/&pointerProperties, /*out*/&pointerCoords);
425 event.pointerProperties = pointerProperties;
426 event.pointerCoords = pointerCoords;
427
428 event.deviceTimestamp = args.deviceTimestamp;
429 event.frames = convertVideoFrames(args.videoFrames);
430
431 return event;
432}
433
434static MotionClassification getMotionClassification(common::V1_0::Classification classification) {
435 static_assert(MotionClassification::NONE ==
436 static_cast<MotionClassification>(common::V1_0::Classification::NONE));
437 static_assert(MotionClassification::AMBIGUOUS_GESTURE ==
438 static_cast<MotionClassification>(common::V1_0::Classification::AMBIGUOUS_GESTURE));
439 static_assert(MotionClassification::DEEP_PRESS ==
440 static_cast<MotionClassification>(common::V1_0::Classification::DEEP_PRESS));
441 return static_cast<MotionClassification>(classification);
442}
443
444static bool isTouchEvent(const NotifyMotionArgs& args) {
445 return args.source == AINPUT_SOURCE_TOUCHPAD || args.source == AINPUT_SOURCE_TOUCHSCREEN;
446}
447
448// Check if the "deep touch" feature is on.
449static bool deepPressEnabled() {
450 std::string flag_value = server_configurable_flags::GetServerConfigurableFlag(
451 INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "true");
452 std::transform(flag_value.begin(), flag_value.end(), flag_value.begin(), ::tolower);
453 if (flag_value == "1" || flag_value == "true") {
454 ALOGI("Deep press feature enabled.");
455 return true;
456 }
457 ALOGI("Deep press feature is not enabled.");
458 return false;
459}
460
461
462// --- ClassifierEvent ---
463
464ClassifierEvent::ClassifierEvent(std::unique_ptr<NotifyMotionArgs> args) :
465 type(ClassifierEventType::MOTION), args(std::move(args)) { };
466ClassifierEvent::ClassifierEvent(std::unique_ptr<NotifyDeviceResetArgs> args) :
467 type(ClassifierEventType::DEVICE_RESET), args(std::move(args)) { };
468ClassifierEvent::ClassifierEvent(ClassifierEventType type, std::unique_ptr<NotifyArgs> args) :
469 type(type), args(std::move(args)) { };
470
471ClassifierEvent::ClassifierEvent(ClassifierEvent&& other) :
472 type(other.type), args(std::move(other.args)) { };
473
474ClassifierEvent& ClassifierEvent::operator=(ClassifierEvent&& other) {
475 type = other.type;
476 args = std::move(other.args);
477 return *this;
478}
479
480ClassifierEvent ClassifierEvent::createHalResetEvent() {
481 return ClassifierEvent(ClassifierEventType::HAL_RESET, nullptr);
482}
483
484ClassifierEvent ClassifierEvent::createExitEvent() {
485 return ClassifierEvent(ClassifierEventType::EXIT, nullptr);
486}
487
488std::optional<int32_t> ClassifierEvent::getDeviceId() const {
489 switch (type) {
490 case ClassifierEventType::MOTION: {
491 NotifyMotionArgs* motionArgs = static_cast<NotifyMotionArgs*>(args.get());
492 return motionArgs->deviceId;
493 }
494 case ClassifierEventType::DEVICE_RESET: {
495 NotifyDeviceResetArgs* deviceResetArgs =
496 static_cast<NotifyDeviceResetArgs*>(args.get());
497 return deviceResetArgs->deviceId;
498 }
499 case ClassifierEventType::HAL_RESET: {
500 return std::nullopt;
501 }
502 case ClassifierEventType::EXIT: {
503 return std::nullopt;
504 }
505 }
506}
507
508// --- MotionClassifier ---
509
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700510MotionClassifier::MotionClassifier(sp<android::hardware::hidl_death_recipient> deathRecipient) :
511 mDeathRecipient(deathRecipient), mEvents(MAX_EVENTS) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800512 mHalThread = std::thread(&MotionClassifier::callInputClassifierHal, this);
513#if defined(__linux__)
514 // Set the thread name for debugging
515 pthread_setname_np(mHalThread.native_handle(), "InputClassifier");
516#endif
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700517}
518
519/**
520 * This function may block for some time to initialize the HAL, so it should only be called
521 * from the "InputClassifier HAL" thread.
522 */
523bool MotionClassifier::init() {
524 ensureHalThread(__func__);
525 sp<android::hardware::input::classifier::V1_0::IInputClassifier> service =
526 classifier::V1_0::IInputClassifier::getService();
527 if (!service) {
528 // Not really an error, maybe the device does not have this HAL,
529 // but somehow the feature flag is flipped
530 ALOGI("Could not obtain InputClassifier HAL");
531 return false;
532 }
533
534 sp<android::hardware::hidl_death_recipient> recipient = mDeathRecipient.promote();
535 if (recipient != nullptr) {
536 const bool linked = service->linkToDeath(recipient, 0 /* cookie */).withDefault(false);
537 if (!linked) {
538 ALOGE("Could not link MotionClassifier to the HAL death");
539 return false;
540 }
541 }
542
Siarhei Vishniakou6dbc3f62019-02-04 14:30:11 -0800543 // Under normal operation, we do not need to reset the HAL here. But in the case where system
544 // crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
545 // have received events in the past. That means, that HAL could be in an inconsistent state
546 // once it receives events from the newly created MotionClassifier.
547 mEvents.push(ClassifierEvent::createHalResetEvent());
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700548
549 {
550 std::scoped_lock lock(mLock);
551 if (mService) {
552 ALOGE("MotionClassifier::%s should only be called once", __func__);
553 }
554 mService = service;
555 }
556 return true;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800557}
558
559MotionClassifier::~MotionClassifier() {
560 requestExit();
561 mHalThread.join();
562}
563
564void MotionClassifier::ensureHalThread(const char* function) {
565 if (DEBUG) {
566 if (std::this_thread::get_id() != mHalThread.get_id()) {
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700567 LOG_FATAL("Function %s should only be called from InputClassifier thread", function);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800568 }
569 }
570}
571
572/**
573 * Obtain the classification from the HAL for a given MotionEvent.
574 * Should only be called from the InputClassifier thread (mHalThread).
575 * Should not be called from the thread that notifyMotion runs on.
576 *
577 * There is no way to provide a timeout for a HAL call. So if the HAL takes too long
578 * to return a classification, this would directly impact the touch latency.
579 * To remove any possibility of negatively affecting the touch latency, the HAL
580 * is called from a dedicated thread.
581 */
582void MotionClassifier::callInputClassifierHal() {
583 ensureHalThread(__func__);
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700584 const bool initialized = init();
585 if (!initialized) {
586 // MotionClassifier no longer useful.
587 // Deliver death notification from a separate thread
588 // because ~MotionClassifier may be invoked, which calls mHalThread.join()
589 std::thread([deathRecipient = mDeathRecipient](){
590 sp<android::hardware::hidl_death_recipient> recipient = deathRecipient.promote();
591 if (recipient != nullptr) {
592 recipient->serviceDied(0 /*cookie*/, nullptr);
593 }
594 }).detach();
595 return;
596 }
597 // From this point on, mService is guaranteed to be non-null.
598
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800599 while (true) {
600 ClassifierEvent event = mEvents.pop();
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800601 bool halResponseOk = true;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800602 switch (event.type) {
603 case ClassifierEventType::MOTION: {
604 NotifyMotionArgs* motionArgs = static_cast<NotifyMotionArgs*>(event.args.get());
605 common::V1_0::MotionEvent motionEvent = getMotionEvent(*motionArgs);
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800606 Return<common::V1_0::Classification> response = mService->classify(motionEvent);
607 halResponseOk = response.isOk();
608 if (halResponseOk) {
609 common::V1_0::Classification halClassification = response;
610 updateClassification(motionArgs->deviceId, motionArgs->eventTime,
611 getMotionClassification(halClassification));
612 }
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800613 break;
614 }
615 case ClassifierEventType::DEVICE_RESET: {
616 const int32_t deviceId = *(event.getDeviceId());
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800617 halResponseOk = mService->resetDevice(deviceId).isOk();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800618 setClassification(deviceId, MotionClassification::NONE);
619 break;
620 }
621 case ClassifierEventType::HAL_RESET: {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800622 halResponseOk = mService->reset().isOk();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800623 clearClassifications();
624 break;
625 }
626 case ClassifierEventType::EXIT: {
627 clearClassifications();
628 return;
629 }
630 }
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800631 if (!halResponseOk) {
632 ALOGE("Error communicating with InputClassifier HAL. "
633 "Exiting MotionClassifier HAL thread");
634 clearClassifications();
635 return;
636 }
637 }
638}
639
640void MotionClassifier::enqueueEvent(ClassifierEvent&& event) {
641 bool eventAdded = mEvents.push(std::move(event));
642 if (!eventAdded) {
643 // If the queue is full, suspect the HAL is slow in processing the events.
644 ALOGE("Dropped event with eventTime %" PRId64, event.args->eventTime);
645 reset();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800646 }
647}
648
649void MotionClassifier::requestExit() {
650 reset();
651 mEvents.push(ClassifierEvent::createExitEvent());
652}
653
654void MotionClassifier::updateClassification(int32_t deviceId, nsecs_t eventTime,
655 MotionClassification classification) {
656 std::scoped_lock lock(mLock);
657 const nsecs_t lastDownTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
658 if (eventTime < lastDownTime) {
659 // HAL just finished processing an event that belonged to an earlier gesture,
660 // but new gesture is already in progress. Drop this classification.
661 ALOGW("Received late classification. Late by at least %" PRId64 " ms.",
662 nanoseconds_to_milliseconds(lastDownTime - eventTime));
663 return;
664 }
665 mClassifications[deviceId] = classification;
666}
667
668void MotionClassifier::setClassification(int32_t deviceId, MotionClassification classification) {
669 std::scoped_lock lock(mLock);
670 mClassifications[deviceId] = classification;
671}
672
673void MotionClassifier::clearClassifications() {
674 std::scoped_lock lock(mLock);
675 mClassifications.clear();
676}
677
678MotionClassification MotionClassifier::getClassification(int32_t deviceId) {
679 std::scoped_lock lock(mLock);
680 return getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
681}
682
683void MotionClassifier::updateLastDownTime(int32_t deviceId, nsecs_t downTime) {
684 std::scoped_lock lock(mLock);
685 mLastDownTimes[deviceId] = downTime;
686 mClassifications[deviceId] = MotionClassification::NONE;
687}
688
689MotionClassification MotionClassifier::classify(const NotifyMotionArgs& args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800690 if ((args.action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN) {
691 updateLastDownTime(args.deviceId, args.downTime);
692 }
693
694 ClassifierEvent event(std::make_unique<NotifyMotionArgs>(args));
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800695 enqueueEvent(std::move(event));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800696 return getClassification(args.deviceId);
697}
698
699void MotionClassifier::reset() {
700 mEvents.clear();
701 mEvents.push(ClassifierEvent::createHalResetEvent());
702}
703
704/**
705 * Per-device reset. Clear the outstanding events that are going to be sent to HAL.
706 * Request InputClassifier thread to call resetDevice for this particular device.
707 */
708void MotionClassifier::reset(const NotifyDeviceResetArgs& args) {
709 int32_t deviceId = args.deviceId;
710 // Clear the pending events right away, to avoid unnecessary work done by the HAL.
711 mEvents.erase([deviceId](const ClassifierEvent& event) {
712 std::optional<int32_t> eventDeviceId = event.getDeviceId();
713 return eventDeviceId && (*eventDeviceId == deviceId);
714 });
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800715 enqueueEvent(std::make_unique<NotifyDeviceResetArgs>(args));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800716}
717
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700718const char* MotionClassifier::getServiceStatus() REQUIRES(mLock) {
719 if (!mService) {
720 return "null";
721 }
722 if (mService->ping().isOk()) {
723 return "running";
724 }
725 return "not responding";
726}
727
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800728void MotionClassifier::dump(std::string& dump) {
729 std::scoped_lock lock(mLock);
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700730 dump += StringPrintf(INDENT2 "mService status: %s\n", getServiceStatus());
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800731 dump += StringPrintf(INDENT2 "mEvents: %zu element(s) (max=%zu)\n",
732 mEvents.size(), MAX_EVENTS);
733 dump += INDENT2 "mClassifications, mLastDownTimes:\n";
734 dump += INDENT3 "Device Id\tClassification\tLast down time";
735 // Combine mClassifications and mLastDownTimes into a single table.
736 // Create a superset of device ids.
737 std::unordered_set<int32_t> deviceIds;
738 std::for_each(mClassifications.begin(), mClassifications.end(),
739 [&deviceIds](auto pair){ deviceIds.insert(pair.first); });
740 std::for_each(mLastDownTimes.begin(), mLastDownTimes.end(),
741 [&deviceIds](auto pair){ deviceIds.insert(pair.first); });
742 for(int32_t deviceId : deviceIds) {
743 const MotionClassification classification =
744 getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
745 const nsecs_t downTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
746 dump += StringPrintf("\n" INDENT4 "%" PRId32 "\t%s\t%" PRId64,
747 deviceId, motionClassificationToString(classification), downTime);
748 }
749}
750
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800751
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800752// --- InputClassifier ---
753
754InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener) :
755 mListener(listener) {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800756 // The rest of the initialization is done in onFirstRef, because we need to obtain
757 // an sp to 'this' in order to register for HAL death notifications
758}
759
760void InputClassifier::onFirstRef() {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800761 if (!deepPressEnabled()) {
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700762 // If feature is not enabled, MotionClassifier should stay null to avoid unnecessary work.
763 // When MotionClassifier is null, InputClassifier will forward all events
764 // to the next InputListener, unmodified.
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800765 return;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800766 }
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700767 std::scoped_lock lock(mLock);
768 mMotionClassifier = std::make_unique<MotionClassifier>(this);
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800769}
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800770
771void InputClassifier::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
772 // pass through
773 mListener->notifyConfigurationChanged(args);
774}
775
776void InputClassifier::notifyKey(const NotifyKeyArgs* args) {
777 // pass through
778 mListener->notifyKey(args);
779}
780
781void InputClassifier::notifyMotion(const NotifyMotionArgs* args) {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800782 std::scoped_lock lock(mLock);
783 // MotionClassifier is only used for touch events, for now
784 const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(*args);
785 if (!sendToMotionClassifier) {
786 mListener->notifyMotion(args);
787 return;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800788 }
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800789
790 NotifyMotionArgs newArgs(*args);
791 newArgs.classification = mMotionClassifier->classify(newArgs);
792 mListener->notifyMotion(&newArgs);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800793}
794
795void InputClassifier::notifySwitch(const NotifySwitchArgs* args) {
796 // pass through
797 mListener->notifySwitch(args);
798}
799
800void InputClassifier::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800801 std::scoped_lock lock(mLock);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800802 if (mMotionClassifier) {
803 mMotionClassifier->reset(*args);
804 }
805 // continue to next stage
806 mListener->notifyDeviceReset(args);
807}
808
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800809void InputClassifier::serviceDied(uint64_t /*cookie*/,
810 const wp<android::hidl::base::V1_0::IBase>& who) {
811 std::scoped_lock lock(mLock);
812 ALOGE("InputClassifier HAL has died. Setting mMotionClassifier to null");
813 mMotionClassifier = nullptr;
814 sp<android::hidl::base::V1_0::IBase> service = who.promote();
815 if (service) {
816 service->unlinkToDeath(this);
817 }
818}
819
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800820void InputClassifier::dump(std::string& dump) {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800821 std::scoped_lock lock(mLock);
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800822 dump += "Input Classifier State:\n";
823
824 dump += INDENT1 "Motion Classifier:\n";
825 if (mMotionClassifier) {
826 mMotionClassifier->dump(dump);
827 } else {
828 dump += INDENT2 "<nullptr>";
829 }
830 dump += "\n";
831}
832
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700833} // namespace android