Commit | Line | Data |
---|---|---|
d42e7319 JB |
1 | /* |
2 | * Copyright (C) 2013 Canonical Ltd | |
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 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | |
17 | * Ricardo Salveti de Araujo <ricardo.salveti@canonical.com> | |
18 | */ | |
19 | ||
20 | #include <hybris/input/input_stack_compatibility_layer.h> | |
21 | ||
22 | #include "InputListener.h" | |
23 | #include "InputReader.h" | |
24 | #include "PointerController.h" | |
25 | #include "SpriteController.h" | |
26 | #include <gui/ISurfaceComposer.h> | |
27 | #include <gui/SurfaceComposerClient.h> | |
28 | ||
29 | #undef LOG_TAG | |
30 | #define LOG_TAG "InputStackCompatibilityLayer" | |
31 | #include <utils/Log.h> | |
32 | ||
33 | namespace | |
34 | { | |
35 | static bool enable_verbose_function_reporting = false; | |
36 | } | |
37 | ||
38 | #define REPORT_FUNCTION() ALOGV("%s\n", __PRETTY_FUNCTION__); | |
39 | ||
40 | namespace | |
41 | { | |
42 | ||
43 | class DefaultPointerControllerPolicy : public android::PointerControllerPolicyInterface | |
44 | { | |
45 | public: | |
46 | static const size_t bitmap_width = 64; | |
47 | static const size_t bitmap_height = 64; | |
48 | ||
49 | DefaultPointerControllerPolicy() | |
50 | { | |
51 | bitmap.setConfig( | |
52 | SkBitmap::kARGB_8888_Config, | |
53 | bitmap_width, | |
54 | bitmap_height); | |
55 | bitmap.allocPixels(); | |
56 | ||
57 | // Icon for spot touches | |
58 | bitmap.eraseARGB(125, 0, 255, 0); | |
59 | spotTouchIcon = android::SpriteIcon( | |
60 | bitmap, | |
61 | bitmap_width/2, | |
62 | bitmap_height/2); | |
63 | ||
64 | // Icon for anchor touches | |
65 | bitmap.eraseARGB(125, 0, 0, 255); | |
66 | spotAnchorIcon = android::SpriteIcon( | |
67 | bitmap, | |
68 | bitmap_width/2, | |
69 | bitmap_height/2); | |
70 | ||
71 | // Icon for hovering touches | |
72 | bitmap.eraseARGB(125, 255, 0, 0); | |
73 | spotHoverIcon = android::SpriteIcon( | |
74 | bitmap, | |
75 | bitmap_width/2, | |
76 | bitmap_height/2); | |
77 | } | |
78 | ||
79 | void loadPointerResources(android::PointerResources* outResources) | |
80 | { | |
81 | outResources->spotHover = spotHoverIcon.copy(); | |
82 | outResources->spotTouch = spotTouchIcon.copy(); | |
83 | outResources->spotAnchor = spotAnchorIcon.copy(); | |
84 | } | |
85 | ||
86 | android::SpriteIcon spotHoverIcon; | |
87 | android::SpriteIcon spotTouchIcon; | |
88 | android::SpriteIcon spotAnchorIcon; | |
89 | SkBitmap bitmap; | |
90 | }; | |
91 | ||
92 | class DefaultInputReaderPolicyInterface : public android::InputReaderPolicyInterface | |
93 | { | |
94 | public: | |
95 | static const int32_t internal_display_id = android::ISurfaceComposer::eDisplayIdMain; | |
96 | static const int32_t external_display_id = android::ISurfaceComposer::eDisplayIdHdmi; | |
97 | ||
98 | DefaultInputReaderPolicyInterface( | |
99 | InputStackConfiguration* configuration, | |
100 | const android::sp<android::Looper>& looper) | |
101 | : looper(looper), | |
102 | default_layer_for_touch_point_visualization(configuration->default_layer_for_touch_point_visualization), | |
103 | input_area_width(configuration->input_area_width), | |
104 | input_area_height(configuration->input_area_height) | |
105 | { | |
106 | default_configuration.showTouches = configuration->enable_touch_point_visualization; | |
107 | ||
108 | android::DisplayViewport viewport; | |
109 | viewport.setNonDisplayViewport(input_area_width, input_area_height); | |
110 | viewport.displayId = android::ISurfaceComposer::eDisplayIdMain; | |
111 | default_configuration.setDisplayInfo( | |
112 | false, /* external */ | |
113 | viewport); | |
114 | } | |
115 | ||
116 | void getReaderConfiguration(android::InputReaderConfiguration* outConfig) | |
117 | { | |
118 | *outConfig = default_configuration; | |
119 | } | |
120 | ||
121 | android::sp<android::PointerControllerInterface> obtainPointerController(int32_t deviceId) | |
122 | { | |
123 | (void) deviceId; | |
124 | ||
125 | android::sp<android::SpriteController> sprite_controller( | |
126 | new android::SpriteController( | |
127 | looper, | |
128 | default_layer_for_touch_point_visualization)); | |
129 | android::sp<android::PointerController> pointer_controller( | |
130 | new android::PointerController( | |
131 | android::sp<DefaultPointerControllerPolicy>(new DefaultPointerControllerPolicy()), | |
132 | looper, | |
133 | sprite_controller)); | |
134 | pointer_controller->setPresentation( | |
135 | android::PointerControllerInterface::PRESENTATION_SPOT); | |
136 | ||
137 | pointer_controller->setDisplayViewport(input_area_width, input_area_height, 0); | |
138 | return pointer_controller; | |
139 | } | |
140 | ||
141 | virtual void notifyInputDevicesChanged(const android::Vector<android::InputDeviceInfo>& inputDevices) { | |
142 | mInputDevices = inputDevices; | |
143 | } | |
144 | ||
145 | virtual android::sp<android::KeyCharacterMap> getKeyboardLayoutOverlay(const android::String8& inputDeviceDescriptor) { | |
146 | return NULL; | |
147 | } | |
148 | ||
149 | virtual android::String8 getDeviceAlias(const android::InputDeviceIdentifier& identifier) { | |
150 | return android::String8::empty(); | |
151 | } | |
152 | ||
153 | private: | |
154 | android::sp<android::Looper> looper; | |
155 | int default_layer_for_touch_point_visualization; | |
156 | android::InputReaderConfiguration default_configuration; | |
157 | android::Vector<android::InputDeviceInfo> mInputDevices; | |
158 | int input_area_width; | |
159 | int input_area_height; | |
160 | }; | |
161 | ||
162 | class ExportedInputListener : public android::InputListenerInterface | |
163 | { | |
164 | public: | |
165 | ExportedInputListener(AndroidEventListener* external_listener) : external_listener(external_listener) | |
166 | { | |
167 | } | |
168 | ||
169 | void notifyConfigurationChanged(const android::NotifyConfigurationChangedArgs* args) | |
170 | { | |
171 | REPORT_FUNCTION(); | |
172 | (void) args; | |
173 | } | |
174 | ||
175 | void notifyKey(const android::NotifyKeyArgs* args) | |
176 | { | |
177 | REPORT_FUNCTION(); | |
178 | ||
179 | current_event.type = KEY_EVENT_TYPE; | |
180 | current_event.device_id = args->deviceId; | |
181 | current_event.source_id = args->source; | |
182 | current_event.action = args->action; | |
183 | current_event.flags = args->flags; | |
184 | current_event.meta_state = args->metaState; | |
185 | ||
186 | current_event.details.key.key_code = args->keyCode; | |
187 | current_event.details.key.scan_code = args->scanCode; | |
188 | current_event.details.key.down_time = args->downTime; | |
189 | current_event.details.key.event_time = args->eventTime; | |
190 | ||
191 | current_event.details.key.is_system_key = false; | |
192 | ||
193 | external_listener->on_new_event(¤t_event, external_listener->context); | |
194 | } | |
195 | ||
196 | void notifyMotion(const android::NotifyMotionArgs* args) | |
197 | { | |
198 | REPORT_FUNCTION(); | |
199 | ||
200 | current_event.type = MOTION_EVENT_TYPE; | |
201 | current_event.device_id = args->deviceId; | |
202 | current_event.source_id = args->source; | |
203 | current_event.action = args->action; | |
204 | current_event.flags = args->flags; | |
205 | current_event.meta_state = args->metaState; | |
206 | ||
207 | current_event.details.motion.button_state = args->buttonState; | |
208 | current_event.details.motion.down_time = args->downTime; | |
209 | current_event.details.motion.event_time = args->eventTime; | |
210 | current_event.details.motion.edge_flags = args->edgeFlags; | |
211 | current_event.details.motion.x_precision = args->xPrecision; | |
212 | current_event.details.motion.y_precision = args->yPrecision; | |
213 | current_event.details.motion.pointer_count = args->pointerCount; | |
214 | ||
215 | for (unsigned int i = 0; i < current_event.details.motion.pointer_count; i++) { | |
216 | current_event.details.motion.pointer_coordinates[i].id = args->pointerProperties[i].id; | |
217 | current_event.details.motion.pointer_coordinates[i].x | |
218 | = current_event.details.motion.pointer_coordinates[i].raw_x | |
219 | = args->pointerCoords[i].getX(); | |
220 | current_event.details.motion.pointer_coordinates[i].y | |
221 | = current_event.details.motion.pointer_coordinates[i].raw_y | |
222 | = args->pointerCoords[i].getY(); | |
223 | current_event.details.motion.pointer_coordinates[i].touch_major | |
224 | = args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR); | |
225 | current_event.details.motion.pointer_coordinates[i].touch_minor | |
226 | = args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR); | |
227 | current_event.details.motion.pointer_coordinates[i].pressure | |
228 | = args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE); | |
229 | current_event.details.motion.pointer_coordinates[i].size | |
230 | = args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE); | |
231 | current_event.details.motion.pointer_coordinates[i].orientation | |
232 | = args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); | |
233 | ||
234 | } | |
235 | ||
236 | external_listener->on_new_event(¤t_event, external_listener->context); | |
237 | } | |
238 | ||
239 | void notifySwitch(const android::NotifySwitchArgs* args) | |
240 | { | |
241 | REPORT_FUNCTION(); | |
242 | current_event.type = HW_SWITCH_EVENT_TYPE; | |
243 | ||
244 | current_event.details.hw_switch.event_time = args->eventTime; | |
245 | current_event.details.hw_switch.policy_flags = args->policyFlags; | |
246 | current_event.details.hw_switch.switch_values = args->switchValues; | |
247 | current_event.details.hw_switch.switch_mask = args->switchMask; | |
248 | ||
249 | external_listener->on_new_event(¤t_event, external_listener->context); | |
250 | } | |
251 | ||
252 | void notifyDeviceReset(const android::NotifyDeviceResetArgs* args) | |
253 | { | |
254 | REPORT_FUNCTION(); | |
255 | (void) args; | |
256 | } | |
257 | ||
258 | private: | |
259 | AndroidEventListener* external_listener; | |
260 | Event current_event; | |
261 | }; | |
262 | ||
263 | class LooperThread : public android::Thread | |
264 | { | |
265 | public: | |
266 | static const int default_poll_timeout_ms = -1; | |
267 | ||
268 | LooperThread(const android::sp<android::Looper>& looper) : looper(looper) | |
269 | { | |
270 | } | |
271 | ||
272 | private: | |
273 | bool threadLoop() | |
274 | { | |
275 | if (ALOOPER_POLL_ERROR == looper->pollAll(default_poll_timeout_ms)) | |
276 | return false; | |
277 | return true; | |
278 | } | |
279 | ||
280 | android::sp<android::Looper> looper; | |
281 | }; | |
282 | ||
283 | struct State : public android::RefBase | |
284 | { | |
285 | State(AndroidEventListener* listener, | |
286 | InputStackConfiguration* configuration) | |
287 | : looper(new android::Looper(false)), | |
288 | looper_thread(new LooperThread(looper)), | |
289 | event_hub(new android::EventHub()), | |
290 | input_reader_policy(new DefaultInputReaderPolicyInterface(configuration, looper)), | |
291 | input_listener(new ExportedInputListener(listener)), | |
292 | input_reader(new android::InputReader( | |
293 | event_hub, | |
294 | input_reader_policy, | |
295 | input_listener)), | |
296 | input_reader_thread(new android::InputReaderThread(input_reader)) | |
297 | { | |
298 | } | |
299 | ||
300 | ~State() | |
301 | { | |
302 | input_reader_thread->requestExit(); | |
303 | } | |
304 | ||
305 | android::sp<android::Looper> looper; | |
306 | android::sp<LooperThread> looper_thread; | |
307 | ||
308 | android::sp<android::EventHubInterface> event_hub; | |
309 | android::sp<android::InputReaderPolicyInterface> input_reader_policy; | |
310 | android::sp<android::InputListenerInterface> input_listener; | |
311 | android::sp<android::InputReaderInterface> input_reader; | |
312 | android::sp<android::InputReaderThread> input_reader_thread; | |
313 | ||
314 | android::Condition wait_condition; | |
315 | android::Mutex wait_guard; | |
316 | }; | |
317 | ||
318 | android::sp<State> global_state; | |
319 | ||
320 | } | |
321 | ||
322 | void android_input_stack_initialize(AndroidEventListener* listener, InputStackConfiguration* config) | |
323 | { | |
324 | global_state = new State(listener, config); | |
325 | } | |
326 | ||
327 | void android_input_stack_loop_once() | |
328 | { | |
329 | global_state->input_reader->loopOnce(); | |
330 | } | |
331 | ||
332 | void android_input_stack_start() | |
333 | { | |
334 | global_state->input_reader_thread->run(); | |
335 | global_state->looper_thread->run(); | |
336 | } | |
337 | ||
338 | void android_input_stack_start_waiting_for_flag(bool* flag) | |
339 | { | |
340 | global_state->input_reader_thread->run(); | |
341 | global_state->looper_thread->run(); | |
342 | ||
343 | while (!*flag) { | |
344 | global_state->wait_condition.waitRelative( | |
345 | global_state->wait_guard, | |
346 | 10 * 1000 * 1000); | |
347 | } | |
348 | } | |
349 | ||
350 | void android_input_stack_stop() | |
351 | { | |
352 | global_state->input_reader_thread->requestExit(); | |
353 | } | |
354 | ||
355 | void android_input_stack_shutdown() | |
356 | { | |
357 | global_state = NULL; | |
358 | } |