hw-sensors.c revision 7c8397abd80cd6ba6a2665ef22739e603ae4c290
1/* 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"
16#include "android/utils/system.h"
17#include "android/hw-qemud.h"
18#include "android/globals.h"
19#include "hw/hw.h"
20#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 {
88    float  value;
89} Proximity;
90
91typedef struct {
92    char       enabled;
93    union {
94        Acceleration   acceleration;
95        MagneticField  magnetic;
96        Orientation    orientation;
97        Temperature    temperature;
98        Proximity      proximity;
99    } 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
149typedef struct HwSensorClient   HwSensorClient;
150
151typedef struct {
152    QemudService*    service;
153    Sensor           sensors[MAX_SENSORS];
154    HwSensorClient*  clients;
155} HwSensors;
156
157struct 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
222/* forward */
223
224static void  _hwSensorClient_receive( HwSensorClient*  cl,
225                                      uint8_t*         query,
226                                      int              querylen );
227
228/* Qemud service management */
229
230static void
231_hwSensorClient_recv( void*  opaque, uint8_t*  msg, int  msglen,
232                      QemudClient*  client )
233{
234    HwSensorClient*  cl = opaque;
235
236    _hwSensorClient_receive(cl, msg, msglen);
237}
238
239static void
240_hwSensorClient_close( void*  opaque )
241{
242    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
311    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
318    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
424/* 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}
447
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,
455                                                _hwSensorClient_close,
456                                                _hwSensorClient_save,
457                                                _hwSensorClient_load );
458    qemud_client_set_framing(client, 1);
459    cl->client = client;
460
461    return client;
462}
463
464/* change the value of the emulated acceleration vector */
465static void
466_hwSensors_setAcceleration( HwSensors*  h, float x, float y, float z )
467{
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
474/* 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;
510        case ANDROID_SENSOR_PROXIMITY:
511            qemu_put_float(f, s->u.proximity.value);
512            break;
513        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;
561        case ANDROID_SENSOR_PROXIMITY:
562            s->u.proximity.value = qemu_get_float(f);
563            break;
564        case MAX_SENSORS:
565            break;
566        }
567    }
568
569    return 0;
570}
571
572
573#if 0  /* not used yet */
574/* change the value of the emulated magnetic vector */
575static void
576_hwSensors_setMagneticField( HwSensors*  h, float x, float y, float z )
577{
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
586_hwSensors_setOrientation( HwSensors*  h, float azimuth, float pitch, float roll )
587{
588    Sensor*  s = &h->sensors[ANDROID_SENSOR_ORIENTATION];
589    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
596_hwSensors_setTemperature( HwSensors*  h, float celsius )
597{
598    Sensor*  s = &h->sensors[ANDROID_SENSOR_TEMPERATURE];
599    s->u.temperature.celsius = celsius;
600}
601#endif
602
603/* 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
611/* change the coarse orientation (landscape/portrait) of the emulated device */
612static void
613_hwSensors_setCoarseOrientation( HwSensors*  h, AndroidCoarseOrientation  orient )
614{
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:
633        _hwSensors_setAcceleration( h, 0., g*cos_30, g*sin_30 );
634        break;
635
636    case ANDROID_COARSE_LANDSCAPE:
637        _hwSensors_setAcceleration( h, g*cos_30, 0., g*sin_30 );
638        break;
639    default:
640        ;
641    }
642}
643
644
645/* initialize the sensors state */
646static void
647_hwSensors_init( HwSensors*  h )
648{
649    h->service = qemud_service_register("sensors", 0, h, _hwSensors_connect,
650                                        _hwSensors_save, _hwSensors_load);
651
652    if (android_hw->hw_accelerometer)
653        h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1;
654
655    if (android_hw->hw_sensors_proximity)
656        h->sensors[ANDROID_SENSOR_PROXIMITY].enabled = 1;
657
658    /* 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);
662    _hwSensors_setProximity(h, 1);
663}
664
665static HwSensors    _sensorsState[1];
666
667void
668android_hw_sensors_init( void )
669{
670    HwSensors*  hw = _sensorsState;
671
672    if (hw->service == NULL) {
673        _hwSensors_init(hw);
674        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();
683    _hwSensors_setCoarseOrientation(_sensorsState, orient);
684}
685
686