模拟器在硬件上为android提供虚拟sensors,通过模拟器console,或者模拟器sensors socket通道,我们可以从外界(比如eclipse调试工具)设置这些虚拟sensors的值
模拟器中运行的android,通过qemu sensor HAL拿到这些sensors值,qemu sensor HAL与实体手机的sensor HAL的区别在于:实体手机的sensor HAL通过底层Linux驱动获取真实sensors数据,qemu sensor HAL通过qemud的socket通道获取前面设置的虚拟sensors值
关于qemud,代码(qemud.c)中有一段介绍,很好说明了qemud与模拟器、qemu sensor HAL之间的关系:
the qemud daemon program is only used within Android as a bridge between the emulator program and the emulated system. it really works as a simple stream multiplexer that works as follows: - qemud is started by init following instructions in /system/etc/init.goldfish.rc (i.e. it is never started on real devices) - qemud communicates with the emulator program through a single serial port, whose name is passed through a kernel boot parameter (e.g. android.qemud=ttyS1) - qemud binds one unix local stream socket (/dev/socket/qemud, created by init through /system/etc/init.goldfish.rc). emulator <==serial==> qemud <---> /dev/socket/qemud <-+--> client1 | +--> client2 -+-->--->==serial==>qemud是一个桥梁,emulator将从外部应用接受到的sensors数据,通过serial串口给qemud,qemud再通过socket通道将数据传递给连接进来的client,qemu sensor HAL就是client之一 init.goldfish.rc脚本的选择依据:查看/proc/cpuinfo文件,其中的Hardware字段表明了使用哪一个init.?.rc配置,模拟器为goldfish 可以看看这幅图,更好理解qemud与模拟器、qemu sensor HAL之间的关系

