Imported Upstream version 0.1.0+git20131207+e452e83
[deb_libhybris.git] / compat / input / input_compatibility_layer.cpp
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(&current_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(&current_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(&current_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 }