• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "qemu-char.h"
20 #include "qemu-timer.h"
21 
22 #define  D(...)  VERBOSE_PRINT(sensors,__VA_ARGS__)
23 
24 /* define T_ACTIVE to 1 to debug transport communications */
25 #define  T_ACTIVE  0
26 
27 #if T_ACTIVE
28 #define  T(...)  VERBOSE_PRINT(sensors,__VA_ARGS__)
29 #else
30 #define  T(...)   ((void)0)
31 #endif
32 
33 /* this code supports emulated sensor hardware
34  *
35  * Note that currently, only the accelerometer is really emulated, and only
36  * for the purpose of allowing auto-rotating the screen in keyboard-less
37  * configurations.
38  *
39  *
40  */
41 
42 
43 static const struct {
44     const char*  name;
45     int          id;
46 } _sSensors[MAX_SENSORS] = {
47 #define SENSOR_(x,y)  { y, ANDROID_SENSOR_##x },
48   SENSORS_LIST
49 #undef SENSOR_
50 };
51 
52 
53 static int
_sensorIdFromName(const char * name)54 _sensorIdFromName( const char*  name )
55 {
56     int  nn;
57     for (nn = 0; nn < MAX_SENSORS; nn++)
58         if (!strcmp(_sSensors[nn].name,name))
59             return _sSensors[nn].id;
60     return -1;
61 }
62 
63 
64 typedef struct {
65     float   x, y, z;
66 } Acceleration;
67 
68 
69 typedef struct {
70     float  x, y, z;
71 } MagneticField;
72 
73 
74 typedef struct {
75     float  azimuth;
76     float  pitch;
77     float  roll;
78 } Orientation;
79 
80 
81 typedef struct {
82     float  celsius;
83 } Temperature;
84 
85 
86 typedef struct {
87     char       enabled;
88     union {
89         Acceleration   acceleration;
90         MagneticField  magnetic;
91         Orientation    orientation;
92         Temperature    temperature;
93     } u;
94 } Sensor;
95 
96 /*
97  * - when the qemu-specific sensors HAL module starts, it sends
98  *   "list-sensors"
99  *
100  * - this code replies with a string containing an integer corresponding
101  *   to a bitmap of available hardware sensors in the current AVD
102  *   configuration (e.g. "1" a.k.a (1 << ANDROID_SENSOR_ACCELERATION))
103  *
104  * - the HAL module sends "set:<sensor>:<flag>" to enable or disable
105  *   the report of a given sensor state. <sensor> must be the name of
106  *   a given sensor (e.g. "accelerometer"), and <flag> must be either
107  *   "1" (to enable) or "0" (to disable).
108  *
109  * - Once at least one sensor is "enabled", this code should periodically
110  *   send information about the corresponding enabled sensors. The default
111  *   period is 200ms.
112  *
113  * - the HAL module sends "set-delay:<delay>", where <delay> is an integer
114  *   corresponding to a time delay in milli-seconds. This corresponds to
115  *   a new interval between sensor events sent by this code to the HAL
116  *   module.
117  *
118  * - the HAL module can also send a "wake" command. This code should simply
119  *   send the "wake" back to the module. This is used internally to wake a
120  *   blocking read that happens in a different thread. This ping-pong makes
121  *   the code in the HAL module very simple.
122  *
123  * - each timer tick, this code sends sensor reports in the following
124  *   format (each line corresponds to a different line sent to the module):
125  *
126  *      acceleration:<x>:<y>:<z>
127  *      magnetic-field:<x>:<y>:<z>
128  *      orientation:<azimuth>:<pitch>:<roll>
129  *      temperature:<celsius>
130  *      sync:<time_us>
131  *
132  *   Where each line before the sync:<time_us> is optional and will only
133  *   appear if the corresponding sensor has been enabled by the HAL module.
134  *
135  *   Note that <time_us> is the VM time in micro-seconds when the report
136  *   was "taken" by this code. This is adjusted by the HAL module to
137  *   emulated system time (using the first sync: to compute an adjustment
138  *   offset).
139  */
140 #define  HEADER_SIZE  4
141 #define  BUFFER_SIZE  512
142 
143 typedef struct HwSensorClient   HwSensorClient;
144 
145 typedef struct {
146     QemudService*    service;
147     Sensor           sensors[MAX_SENSORS];
148     HwSensorClient*  clients;
149 } HwSensors;
150 
151 struct HwSensorClient {
152     HwSensorClient*  next;
153     HwSensors*       sensors;
154     QemudClient*     client;
155     QEMUTimer*       timer;
156     uint32_t         enabledMask;
157     int32_t          delay_ms;
158 };
159 
160 static void
_hwSensorClient_free(HwSensorClient * cl)161 _hwSensorClient_free( HwSensorClient*  cl )
162 {
163     /* remove from sensors's list */
164     if (cl->sensors) {
165         HwSensorClient**  pnode = &cl->sensors->clients;
166         for (;;) {
167             HwSensorClient*  node = *pnode;
168             if (node == NULL)
169                 break;
170             if (node == cl) {
171                 *pnode = cl->next;
172                 break;
173             }
174             pnode = &node->next;
175         }
176         cl->next    = NULL;
177         cl->sensors = NULL;
178     }
179 
180     /* close QEMUD client, if any */
181     if (cl->client) {
182         qemud_client_close(cl->client);
183         cl->client = NULL;
184     }
185     /* remove timer, if any */
186     if (cl->timer) {
187         qemu_del_timer(cl->timer);
188         qemu_free_timer(cl->timer);
189         cl->timer = NULL;
190     }
191     AFREE(cl);
192 }
193 
194 /* forward */
195 static void  _hwSensorClient_tick(void*  opaque);
196 
197 
198 static HwSensorClient*
_hwSensorClient_new(HwSensors * sensors)199 _hwSensorClient_new( HwSensors*  sensors )
200 {
201     HwSensorClient*  cl;
202 
203     ANEW0(cl);
204 
205     cl->sensors     = sensors;
206     cl->enabledMask = 0;
207     cl->delay_ms    = 1000;
208     cl->timer       = qemu_new_timer(vm_clock, _hwSensorClient_tick, cl);
209 
210     cl->next         = sensors->clients;
211     sensors->clients = cl;
212 
213     return cl;
214 }
215 
216 /* forward */
217 
218 static void  _hwSensorClient_receive( HwSensorClient*  cl,
219                                       uint8_t*         query,
220                                       int              querylen );
221 
222 /* Qemud service management */
223 
224 static void
_hwSensorClient_recv(void * opaque,uint8_t * msg,int msglen,QemudClient * client)225 _hwSensorClient_recv( void*  opaque, uint8_t*  msg, int  msglen,
226                       QemudClient*  client )
227 {
228     HwSensorClient*  cl = opaque;
229 
230     _hwSensorClient_receive(cl, msg, msglen);
231 }
232 
233 static void
_hwSensorClient_close(void * opaque)234 _hwSensorClient_close( void*  opaque )
235 {
236     HwSensorClient*  cl = opaque;
237 
238     /* the client is already closed here */
239     cl->client = NULL;
240     _hwSensorClient_free(cl);
241 }
242 
243 /* send a one-line message to the HAL module through a qemud channel */
244 static void
_hwSensorClient_send(HwSensorClient * cl,const uint8_t * msg,int msglen)245 _hwSensorClient_send( HwSensorClient*  cl, const uint8_t*  msg, int  msglen )
246 {
247     D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen));
248     qemud_client_send(cl->client, msg, msglen);
249 }
250 
251 static int
_hwSensorClient_enabled(HwSensorClient * cl,int sensorId)252 _hwSensorClient_enabled( HwSensorClient*  cl, int  sensorId )
253 {
254     return (cl->enabledMask & (1 << sensorId)) != 0;
255 }
256 
257 /* this function is called periodically to send sensor reports
258  * to the HAL module, and re-arm the timer if necessary
259  */
260 static void
_hwSensorClient_tick(void * opaque)261 _hwSensorClient_tick( void*  opaque )
262 {
263     HwSensorClient*  cl = opaque;
264     HwSensors*       hw  = cl->sensors;
265     int64_t          delay = cl->delay_ms;
266     int64_t          now_ns;
267     uint32_t         mask  = cl->enabledMask;
268     Sensor*          sensor;
269     char             buffer[128];
270 
271     if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ACCELERATION)) {
272         sensor = &hw->sensors[ANDROID_SENSOR_ACCELERATION];
273         snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g",
274                  sensor->u.acceleration.x,
275                  sensor->u.acceleration.y,
276                  sensor->u.acceleration.z);
277         _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
278     }
279 
280     if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_MAGNETIC_FIELD)) {
281         sensor = &hw->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
282         snprintf(buffer, sizeof buffer, "magnetic-field:%g:%g:%g",
283                  sensor->u.magnetic.x,
284                  sensor->u.magnetic.y,
285                  sensor->u.magnetic.z);
286         _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
287     }
288 
289     if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ORIENTATION)) {
290         sensor = &hw->sensors[ANDROID_SENSOR_ORIENTATION];
291         snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g",
292                  sensor->u.orientation.azimuth,
293                  sensor->u.orientation.pitch,
294                  sensor->u.orientation.roll);
295         _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
296     }
297 
298     if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_TEMPERATURE)) {
299         sensor = &hw->sensors[ANDROID_SENSOR_TEMPERATURE];
300         snprintf(buffer, sizeof buffer, "temperature:%g",
301                  sensor->u.temperature.celsius);
302         _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
303     }
304 
305     now_ns = qemu_get_clock(vm_clock);
306 
307     snprintf(buffer, sizeof buffer, "sync:%lld", now_ns/1000);
308     _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
309 
310     /* rearm timer, use a minimum delay of 20 ms, just to
311      * be safe.
312      */
313     if (mask == 0)
314         return;
315 
316     if (delay < 20)
317         delay = 20;
318 
319     delay *= 1000000LL;  /* convert to nanoseconds */
320     qemu_mod_timer(cl->timer, now_ns + delay);
321 }
322 
323 /* handle incoming messages from the HAL module */
324 static void
_hwSensorClient_receive(HwSensorClient * cl,uint8_t * msg,int msglen)325 _hwSensorClient_receive( HwSensorClient*  cl, uint8_t*  msg, int  msglen )
326 {
327     HwSensors*  hw = cl->sensors;
328 
329     D("%s: '%.*s'", __FUNCTION__, msglen, msg);
330 
331     /* "list-sensors" is used to get an integer bit map of
332      * available emulated sensors. We compute the mask from the
333      * current hardware configuration.
334      */
335     if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) {
336         char  buff[12];
337         int   mask = 0;
338         int   nn;
339 
340         for (nn = 0; nn < MAX_SENSORS; nn++) {
341             if (hw->sensors[nn].enabled)
342                 mask |= (1 << nn);
343         }
344 
345         snprintf(buff, sizeof buff, "%d", mask);
346         _hwSensorClient_send(cl, (const uint8_t*)buff, strlen(buff));
347         return;
348     }
349 
350     /* "wake" is a special message that must be sent back through
351      * the channel. It is used to exit a blocking read.
352      */
353     if (msglen == 4 && !memcmp(msg, "wake", 4)) {
354         _hwSensorClient_send(cl, (const uint8_t*)"wake", 4);
355         return;
356     }
357 
358     /* "set-delay:<delay>" is used to set the delay in milliseconds
359      * between sensor events
360      */
361     if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) {
362         cl->delay_ms = atoi((const char*)msg+10);
363         if (cl->enabledMask != 0)
364             _hwSensorClient_tick(cl);
365 
366         return;
367     }
368 
369     /* "set:<name>:<state>" is used to enable/disable a given
370      * sensor. <state> must be 0 or 1
371      */
372     if (msglen > 4 && !memcmp(msg, "set:", 4)) {
373         char*  q;
374         int    id, enabled, oldEnabledMask = cl->enabledMask;
375         msg += 4;
376         q    = strchr((char*)msg, ':');
377         if (q == NULL) {  /* should not happen */
378             D("%s: ignore bad 'set' command", __FUNCTION__);
379             return;
380         }
381         *q++ = 0;
382 
383         id = _sensorIdFromName((const char*)msg);
384         if (id < 0 || id >= MAX_SENSORS) {
385             D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg);
386             return;
387         }
388 
389         if (!hw->sensors[id].enabled) {
390             D("%s: trying to set disabled %s sensor", __FUNCTION__, msg);
391             return;
392         }
393         enabled = (q[0] == '1');
394 
395         if (enabled)
396             cl->enabledMask |= (1 << id);
397         else
398             cl->enabledMask &= ~(1 << id);
399 
400         if (cl->enabledMask != oldEnabledMask) {
401             D("%s: %s %s sensor", __FUNCTION__,
402                 (cl->enabledMask & (1 << id))  ? "enabling" : "disabling",  msg);
403         }
404         _hwSensorClient_tick(cl);
405         return;
406     }
407 
408     D("%s: ignoring unknown query", __FUNCTION__);
409 }
410 
411 
412 static QemudClient*
_hwSensors_connect(void * opaque,QemudService * service,int channel)413 _hwSensors_connect( void*  opaque, QemudService*  service, int  channel )
414 {
415     HwSensors*       sensors = opaque;
416     HwSensorClient*  cl      = _hwSensorClient_new(sensors);
417     QemudClient*     client  = qemud_client_new(service, channel, cl,
418                                                 _hwSensorClient_recv,
419                                                 _hwSensorClient_close);
420     qemud_client_set_framing(client, 1);
421     cl->client = client;
422 
423     return client;
424 }
425 
426 /* change the value of the emulated acceleration vector */
427 static void
_hwSensors_setAcceleration(HwSensors * h,float x,float y,float z)428 _hwSensors_setAcceleration( HwSensors*  h, float x, float y, float z )
429 {
430     Sensor*  s = &h->sensors[ANDROID_SENSOR_ACCELERATION];
431     s->u.acceleration.x = x;
432     s->u.acceleration.y = y;
433     s->u.acceleration.z = z;
434 }
435 
436 #if 0  /* not used yet */
437 /* change the value of the emulated magnetic vector */
438 static void
439 _hwSensors_setMagneticField( HwSensors*  h, float x, float y, float z )
440 {
441     Sensor*  s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
442     s->u.magnetic.x = x;
443     s->u.magnetic.y = y;
444     s->u.magnetic.z = z;
445 }
446 
447 /* change the values of the emulated orientation */
448 static void
449 _hwSensors_setOrientation( HwSensors*  h, float azimuth, float pitch, float roll )
450 {
451     Sensor*  s = &h->sensors[ANDROID_SENSOR_ORIENTATION];
452     s->u.orientation.azimuth = azimuth;
453     s->u.orientation.pitch   = pitch;
454     s->u.orientation.roll    = roll;
455 }
456 
457 /* change the emulated temperature */
458 static void
459 _hwSensors_setTemperature( HwSensors*  h, float celsius )
460 {
461     Sensor*  s = &h->sensors[ANDROID_SENSOR_TEMPERATURE];
462     s->u.temperature.celsius = celsius;
463 }
464 #endif
465 
466 /* change the coarse orientation (landscape/portrait) of the emulated device */
467 static void
_hwSensors_setCoarseOrientation(HwSensors * h,AndroidCoarseOrientation orient)468 _hwSensors_setCoarseOrientation( HwSensors*  h, AndroidCoarseOrientation  orient )
469 {
470     /* The Android framework computes the orientation by looking at
471      * the accelerometer sensor (*not* the orientation sensor !)
472      *
473      * That's because the gravity is a constant 9.81 vector that
474      * can be determined quite easily.
475      *
476      * Also, for some reason, the framework code considers that the phone should
477      * be inclined by 30 degrees along the phone's X axis to be considered
478      * in its ideal "vertical" position
479      *
480      * If the phone is completely vertical, rotating it will not do anything !
481      */
482     const double  g      = 9.81;
483     const double  cos_30 = 0.866025403784;
484     const double  sin_30 = 0.5;
485 
486     switch (orient) {
487     case ANDROID_COARSE_PORTRAIT:
488         _hwSensors_setAcceleration( h, 0., g*cos_30, g*sin_30 );
489         break;
490 
491     case ANDROID_COARSE_LANDSCAPE:
492         _hwSensors_setAcceleration( h, g*cos_30, 0., g*sin_30 );
493         break;
494     default:
495         ;
496     }
497 }
498 
499 
500 /* initialize the sensors state */
501 static void
_hwSensors_init(HwSensors * h)502 _hwSensors_init( HwSensors*  h )
503 {
504     h->service = qemud_service_register("sensors", 0, h,
505                                         _hwSensors_connect );
506 
507     if (android_hw->hw_accelerometer)
508         h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1;
509 
510     /* XXX: TODO: Add other tests when we add the corresponding
511         * properties to hardware-properties.ini et al. */
512 
513     _hwSensors_setCoarseOrientation(h, ANDROID_COARSE_PORTRAIT);
514 }
515 
516 static HwSensors    _sensorsState[1];
517 
518 void
android_hw_sensors_init(void)519 android_hw_sensors_init( void )
520 {
521     HwSensors*  hw = _sensorsState;
522 
523     if (hw->service == NULL) {
524         _hwSensors_init(hw);
525         D("%s: sensors qemud service initialized", __FUNCTION__);
526     }
527 }
528 
529 /* change the coarse orientation value */
530 extern void
android_sensors_set_coarse_orientation(AndroidCoarseOrientation orient)531 android_sensors_set_coarse_orientation( AndroidCoarseOrientation  orient )
532 {
533     android_hw_sensors_init();
534     _hwSensors_setCoarseOrientation(_sensorsState, orient);
535 }
536 
537