blob: d9f3a6f7c83c6fb1ace6432b56c8ceec053fa6fb [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
13#include "android/hw-sensors.h"
14#include "android/utils/debug.h"
15#include "android/utils/misc.h"
David 'Digit' Turner5998b892009-06-11 14:43:03 +020016#include "android/utils/system.h"
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070017#include "android/hw-qemud.h"
18#include "android/globals.h"
Ot ten Thije871da2a2010-09-20 10:29:22 +010019#include "hw/hw.h"
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070020#include "qemu-char.h"
21#include "qemu-timer.h"
22
23#define D(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
24
25/* define T_ACTIVE to 1 to debug transport communications */
26#define T_ACTIVE 0
27
28#if T_ACTIVE
29#define T(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
30#else
31#define T(...) ((void)0)
32#endif
33
34/* this code supports emulated sensor hardware
35 *
36 * Note that currently, only the accelerometer is really emulated, and only
37 * for the purpose of allowing auto-rotating the screen in keyboard-less
38 * configurations.
39 *
40 *
41 */
42
43
44static const struct {
45 const char* name;
46 int id;
47} _sSensors[MAX_SENSORS] = {
48#define SENSOR_(x,y) { y, ANDROID_SENSOR_##x },
49 SENSORS_LIST
50#undef SENSOR_
51};
52
53
54static int
55_sensorIdFromName( const char* name )
56{
57 int nn;
58 for (nn = 0; nn < MAX_SENSORS; nn++)
59 if (!strcmp(_sSensors[nn].name,name))
60 return _sSensors[nn].id;
61 return -1;
62}
63
64
65typedef struct {
66 float x, y, z;
67} Acceleration;
68
69
70typedef struct {
71 float x, y, z;
72} MagneticField;
73
74
75typedef struct {
76 float azimuth;
77 float pitch;
78 float roll;
79} Orientation;
80
81
82typedef struct {
83 float celsius;
84} Temperature;
85
86
87typedef struct {
Ola Albertsson7c8397a2010-12-17 14:53:44 +010088 float value;
89} Proximity;
90
91typedef struct {
92 char enabled;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070093 union {
94 Acceleration acceleration;
95 MagneticField magnetic;
96 Orientation orientation;
97 Temperature temperature;
Ola Albertsson7c8397a2010-12-17 14:53:44 +010098 Proximity proximity;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070099 } u;
100} Sensor;
101
102/*
103 * - when the qemu-specific sensors HAL module starts, it sends
104 * "list-sensors"
105 *
106 * - this code replies with a string containing an integer corresponding
107 * to a bitmap of available hardware sensors in the current AVD
108 * configuration (e.g. "1" a.k.a (1 << ANDROID_SENSOR_ACCELERATION))
109 *
110 * - the HAL module sends "set:<sensor>:<flag>" to enable or disable
111 * the report of a given sensor state. <sensor> must be the name of
112 * a given sensor (e.g. "accelerometer"), and <flag> must be either
113 * "1" (to enable) or "0" (to disable).
114 *
115 * - Once at least one sensor is "enabled", this code should periodically
116 * send information about the corresponding enabled sensors. The default
117 * period is 200ms.
118 *
119 * - the HAL module sends "set-delay:<delay>", where <delay> is an integer
120 * corresponding to a time delay in milli-seconds. This corresponds to
121 * a new interval between sensor events sent by this code to the HAL
122 * module.
123 *
124 * - the HAL module can also send a "wake" command. This code should simply
125 * send the "wake" back to the module. This is used internally to wake a
126 * blocking read that happens in a different thread. This ping-pong makes
127 * the code in the HAL module very simple.
128 *
129 * - each timer tick, this code sends sensor reports in the following
130 * format (each line corresponds to a different line sent to the module):
131 *
132 * acceleration:<x>:<y>:<z>
133 * magnetic-field:<x>:<y>:<z>
134 * orientation:<azimuth>:<pitch>:<roll>
135 * temperature:<celsius>
136 * sync:<time_us>
137 *
138 * Where each line before the sync:<time_us> is optional and will only
139 * appear if the corresponding sensor has been enabled by the HAL module.
140 *
141 * Note that <time_us> is the VM time in micro-seconds when the report
142 * was "taken" by this code. This is adjusted by the HAL module to
143 * emulated system time (using the first sync: to compute an adjustment
144 * offset).
145 */
146#define HEADER_SIZE 4
147#define BUFFER_SIZE 512
148
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200149typedef struct HwSensorClient HwSensorClient;
150
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700151typedef struct {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200152 QemudService* service;
153 Sensor sensors[MAX_SENSORS];
154 HwSensorClient* clients;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700155} HwSensors;
156
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200157struct HwSensorClient {
158 HwSensorClient* next;
159 HwSensors* sensors;
160 QemudClient* client;
161 QEMUTimer* timer;
162 uint32_t enabledMask;
163 int32_t delay_ms;
164};
165
166static void
167_hwSensorClient_free( HwSensorClient* cl )
168{
169 /* remove from sensors's list */
170 if (cl->sensors) {
171 HwSensorClient** pnode = &cl->sensors->clients;
172 for (;;) {
173 HwSensorClient* node = *pnode;
174 if (node == NULL)
175 break;
176 if (node == cl) {
177 *pnode = cl->next;
178 break;
179 }
180 pnode = &node->next;
181 }
182 cl->next = NULL;
183 cl->sensors = NULL;
184 }
185
186 /* close QEMUD client, if any */
187 if (cl->client) {
188 qemud_client_close(cl->client);
189 cl->client = NULL;
190 }
191 /* remove timer, if any */
192 if (cl->timer) {
193 qemu_del_timer(cl->timer);
194 qemu_free_timer(cl->timer);
195 cl->timer = NULL;
196 }
197 AFREE(cl);
198}
199
200/* forward */
201static void _hwSensorClient_tick(void* opaque);
202
203
204static HwSensorClient*
205_hwSensorClient_new( HwSensors* sensors )
206{
207 HwSensorClient* cl;
208
209 ANEW0(cl);
210
211 cl->sensors = sensors;
212 cl->enabledMask = 0;
213 cl->delay_ms = 1000;
214 cl->timer = qemu_new_timer(vm_clock, _hwSensorClient_tick, cl);
215
216 cl->next = sensors->clients;
217 sensors->clients = cl;
218
219 return cl;
220}
221
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700222/* forward */
223
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200224static void _hwSensorClient_receive( HwSensorClient* cl,
225 uint8_t* query,
226 int querylen );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700227
228/* Qemud service management */
229
230static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200231_hwSensorClient_recv( void* opaque, uint8_t* msg, int msglen,
232 QemudClient* client )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700233{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200234 HwSensorClient* cl = opaque;
235
236 _hwSensorClient_receive(cl, msg, msglen);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700237}
238
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200239static void
240_hwSensorClient_close( void* opaque )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700241{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200242 HwSensorClient* cl = opaque;
243
244 /* the client is already closed here */
245 cl->client = NULL;
246 _hwSensorClient_free(cl);
247}
248
249/* send a one-line message to the HAL module through a qemud channel */
250static void
251_hwSensorClient_send( HwSensorClient* cl, const uint8_t* msg, int msglen )
252{
253 D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen));
254 qemud_client_send(cl->client, msg, msglen);
255}
256
257static int
258_hwSensorClient_enabled( HwSensorClient* cl, int sensorId )
259{
260 return (cl->enabledMask & (1 << sensorId)) != 0;
261}
262
263/* this function is called periodically to send sensor reports
264 * to the HAL module, and re-arm the timer if necessary
265 */
266static void
267_hwSensorClient_tick( void* opaque )
268{
269 HwSensorClient* cl = opaque;
270 HwSensors* hw = cl->sensors;
271 int64_t delay = cl->delay_ms;
272 int64_t now_ns;
273 uint32_t mask = cl->enabledMask;
274 Sensor* sensor;
275 char buffer[128];
276
277 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ACCELERATION)) {
278 sensor = &hw->sensors[ANDROID_SENSOR_ACCELERATION];
279 snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g",
280 sensor->u.acceleration.x,
281 sensor->u.acceleration.y,
282 sensor->u.acceleration.z);
283 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
284 }
285
286 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_MAGNETIC_FIELD)) {
287 sensor = &hw->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
288 snprintf(buffer, sizeof buffer, "magnetic-field:%g:%g:%g",
289 sensor->u.magnetic.x,
290 sensor->u.magnetic.y,
291 sensor->u.magnetic.z);
292 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
293 }
294
295 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ORIENTATION)) {
296 sensor = &hw->sensors[ANDROID_SENSOR_ORIENTATION];
297 snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g",
298 sensor->u.orientation.azimuth,
299 sensor->u.orientation.pitch,
300 sensor->u.orientation.roll);
301 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
302 }
303
304 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_TEMPERATURE)) {
305 sensor = &hw->sensors[ANDROID_SENSOR_TEMPERATURE];
306 snprintf(buffer, sizeof buffer, "temperature:%g",
307 sensor->u.temperature.celsius);
308 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
309 }
310
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100311 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_PROXIMITY)) {
312 sensor = &hw->sensors[ANDROID_SENSOR_PROXIMITY];
313 snprintf(buffer, sizeof buffer, "proximity:%g",
314 sensor->u.proximity.value);
315 _hwSensorClient_send(cl, (uint8_t*) buffer, strlen(buffer));
316 }
317
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200318 now_ns = qemu_get_clock(vm_clock);
319
320 snprintf(buffer, sizeof buffer, "sync:%lld", now_ns/1000);
321 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
322
323 /* rearm timer, use a minimum delay of 20 ms, just to
324 * be safe.
325 */
326 if (mask == 0)
327 return;
328
329 if (delay < 20)
330 delay = 20;
331
332 delay *= 1000000LL; /* convert to nanoseconds */
333 qemu_mod_timer(cl->timer, now_ns + delay);
334}
335
336/* handle incoming messages from the HAL module */
337static void
338_hwSensorClient_receive( HwSensorClient* cl, uint8_t* msg, int msglen )
339{
340 HwSensors* hw = cl->sensors;
341
342 D("%s: '%.*s'", __FUNCTION__, msglen, msg);
343
344 /* "list-sensors" is used to get an integer bit map of
345 * available emulated sensors. We compute the mask from the
346 * current hardware configuration.
347 */
348 if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) {
349 char buff[12];
350 int mask = 0;
351 int nn;
352
353 for (nn = 0; nn < MAX_SENSORS; nn++) {
354 if (hw->sensors[nn].enabled)
355 mask |= (1 << nn);
356 }
357
358 snprintf(buff, sizeof buff, "%d", mask);
359 _hwSensorClient_send(cl, (const uint8_t*)buff, strlen(buff));
360 return;
361 }
362
363 /* "wake" is a special message that must be sent back through
364 * the channel. It is used to exit a blocking read.
365 */
366 if (msglen == 4 && !memcmp(msg, "wake", 4)) {
367 _hwSensorClient_send(cl, (const uint8_t*)"wake", 4);
368 return;
369 }
370
371 /* "set-delay:<delay>" is used to set the delay in milliseconds
372 * between sensor events
373 */
374 if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) {
375 cl->delay_ms = atoi((const char*)msg+10);
376 if (cl->enabledMask != 0)
377 _hwSensorClient_tick(cl);
378
379 return;
380 }
381
382 /* "set:<name>:<state>" is used to enable/disable a given
383 * sensor. <state> must be 0 or 1
384 */
385 if (msglen > 4 && !memcmp(msg, "set:", 4)) {
386 char* q;
387 int id, enabled, oldEnabledMask = cl->enabledMask;
388 msg += 4;
389 q = strchr((char*)msg, ':');
390 if (q == NULL) { /* should not happen */
391 D("%s: ignore bad 'set' command", __FUNCTION__);
392 return;
393 }
394 *q++ = 0;
395
396 id = _sensorIdFromName((const char*)msg);
397 if (id < 0 || id >= MAX_SENSORS) {
398 D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg);
399 return;
400 }
401
402 if (!hw->sensors[id].enabled) {
403 D("%s: trying to set disabled %s sensor", __FUNCTION__, msg);
404 return;
405 }
406 enabled = (q[0] == '1');
407
408 if (enabled)
409 cl->enabledMask |= (1 << id);
410 else
411 cl->enabledMask &= ~(1 << id);
412
413 if (cl->enabledMask != oldEnabledMask) {
414 D("%s: %s %s sensor", __FUNCTION__,
415 (cl->enabledMask & (1 << id)) ? "enabling" : "disabling", msg);
416 }
417 _hwSensorClient_tick(cl);
418 return;
419 }
420
421 D("%s: ignoring unknown query", __FUNCTION__);
422}
423
Ot ten Thije871da2a2010-09-20 10:29:22 +0100424/* Saves sensor-specific client data to snapshot */
425static void
426_hwSensorClient_save( QEMUFile* f, QemudClient* client, void* opaque )
427{
428 HwSensorClient* sc = opaque;
429
430 qemu_put_be32(f, sc->delay_ms);
431 qemu_put_be32(f, sc->enabledMask);
432 qemu_put_timer(f, sc->timer);
433}
434
435/* Loads sensor-specific client data from snapshot */
436static int
437_hwSensorClient_load( QEMUFile* f, QemudClient* client, void* opaque )
438{
439 HwSensorClient* sc = opaque;
440
441 sc->delay_ms = qemu_get_be32(f);
442 sc->enabledMask = qemu_get_be32(f);
443 qemu_get_timer(f, sc->timer);
444
445 return 0;
446}
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200447
448static QemudClient*
449_hwSensors_connect( void* opaque, QemudService* service, int channel )
450{
451 HwSensors* sensors = opaque;
452 HwSensorClient* cl = _hwSensorClient_new(sensors);
453 QemudClient* client = qemud_client_new(service, channel, cl,
454 _hwSensorClient_recv,
Ot ten Thije871da2a2010-09-20 10:29:22 +0100455 _hwSensorClient_close,
456 _hwSensorClient_save,
457 _hwSensorClient_load );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700458 qemud_client_set_framing(client, 1);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200459 cl->client = client;
460
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700461 return client;
462}
463
464/* change the value of the emulated acceleration vector */
465static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200466_hwSensors_setAcceleration( HwSensors* h, float x, float y, float z )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700467{
468 Sensor* s = &h->sensors[ANDROID_SENSOR_ACCELERATION];
469 s->u.acceleration.x = x;
470 s->u.acceleration.y = y;
471 s->u.acceleration.z = z;
472}
473
Ot ten Thije871da2a2010-09-20 10:29:22 +0100474/* Saves available sensors to allow checking availability when loaded.
475 */
476static void
477_hwSensors_save( QEMUFile* f, QemudService* sv, void* opaque)
478{
479 HwSensors* h = opaque;
480
481 // number of sensors
482 qemu_put_be32(f, MAX_SENSORS);
483 AndroidSensor i;
484 for (i = 0 ; i < MAX_SENSORS; i++) {
485 Sensor* s = &h->sensors[i];
486 qemu_put_be32(f, s->enabled);
487
488 /* this switch ensures that a warning is raised when a new sensor is
489 * added and is not added here as well.
490 */
491 switch (i) {
492 case ANDROID_SENSOR_ACCELERATION:
493 qemu_put_float(f, s->u.acceleration.x);
494 qemu_put_float(f, s->u.acceleration.y);
495 qemu_put_float(f, s->u.acceleration.z);
496 break;
497 case ANDROID_SENSOR_MAGNETIC_FIELD:
498 qemu_put_float(f, s->u.magnetic.x);
499 qemu_put_float(f, s->u.magnetic.y);
500 qemu_put_float(f, s->u.magnetic.z);
501 break;
502 case ANDROID_SENSOR_ORIENTATION:
503 qemu_put_float(f, s->u.orientation.azimuth);
504 qemu_put_float(f, s->u.orientation.pitch);
505 qemu_put_float(f, s->u.orientation.roll);
506 break;
507 case ANDROID_SENSOR_TEMPERATURE:
508 qemu_put_float(f, s->u.temperature.celsius);
509 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100510 case ANDROID_SENSOR_PROXIMITY:
511 qemu_put_float(f, s->u.proximity.value);
512 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100513 case MAX_SENSORS:
514 break;
515 }
516 }
517}
518
519
520static int
521_hwSensors_load( QEMUFile* f, QemudService* s, void* opaque)
522{
523 HwSensors* h = opaque;
524
525 /* check number of sensors */
526 int32_t num_sensors = qemu_get_be32(f);
527 if (num_sensors != MAX_SENSORS) {
528 D("%s: cannot load: snapshot requires %d sensors, %d available\n",
529 __FUNCTION__, num_sensors, MAX_SENSORS);
530 return -EIO;
531 }
532
533 /* load sensor state */
534 AndroidSensor i;
535 for (i = 0 ; i < MAX_SENSORS; i++) {
536 Sensor* s = &h->sensors[i];
537 s->enabled = qemu_get_be32(f);
538
539 /* this switch ensures that a warning is raised when a new sensor is
540 * added and is not added here as well.
541 */
542 switch (i) {
543 case ANDROID_SENSOR_ACCELERATION:
544 s->u.acceleration.x = qemu_get_float(f);
545 s->u.acceleration.y = qemu_get_float(f);
546 s->u.acceleration.z = qemu_get_float(f);
547 break;
548 case ANDROID_SENSOR_MAGNETIC_FIELD:
549 s->u.magnetic.x = qemu_get_float(f);
550 s->u.magnetic.y = qemu_get_float(f);
551 s->u.magnetic.z = qemu_get_float(f);
552 break;
553 case ANDROID_SENSOR_ORIENTATION:
554 s->u.orientation.azimuth = qemu_get_float(f);
555 s->u.orientation.pitch = qemu_get_float(f);
556 s->u.orientation.roll = qemu_get_float(f);
557 break;
558 case ANDROID_SENSOR_TEMPERATURE:
559 s->u.temperature.celsius = qemu_get_float(f);
560 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100561 case ANDROID_SENSOR_PROXIMITY:
562 s->u.proximity.value = qemu_get_float(f);
563 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100564 case MAX_SENSORS:
565 break;
566 }
567 }
568
569 return 0;
570}
571
572
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700573#if 0 /* not used yet */
574/* change the value of the emulated magnetic vector */
575static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200576_hwSensors_setMagneticField( HwSensors* h, float x, float y, float z )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700577{
578 Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
579 s->u.magnetic.x = x;
580 s->u.magnetic.y = y;
581 s->u.magnetic.z = z;
582}
583
584/* change the values of the emulated orientation */
585static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200586_hwSensors_setOrientation( HwSensors* h, float azimuth, float pitch, float roll )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700587{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200588 Sensor* s = &h->sensors[ANDROID_SENSOR_ORIENTATION];
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700589 s->u.orientation.azimuth = azimuth;
590 s->u.orientation.pitch = pitch;
591 s->u.orientation.roll = roll;
592}
593
594/* change the emulated temperature */
595static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200596_hwSensors_setTemperature( HwSensors* h, float celsius )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700597{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200598 Sensor* s = &h->sensors[ANDROID_SENSOR_TEMPERATURE];
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700599 s->u.temperature.celsius = celsius;
600}
601#endif
602
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100603/* change the emulated proximity */
604static void
605_hwSensors_setProximity( HwSensors* h, float value )
606{
607 Sensor* s = &h->sensors[ANDROID_SENSOR_PROXIMITY];
608 s->u.proximity.value = value;
609}
610
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700611/* change the coarse orientation (landscape/portrait) of the emulated device */
612static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200613_hwSensors_setCoarseOrientation( HwSensors* h, AndroidCoarseOrientation orient )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700614{
615 /* The Android framework computes the orientation by looking at
616 * the accelerometer sensor (*not* the orientation sensor !)
617 *
618 * That's because the gravity is a constant 9.81 vector that
619 * can be determined quite easily.
620 *
621 * Also, for some reason, the framework code considers that the phone should
622 * be inclined by 30 degrees along the phone's X axis to be considered
623 * in its ideal "vertical" position
624 *
625 * If the phone is completely vertical, rotating it will not do anything !
626 */
627 const double g = 9.81;
628 const double cos_30 = 0.866025403784;
629 const double sin_30 = 0.5;
630
631 switch (orient) {
632 case ANDROID_COARSE_PORTRAIT:
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200633 _hwSensors_setAcceleration( h, 0., g*cos_30, g*sin_30 );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700634 break;
635
636 case ANDROID_COARSE_LANDSCAPE:
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200637 _hwSensors_setAcceleration( h, g*cos_30, 0., g*sin_30 );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700638 break;
639 default:
640 ;
641 }
642}
643
644
645/* initialize the sensors state */
646static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200647_hwSensors_init( HwSensors* h )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700648{
Ot ten Thije871da2a2010-09-20 10:29:22 +0100649 h->service = qemud_service_register("sensors", 0, h, _hwSensors_connect,
650 _hwSensors_save, _hwSensors_load);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700651
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200652 if (android_hw->hw_accelerometer)
653 h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1;
654
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100655 if (android_hw->hw_sensors_proximity)
656 h->sensors[ANDROID_SENSOR_PROXIMITY].enabled = 1;
657
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200658 /* XXX: TODO: Add other tests when we add the corresponding
659 * properties to hardware-properties.ini et al. */
660
661 _hwSensors_setCoarseOrientation(h, ANDROID_COARSE_PORTRAIT);
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100662 _hwSensors_setProximity(h, 1);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700663}
664
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700665static HwSensors _sensorsState[1];
666
667void
668android_hw_sensors_init( void )
669{
670 HwSensors* hw = _sensorsState;
671
672 if (hw->service == NULL) {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200673 _hwSensors_init(hw);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700674 D("%s: sensors qemud service initialized", __FUNCTION__);
675 }
676}
677
678/* change the coarse orientation value */
679extern void
680android_sensors_set_coarse_orientation( AndroidCoarseOrientation orient )
681{
682 android_hw_sensors_init();
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200683 _hwSensors_setCoarseOrientation(_sensorsState, orient);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700684}
685