sensors数据格式
HAL层发送过来的请求数据主要包括这么几种格式: "list-sensors":列出支持的sensors列表,模拟器将返回一个int表示支持的sensors mask值 "wake":原样返回给HAL,让HAL退出poll循环 "set-delay:%d":设置sensors轮询间隔 "set:%s:%d":设置对应的sensor是否enable,例如"set:acceleration:1" 模拟器将虚拟sensors数据返回给HAL,格式如下: "acceleration:%g:%g:%g":获取加速度传感器数据 "orientation:%g:%g:%g":获取方向传感器数据 "magnetic:%g:%g:%g":获取磁力传感器数据 "temperature:%g":获取温度传感器数据 "proximity:%g":获取距离传感器数据 "sync:%lld":sent after a series of sensor events where 'time' is expressed in micro-seconds下面来看看具体的代码 qemu sensor HAL层对应的代码位于device/generic/goldfish/sensors/sensors_qemu.c 模拟器的虚拟sensors代码位于android-4.4/external/qemu/android/hw-sensors.c
/* handle incoming messages from the HAL module */ static void _hwSensorClient_receive( HwSensorClient* cl, uint8_t* msg, int msglen ) { HwSensors* hw = cl->sensors; D("%s: '%.*s'", __FUNCTION__, msglen, msg); /* "list-sensors" is used to get an integer bit map of * available emulated sensors. We compute the mask from the * current hardware configuration. */ if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) { char buff[12]; int mask = 0; int nn; for (nn = 0; nn < MAX_SENSORS; nn++) { if (hw->sensors[nn].enabled) mask |= (1 << nn); } snprintf(buff, sizeof buff, "%d", mask); _hwSensorClient_send(cl, (const uint8_t*)buff, strlen(buff)); return; } /* "wake" is a special message that must be sent back through * the channel. It is used to exit a blocking read. */ if (msglen == 4 && !memcmp(msg, "wake", 4)) { _hwSensorClient_send(cl, (const uint8_t*)"wake", 4); return; } /* "set-delay:<delay>" is used to set the delay in milliseconds * between sensor events */ if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) { cl->delay_ms = atoi((const char*)msg+10); if (cl->enabledMask != 0) _hwSensorClient_tick(cl); return; } /* "set:<name>:<state>" is used to enable/disable a given * sensor. <state> must be 0 or 1 */ if (msglen > 4 && !memcmp(msg, "set:", 4)) { char* q; int id, enabled, oldEnabledMask = cl->enabledMask; msg += 4; q = strchr((char*)msg, ':'); if (q == NULL) { /* should not happen */ D("%s: ignore bad 'set' command", __FUNCTION__); return; } *q++ = 0; id = _sensorIdFromName((const char*)msg); if (id < 0 || id >= MAX_SENSORS) { D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg); return; } if (!hw->sensors[id].enabled) { D("%s: trying to set disabled %s sensor", __FUNCTION__, msg); return; } enabled = (q[0] == '1'); if (enabled) cl->enabledMask |= (1 << id); else cl->enabledMask &= ~(1 << id); if (cl->enabledMask != oldEnabledMask) { D("%s: %s %s sensor", __FUNCTION__, (cl->enabledMask & (1 << id)) ? "enabling" : "disabling", msg); } /* If emulating device is connected update sensor state there too. */ if (hw->sensors_port != NULL) { if (enabled) { sensors_port_enable_sensor(hw->sensors_port, (const char*)msg); } else { sensors_port_disable_sensor(hw->sensors_port, (const char*)msg); } } _hwSensorClient_tick(cl); return; } D("%s: ignoring unknown query", __FUNCTION__); }
/* this function is called periodically to send sensor reports * to the HAL module, and re-arm the timer if necessary */ static void _hwSensorClient_tick( void* opaque ) { HwSensorClient* cl = opaque; HwSensors* hw = cl->sensors; int64_t delay = cl->delay_ms; int64_t now_ns; uint32_t mask = cl->enabledMask; Sensor* sensor; char buffer[128]; if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ACCELERATION)) { sensor = &hw->sensors[ANDROID_SENSOR_ACCELERATION]; snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g", sensor->u.acceleration.x, sensor->u.acceleration.y, sensor->u.acceleration.z); _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); } if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_MAGNETIC_FIELD)) { sensor = &hw->sensors[ANDROID_SENSOR_MAGNETIC_FIELD]; /* NOTE: sensors HAL expects "magnetic", not "magnetic-field" name here. */ snprintf(buffer, sizeof buffer, "magnetic:%g:%g:%g", sensor->u.magnetic.x, sensor->u.magnetic.y, sensor->u.magnetic.z); _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); } if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ORIENTATION)) { sensor = &hw->sensors[ANDROID_SENSOR_ORIENTATION]; snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g", sensor->u.orientation.azimuth, sensor->u.orientation.pitch, sensor->u.orientation.roll); _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); } if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_TEMPERATURE)) { sensor = &hw->sensors[ANDROID_SENSOR_TEMPERATURE]; snprintf(buffer, sizeof buffer, "temperature:%g", sensor->u.temperature.celsius); _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); } if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_PROXIMITY)) { sensor = &hw->sensors[ANDROID_SENSOR_PROXIMITY]; snprintf(buffer, sizeof buffer, "proximity:%g", sensor->u.proximity.value); _hwSensorClient_send(cl, (uint8_t*) buffer, strlen(buffer)); } now_ns = qemu_get_clock_ns(vm_clock); snprintf(buffer, sizeof buffer, "sync:%" PRId64, now_ns/1000); _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); /* rearm timer, use a minimum delay of 20 ms, just to * be safe. */ if (mask == 0) return; if (delay < 20) delay = 20; delay *= 1000000LL; /* convert to nanoseconds */ qemu_mod_timer(cl->timer, now_ns + delay); } /* send a one-line message to the HAL module through a qemud channel */ static void _hwSensorClient_send( HwSensorClient* cl, const uint8_t* msg, int msglen ) { D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen)); qemud_client_send(cl->client, msg, msglen); }