blob: 69447a248319871b54bad4f10255505463a4c12f [file] [log] [blame]
The Android Open Source Project9877e2e2009-03-18 17:39:44 -07001/* Copyright (C) 2009 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10** GNU General Public License for more details.
11*/
12
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +010013#include <math.h>
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070014#include "android/hw-sensors.h"
15#include "android/utils/debug.h"
16#include "android/utils/misc.h"
David 'Digit' Turner5998b892009-06-11 14:43:03 +020017#include "android/utils/system.h"
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070018#include "android/hw-qemud.h"
19#include "android/globals.h"
Ot ten Thije871da2a2010-09-20 10:29:22 +010020#include "hw/hw.h"
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070021#include "qemu-char.h"
22#include "qemu-timer.h"
23
24#define D(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
25
26/* define T_ACTIVE to 1 to debug transport communications */
27#define T_ACTIVE 0
28
29#if T_ACTIVE
30#define T(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
31#else
32#define T(...) ((void)0)
33#endif
34
35/* this code supports emulated sensor hardware
36 *
37 * Note that currently, only the accelerometer is really emulated, and only
38 * for the purpose of allowing auto-rotating the screen in keyboard-less
39 * configurations.
40 *
41 *
42 */
43
44
45static const struct {
46 const char* name;
47 int id;
48} _sSensors[MAX_SENSORS] = {
49#define SENSOR_(x,y) { y, ANDROID_SENSOR_##x },
50 SENSORS_LIST
51#undef SENSOR_
52};
53
54
55static int
56_sensorIdFromName( const char* name )
57{
58 int nn;
59 for (nn = 0; nn < MAX_SENSORS; nn++)
60 if (!strcmp(_sSensors[nn].name,name))
61 return _sSensors[nn].id;
62 return -1;
63}
64
65
66typedef struct {
67 float x, y, z;
68} Acceleration;
69
70
71typedef struct {
72 float x, y, z;
73} MagneticField;
74
75
76typedef struct {
77 float azimuth;
78 float pitch;
79 float roll;
80} Orientation;
81
82
83typedef struct {
84 float celsius;
85} Temperature;
86
87
88typedef struct {
Ola Albertsson7c8397a2010-12-17 14:53:44 +010089 float value;
90} Proximity;
91
92typedef struct {
93 char enabled;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070094 union {
95 Acceleration acceleration;
96 MagneticField magnetic;
97 Orientation orientation;
98 Temperature temperature;
Ola Albertsson7c8397a2010-12-17 14:53:44 +010099 Proximity proximity;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700100 } u;
101} Sensor;
102
103/*
104 * - when the qemu-specific sensors HAL module starts, it sends
105 * "list-sensors"
106 *
107 * - this code replies with a string containing an integer corresponding
108 * to a bitmap of available hardware sensors in the current AVD
109 * configuration (e.g. "1" a.k.a (1 << ANDROID_SENSOR_ACCELERATION))
110 *
111 * - the HAL module sends "set:<sensor>:<flag>" to enable or disable
112 * the report of a given sensor state. <sensor> must be the name of
113 * a given sensor (e.g. "accelerometer"), and <flag> must be either
114 * "1" (to enable) or "0" (to disable).
115 *
116 * - Once at least one sensor is "enabled", this code should periodically
117 * send information about the corresponding enabled sensors. The default
118 * period is 200ms.
119 *
120 * - the HAL module sends "set-delay:<delay>", where <delay> is an integer
121 * corresponding to a time delay in milli-seconds. This corresponds to
122 * a new interval between sensor events sent by this code to the HAL
123 * module.
124 *
125 * - the HAL module can also send a "wake" command. This code should simply
126 * send the "wake" back to the module. This is used internally to wake a
127 * blocking read that happens in a different thread. This ping-pong makes
128 * the code in the HAL module very simple.
129 *
130 * - each timer tick, this code sends sensor reports in the following
131 * format (each line corresponds to a different line sent to the module):
132 *
133 * acceleration:<x>:<y>:<z>
134 * magnetic-field:<x>:<y>:<z>
135 * orientation:<azimuth>:<pitch>:<roll>
136 * temperature:<celsius>
137 * sync:<time_us>
138 *
139 * Where each line before the sync:<time_us> is optional and will only
140 * appear if the corresponding sensor has been enabled by the HAL module.
141 *
142 * Note that <time_us> is the VM time in micro-seconds when the report
143 * was "taken" by this code. This is adjusted by the HAL module to
144 * emulated system time (using the first sync: to compute an adjustment
145 * offset).
146 */
147#define HEADER_SIZE 4
148#define BUFFER_SIZE 512
149
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200150typedef struct HwSensorClient HwSensorClient;
151
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700152typedef struct {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200153 QemudService* service;
154 Sensor sensors[MAX_SENSORS];
155 HwSensorClient* clients;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700156} HwSensors;
157
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200158struct HwSensorClient {
159 HwSensorClient* next;
160 HwSensors* sensors;
161 QemudClient* client;
162 QEMUTimer* timer;
163 uint32_t enabledMask;
164 int32_t delay_ms;
165};
166
167static void
168_hwSensorClient_free( HwSensorClient* cl )
169{
170 /* remove from sensors's list */
171 if (cl->sensors) {
172 HwSensorClient** pnode = &cl->sensors->clients;
173 for (;;) {
174 HwSensorClient* node = *pnode;
175 if (node == NULL)
176 break;
177 if (node == cl) {
178 *pnode = cl->next;
179 break;
180 }
181 pnode = &node->next;
182 }
183 cl->next = NULL;
184 cl->sensors = NULL;
185 }
186
187 /* close QEMUD client, if any */
188 if (cl->client) {
189 qemud_client_close(cl->client);
190 cl->client = NULL;
191 }
192 /* remove timer, if any */
193 if (cl->timer) {
194 qemu_del_timer(cl->timer);
195 qemu_free_timer(cl->timer);
196 cl->timer = NULL;
197 }
198 AFREE(cl);
199}
200
201/* forward */
202static void _hwSensorClient_tick(void* opaque);
203
204
205static HwSensorClient*
206_hwSensorClient_new( HwSensors* sensors )
207{
208 HwSensorClient* cl;
209
210 ANEW0(cl);
211
212 cl->sensors = sensors;
213 cl->enabledMask = 0;
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100214 cl->delay_ms = 800;
David 'Digit' Turner5973c772011-05-10 07:06:00 +0200215 cl->timer = qemu_new_timer_ns(vm_clock, _hwSensorClient_tick, cl);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200216
217 cl->next = sensors->clients;
218 sensors->clients = cl;
219
220 return cl;
221}
222
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700223/* forward */
224
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200225static void _hwSensorClient_receive( HwSensorClient* cl,
226 uint8_t* query,
227 int querylen );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700228
229/* Qemud service management */
230
231static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200232_hwSensorClient_recv( void* opaque, uint8_t* msg, int msglen,
233 QemudClient* client )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700234{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200235 HwSensorClient* cl = opaque;
236
237 _hwSensorClient_receive(cl, msg, msglen);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700238}
239
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200240static void
241_hwSensorClient_close( void* opaque )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700242{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200243 HwSensorClient* cl = opaque;
244
245 /* the client is already closed here */
246 cl->client = NULL;
247 _hwSensorClient_free(cl);
248}
249
250/* send a one-line message to the HAL module through a qemud channel */
251static void
252_hwSensorClient_send( HwSensorClient* cl, const uint8_t* msg, int msglen )
253{
254 D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen));
255 qemud_client_send(cl->client, msg, msglen);
256}
257
258static int
259_hwSensorClient_enabled( HwSensorClient* cl, int sensorId )
260{
261 return (cl->enabledMask & (1 << sensorId)) != 0;
262}
263
264/* this function is called periodically to send sensor reports
265 * to the HAL module, and re-arm the timer if necessary
266 */
267static void
268_hwSensorClient_tick( void* opaque )
269{
270 HwSensorClient* cl = opaque;
271 HwSensors* hw = cl->sensors;
272 int64_t delay = cl->delay_ms;
273 int64_t now_ns;
274 uint32_t mask = cl->enabledMask;
275 Sensor* sensor;
276 char buffer[128];
277
278 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ACCELERATION)) {
279 sensor = &hw->sensors[ANDROID_SENSOR_ACCELERATION];
280 snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g",
281 sensor->u.acceleration.x,
282 sensor->u.acceleration.y,
283 sensor->u.acceleration.z);
284 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
285 }
286
287 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_MAGNETIC_FIELD)) {
288 sensor = &hw->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
289 snprintf(buffer, sizeof buffer, "magnetic-field:%g:%g:%g",
290 sensor->u.magnetic.x,
291 sensor->u.magnetic.y,
292 sensor->u.magnetic.z);
293 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
294 }
295
296 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ORIENTATION)) {
297 sensor = &hw->sensors[ANDROID_SENSOR_ORIENTATION];
298 snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g",
299 sensor->u.orientation.azimuth,
300 sensor->u.orientation.pitch,
301 sensor->u.orientation.roll);
302 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
303 }
304
305 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_TEMPERATURE)) {
306 sensor = &hw->sensors[ANDROID_SENSOR_TEMPERATURE];
307 snprintf(buffer, sizeof buffer, "temperature:%g",
308 sensor->u.temperature.celsius);
309 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
310 }
311
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100312 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_PROXIMITY)) {
313 sensor = &hw->sensors[ANDROID_SENSOR_PROXIMITY];
314 snprintf(buffer, sizeof buffer, "proximity:%g",
315 sensor->u.proximity.value);
316 _hwSensorClient_send(cl, (uint8_t*) buffer, strlen(buffer));
317 }
318
David 'Digit' Turner5973c772011-05-10 07:06:00 +0200319 now_ns = qemu_get_clock_ns(vm_clock);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200320
321 snprintf(buffer, sizeof buffer, "sync:%lld", now_ns/1000);
322 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
323
324 /* rearm timer, use a minimum delay of 20 ms, just to
325 * be safe.
326 */
327 if (mask == 0)
328 return;
329
330 if (delay < 20)
331 delay = 20;
332
333 delay *= 1000000LL; /* convert to nanoseconds */
334 qemu_mod_timer(cl->timer, now_ns + delay);
335}
336
337/* handle incoming messages from the HAL module */
338static void
339_hwSensorClient_receive( HwSensorClient* cl, uint8_t* msg, int msglen )
340{
341 HwSensors* hw = cl->sensors;
342
343 D("%s: '%.*s'", __FUNCTION__, msglen, msg);
344
345 /* "list-sensors" is used to get an integer bit map of
346 * available emulated sensors. We compute the mask from the
347 * current hardware configuration.
348 */
349 if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) {
350 char buff[12];
351 int mask = 0;
352 int nn;
353
354 for (nn = 0; nn < MAX_SENSORS; nn++) {
355 if (hw->sensors[nn].enabled)
356 mask |= (1 << nn);
357 }
358
359 snprintf(buff, sizeof buff, "%d", mask);
360 _hwSensorClient_send(cl, (const uint8_t*)buff, strlen(buff));
361 return;
362 }
363
364 /* "wake" is a special message that must be sent back through
365 * the channel. It is used to exit a blocking read.
366 */
367 if (msglen == 4 && !memcmp(msg, "wake", 4)) {
368 _hwSensorClient_send(cl, (const uint8_t*)"wake", 4);
369 return;
370 }
371
372 /* "set-delay:<delay>" is used to set the delay in milliseconds
373 * between sensor events
374 */
375 if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) {
376 cl->delay_ms = atoi((const char*)msg+10);
377 if (cl->enabledMask != 0)
378 _hwSensorClient_tick(cl);
379
380 return;
381 }
382
383 /* "set:<name>:<state>" is used to enable/disable a given
384 * sensor. <state> must be 0 or 1
385 */
386 if (msglen > 4 && !memcmp(msg, "set:", 4)) {
387 char* q;
388 int id, enabled, oldEnabledMask = cl->enabledMask;
389 msg += 4;
390 q = strchr((char*)msg, ':');
391 if (q == NULL) { /* should not happen */
392 D("%s: ignore bad 'set' command", __FUNCTION__);
393 return;
394 }
395 *q++ = 0;
396
397 id = _sensorIdFromName((const char*)msg);
398 if (id < 0 || id >= MAX_SENSORS) {
399 D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg);
400 return;
401 }
402
403 if (!hw->sensors[id].enabled) {
404 D("%s: trying to set disabled %s sensor", __FUNCTION__, msg);
405 return;
406 }
407 enabled = (q[0] == '1');
408
409 if (enabled)
410 cl->enabledMask |= (1 << id);
411 else
412 cl->enabledMask &= ~(1 << id);
413
414 if (cl->enabledMask != oldEnabledMask) {
415 D("%s: %s %s sensor", __FUNCTION__,
416 (cl->enabledMask & (1 << id)) ? "enabling" : "disabling", msg);
417 }
418 _hwSensorClient_tick(cl);
419 return;
420 }
421
422 D("%s: ignoring unknown query", __FUNCTION__);
423}
424
Ot ten Thije871da2a2010-09-20 10:29:22 +0100425/* Saves sensor-specific client data to snapshot */
426static void
427_hwSensorClient_save( QEMUFile* f, QemudClient* client, void* opaque )
428{
429 HwSensorClient* sc = opaque;
430
431 qemu_put_be32(f, sc->delay_ms);
432 qemu_put_be32(f, sc->enabledMask);
433 qemu_put_timer(f, sc->timer);
434}
435
436/* Loads sensor-specific client data from snapshot */
437static int
438_hwSensorClient_load( QEMUFile* f, QemudClient* client, void* opaque )
439{
440 HwSensorClient* sc = opaque;
441
442 sc->delay_ms = qemu_get_be32(f);
443 sc->enabledMask = qemu_get_be32(f);
444 qemu_get_timer(f, sc->timer);
445
446 return 0;
447}
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200448
449static QemudClient*
450_hwSensors_connect( void* opaque, QemudService* service, int channel )
451{
452 HwSensors* sensors = opaque;
453 HwSensorClient* cl = _hwSensorClient_new(sensors);
454 QemudClient* client = qemud_client_new(service, channel, cl,
455 _hwSensorClient_recv,
Ot ten Thije871da2a2010-09-20 10:29:22 +0100456 _hwSensorClient_close,
457 _hwSensorClient_save,
458 _hwSensorClient_load );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700459 qemud_client_set_framing(client, 1);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200460 cl->client = client;
461
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700462 return client;
463}
464
465/* change the value of the emulated acceleration vector */
466static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200467_hwSensors_setAcceleration( HwSensors* h, float x, float y, float z )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700468{
469 Sensor* s = &h->sensors[ANDROID_SENSOR_ACCELERATION];
470 s->u.acceleration.x = x;
471 s->u.acceleration.y = y;
472 s->u.acceleration.z = z;
473}
474
Ot ten Thije871da2a2010-09-20 10:29:22 +0100475/* Saves available sensors to allow checking availability when loaded.
476 */
477static void
478_hwSensors_save( QEMUFile* f, QemudService* sv, void* opaque)
479{
480 HwSensors* h = opaque;
481
482 // number of sensors
483 qemu_put_be32(f, MAX_SENSORS);
484 AndroidSensor i;
485 for (i = 0 ; i < MAX_SENSORS; i++) {
486 Sensor* s = &h->sensors[i];
487 qemu_put_be32(f, s->enabled);
488
489 /* this switch ensures that a warning is raised when a new sensor is
490 * added and is not added here as well.
491 */
492 switch (i) {
493 case ANDROID_SENSOR_ACCELERATION:
494 qemu_put_float(f, s->u.acceleration.x);
495 qemu_put_float(f, s->u.acceleration.y);
496 qemu_put_float(f, s->u.acceleration.z);
497 break;
498 case ANDROID_SENSOR_MAGNETIC_FIELD:
499 qemu_put_float(f, s->u.magnetic.x);
500 qemu_put_float(f, s->u.magnetic.y);
501 qemu_put_float(f, s->u.magnetic.z);
502 break;
503 case ANDROID_SENSOR_ORIENTATION:
504 qemu_put_float(f, s->u.orientation.azimuth);
505 qemu_put_float(f, s->u.orientation.pitch);
506 qemu_put_float(f, s->u.orientation.roll);
507 break;
508 case ANDROID_SENSOR_TEMPERATURE:
509 qemu_put_float(f, s->u.temperature.celsius);
510 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100511 case ANDROID_SENSOR_PROXIMITY:
512 qemu_put_float(f, s->u.proximity.value);
513 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100514 case MAX_SENSORS:
515 break;
516 }
517 }
518}
519
520
521static int
522_hwSensors_load( QEMUFile* f, QemudService* s, void* opaque)
523{
524 HwSensors* h = opaque;
525
526 /* check number of sensors */
527 int32_t num_sensors = qemu_get_be32(f);
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100528 if (num_sensors > MAX_SENSORS) {
Ot ten Thije871da2a2010-09-20 10:29:22 +0100529 D("%s: cannot load: snapshot requires %d sensors, %d available\n",
530 __FUNCTION__, num_sensors, MAX_SENSORS);
531 return -EIO;
532 }
533
534 /* load sensor state */
535 AndroidSensor i;
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100536 for (i = 0 ; i < num_sensors; i++) {
Ot ten Thije871da2a2010-09-20 10:29:22 +0100537 Sensor* s = &h->sensors[i];
538 s->enabled = qemu_get_be32(f);
539
540 /* this switch ensures that a warning is raised when a new sensor is
541 * added and is not added here as well.
542 */
543 switch (i) {
544 case ANDROID_SENSOR_ACCELERATION:
545 s->u.acceleration.x = qemu_get_float(f);
546 s->u.acceleration.y = qemu_get_float(f);
547 s->u.acceleration.z = qemu_get_float(f);
548 break;
549 case ANDROID_SENSOR_MAGNETIC_FIELD:
550 s->u.magnetic.x = qemu_get_float(f);
551 s->u.magnetic.y = qemu_get_float(f);
552 s->u.magnetic.z = qemu_get_float(f);
553 break;
554 case ANDROID_SENSOR_ORIENTATION:
555 s->u.orientation.azimuth = qemu_get_float(f);
556 s->u.orientation.pitch = qemu_get_float(f);
557 s->u.orientation.roll = qemu_get_float(f);
558 break;
559 case ANDROID_SENSOR_TEMPERATURE:
560 s->u.temperature.celsius = qemu_get_float(f);
561 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100562 case ANDROID_SENSOR_PROXIMITY:
563 s->u.proximity.value = qemu_get_float(f);
564 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100565 case MAX_SENSORS:
566 break;
567 }
568 }
569
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100570 /* The following is necessary when we resume a snaphost
571 * created by an older version of the emulator that provided
572 * less hardware sensors.
573 */
574 for ( ; i < MAX_SENSORS; i++ ) {
575 h->sensors[i].enabled = 0;
576 }
577
Ot ten Thije871da2a2010-09-20 10:29:22 +0100578 return 0;
579}
580
581
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700582#if 0 /* not used yet */
583/* change the value of the emulated magnetic vector */
584static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200585_hwSensors_setMagneticField( HwSensors* h, float x, float y, float z )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700586{
587 Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
588 s->u.magnetic.x = x;
589 s->u.magnetic.y = y;
590 s->u.magnetic.z = z;
591}
592
593/* change the values of the emulated orientation */
594static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200595_hwSensors_setOrientation( HwSensors* h, float azimuth, float pitch, float roll )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700596{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200597 Sensor* s = &h->sensors[ANDROID_SENSOR_ORIENTATION];
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700598 s->u.orientation.azimuth = azimuth;
599 s->u.orientation.pitch = pitch;
600 s->u.orientation.roll = roll;
601}
602
603/* change the emulated temperature */
604static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200605_hwSensors_setTemperature( HwSensors* h, float celsius )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700606{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200607 Sensor* s = &h->sensors[ANDROID_SENSOR_TEMPERATURE];
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700608 s->u.temperature.celsius = celsius;
609}
610#endif
611
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100612/* change the emulated proximity */
613static void
614_hwSensors_setProximity( HwSensors* h, float value )
615{
616 Sensor* s = &h->sensors[ANDROID_SENSOR_PROXIMITY];
617 s->u.proximity.value = value;
618}
619
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700620/* change the coarse orientation (landscape/portrait) of the emulated device */
621static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200622_hwSensors_setCoarseOrientation( HwSensors* h, AndroidCoarseOrientation orient )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700623{
624 /* The Android framework computes the orientation by looking at
625 * the accelerometer sensor (*not* the orientation sensor !)
626 *
627 * That's because the gravity is a constant 9.81 vector that
628 * can be determined quite easily.
629 *
630 * Also, for some reason, the framework code considers that the phone should
631 * be inclined by 30 degrees along the phone's X axis to be considered
632 * in its ideal "vertical" position
633 *
634 * If the phone is completely vertical, rotating it will not do anything !
635 */
636 const double g = 9.81;
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100637 const double angle = 20.0;
638 const double cos_angle = cos(angle/M_PI);
639 const double sin_angle = sin(angle/M_PI);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700640
641 switch (orient) {
642 case ANDROID_COARSE_PORTRAIT:
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100643 _hwSensors_setAcceleration( h, 0., g*cos_angle, g*sin_angle );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700644 break;
645
646 case ANDROID_COARSE_LANDSCAPE:
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100647 _hwSensors_setAcceleration( h, g*cos_angle, 0., g*sin_angle );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700648 break;
649 default:
650 ;
651 }
652}
653
654
655/* initialize the sensors state */
656static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200657_hwSensors_init( HwSensors* h )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700658{
Ot ten Thije871da2a2010-09-20 10:29:22 +0100659 h->service = qemud_service_register("sensors", 0, h, _hwSensors_connect,
660 _hwSensors_save, _hwSensors_load);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700661
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200662 if (android_hw->hw_accelerometer)
663 h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1;
664
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100665 if (android_hw->hw_sensors_proximity)
666 h->sensors[ANDROID_SENSOR_PROXIMITY].enabled = 1;
667
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200668 /* XXX: TODO: Add other tests when we add the corresponding
669 * properties to hardware-properties.ini et al. */
670
671 _hwSensors_setCoarseOrientation(h, ANDROID_COARSE_PORTRAIT);
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100672 _hwSensors_setProximity(h, 1);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700673}
674
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700675static HwSensors _sensorsState[1];
676
677void
678android_hw_sensors_init( void )
679{
680 HwSensors* hw = _sensorsState;
681
682 if (hw->service == NULL) {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200683 _hwSensors_init(hw);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700684 D("%s: sensors qemud service initialized", __FUNCTION__);
685 }
686}
687
688/* change the coarse orientation value */
689extern void
690android_sensors_set_coarse_orientation( AndroidCoarseOrientation orient )
691{
692 android_hw_sensors_init();
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200693 _hwSensors_setCoarseOrientation(_sensorsState, orient);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700694}
695