X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fandroid%2Fsensors%2Fsensors_qemu.c;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fandroid%2Fsensors%2Fsensors_qemu.c;h=b0e858cca2f9dfa272bdd0501d1ecb94c4641641;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/android/sensors/sensors_qemu.c b/src/type3_AndroidCloud/anbox-master/android/sensors/sensors_qemu.c new file mode 100644 index 0000000..b0e858c --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/android/sensors/sensors_qemu.c @@ -0,0 +1,751 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* this implements a sensors hardware library for the Android emulator. + * the following code should be built as a shared library that will be + * placed into /system/lib/hw/sensors.goldfish.so + * + * it will be loaded by the code in hardware/libhardware/hardware.c + * which is itself called from com_android_server_SensorService.cpp + */ + + +/* we connect with the emulator through the "sensors" qemud service + */ +#define SENSORS_SERVICE_NAME "sensors" + +#define LOG_TAG "QemuSensors" + +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define D(...) ALOGD(__VA_ARGS__) +#else +#define D(...) ((void)0) +#endif + +#define E(...) ALOGE(__VA_ARGS__) + +#include + +/** SENSOR IDS AND NAMES + **/ + +#define MAX_NUM_SENSORS 8 + +#define SUPPORTED_SENSORS ((1<"; +} + +static int +_sensorIdFromName( const char* name ) +{ + int nn; + + if (name == NULL) + return -1; + + for (nn = 0; nn < MAX_NUM_SENSORS; nn++) + if (!strcmp(name, _sensorIds[nn].name)) + return _sensorIds[nn].id; + + return -1; +} + +/* return the current time in nanoseconds */ +static int64_t now_ns(void) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (int64_t)ts.tv_sec * 1000000000 + ts.tv_nsec; +} + +/** SENSORS POLL DEVICE + ** + ** This one is used to read sensor data from the hardware. + ** We implement this by simply reading the data from the + ** emulator through the QEMUD channel. + **/ + +typedef struct SensorDevice { + struct sensors_poll_device_1 device; + sensors_event_t sensors[MAX_NUM_SENSORS]; + uint32_t pendingSensors; + int64_t timeStart; + int64_t timeOffset; + uint32_t active_sensors; + int fd; + pthread_mutex_t lock; +} SensorDevice; + +/* Grab the file descriptor to the emulator's sensors service pipe. + * This function returns a file descriptor on success, or -errno on + * failure, and assumes the SensorDevice instance's lock is held. + * + * This is needed because set_delay(), poll() and activate() can be called + * from different threads, and poll() is blocking. + * + * Note that the emulator's sensors service creates a new client for each + * connection through qemud_channel_open(), where each client has its own + * delay and set of activated sensors. This precludes calling + * qemud_channel_open() on each request, because a typical emulated system + * will do something like: + * + * 1) On a first thread, de-activate() all sensors first, then call poll(), + * which results in the thread blocking. + * + * 2) On a second thread, slightly later, call set_delay() then activate() + * to enable the acceleration sensor. + * + * The system expects this to unblock the first thread which will receive + * new sensor events after the activate() call in 2). + * + * This cannot work if both threads don't use the same connection. + * + * TODO(digit): This protocol is brittle, implement another control channel + * for set_delay()/activate()/batch() when supporting HAL 1.3 + */ +static int sensor_device_get_fd_locked(SensorDevice* dev) { + /* Create connection to service on first call */ + if (dev->fd < 0) { + dev->fd = qemud_channel_open(SENSORS_SERVICE_NAME); + if (dev->fd < 0) { + int ret = -errno; + E("%s: Could not open connection to service: %s", __FUNCTION__, + strerror(-ret)); + return ret; + } + } + return dev->fd; +} + +/* Send a command to the sensors virtual device. |dev| is a device instance and + * |cmd| is a zero-terminated command string. Return 0 on success, or -errno + * on failure. */ +static int sensor_device_send_command_locked(SensorDevice* dev, + const char* cmd) { + int fd = sensor_device_get_fd_locked(dev); + if (fd < 0) { + return fd; + } + + int ret = 0; + if (qemud_channel_send(fd, cmd, strlen(cmd)) < 0) { + ret = -errno; + E("%s(fd=%d): ERROR: %s", __FUNCTION__, fd, strerror(errno)); + } + return ret; +} + +/* Pick up one pending sensor event. On success, this returns the sensor + * id, and sets |*event| accordingly. On failure, i.e. if there are no + * pending events, return -EINVAL. + * + * Note: The device's lock must be acquired. + */ +static int sensor_device_pick_pending_event_locked(SensorDevice* d, + sensors_event_t* event) +{ + uint32_t mask = SUPPORTED_SENSORS & d->pendingSensors; + if (mask) { + uint32_t i = 31 - __builtin_clz(mask); + d->pendingSensors &= ~(1U << i); + *event = d->sensors[i]; + event->sensor = i; + event->version = sizeof(*event); + + D("%s: %d [%f, %f, %f]", __FUNCTION__, + i, + event->data[0], + event->data[1], + event->data[2]); + return i; + } + E("No sensor to return!!! pendingSensors=0x%08x", d->pendingSensors); + // we may end-up in a busy loop, slow things down, just in case. + usleep(100000); + return -EINVAL; +} + +/* Block until new sensor events are reported by the emulator, or if a + * 'wake' command is received through the service. On succes, return 0 + * and updates the |pendingEvents| and |sensors| fields of |dev|. + * On failure, return -errno. + * + * Note: The device lock must be acquired when calling this function, and + * will still be held on return. However, the function releases the + * lock temporarily during the blocking wait. + */ +static int sensor_device_poll_event_locked(SensorDevice* dev) +{ + D("%s: dev=%p", __FUNCTION__, dev); + + int fd = sensor_device_get_fd_locked(dev); + if (fd < 0) { + E("%s: Could not get pipe channel: %s", __FUNCTION__, strerror(-fd)); + return fd; + } + + // Accumulate pending events into |events| and |new_sensors| mask + // until a 'sync' or 'wake' command is received. This also simplifies the + // code a bit. + uint32_t new_sensors = 0U; + sensors_event_t* events = dev->sensors; + + int64_t event_time = -1; + int ret = 0; + + for (;;) { + /* Release the lock since we're going to block on recv() */ + pthread_mutex_unlock(&dev->lock); + + /* read the next event */ + char buff[256]; + int len = qemud_channel_recv(fd, buff, sizeof(buff) - 1U); + /* re-acquire the lock to modify the device state. */ + pthread_mutex_lock(&dev->lock); + + if (len < 0) { + ret = -errno; + E("%s(fd=%d): Could not receive event data len=%d, errno=%d: %s", + __FUNCTION__, fd, len, errno, strerror(errno)); + break; + } + buff[len] = 0; + D("%s(fd=%d): received [%s]", __FUNCTION__, fd, buff); + + + /* "wake" is sent from the emulator to exit this loop. */ + /* TODO(digit): Is it still needed? */ + if (!strcmp((const char*)buff, "wake")) { + ret = 0x7FFFFFFF; + break; + } + + float params[3]; + + /* "acceleration:::" corresponds to an acceleration event */ + if (sscanf(buff, "acceleration:%g:%g:%g", params+0, params+1, params+2) + == 3) { + new_sensors |= SENSORS_ACCELERATION; + events[ID_ACCELERATION].acceleration.x = params[0]; + events[ID_ACCELERATION].acceleration.y = params[1]; + events[ID_ACCELERATION].acceleration.z = params[2]; + events[ID_ACCELERATION].type = SENSOR_TYPE_ACCELEROMETER; + continue; + } + + /* "orientation:::" is sent when orientation + * changes */ + if (sscanf(buff, "orientation:%g:%g:%g", params+0, params+1, params+2) + == 3) { + new_sensors |= SENSORS_ORIENTATION; + events[ID_ORIENTATION].orientation.azimuth = params[0]; + events[ID_ORIENTATION].orientation.pitch = params[1]; + events[ID_ORIENTATION].orientation.roll = params[2]; + events[ID_ORIENTATION].orientation.status = + SENSOR_STATUS_ACCURACY_HIGH; + events[ID_ORIENTATION].type = SENSOR_TYPE_ORIENTATION; + continue; + } + + /* "magnetic:::" is sent for the params of the magnetic + * field */ + if (sscanf(buff, "magnetic:%g:%g:%g", params+0, params+1, params+2) + == 3) { + new_sensors |= SENSORS_MAGNETIC_FIELD; + events[ID_MAGNETIC_FIELD].magnetic.x = params[0]; + events[ID_MAGNETIC_FIELD].magnetic.y = params[1]; + events[ID_MAGNETIC_FIELD].magnetic.z = params[2]; + events[ID_MAGNETIC_FIELD].magnetic.status = + SENSOR_STATUS_ACCURACY_HIGH; + events[ID_MAGNETIC_FIELD].type = SENSOR_TYPE_MAGNETIC_FIELD; + continue; + } + + /* "temperature:" */ + if (sscanf(buff, "temperature:%g", params+0) == 1) { + new_sensors |= SENSORS_TEMPERATURE; + events[ID_TEMPERATURE].temperature = params[0]; + events[ID_TEMPERATURE].type = SENSOR_TYPE_TEMPERATURE; + continue; + } + + /* "proximity:" */ + if (sscanf(buff, "proximity:%g", params+0) == 1) { + new_sensors |= SENSORS_PROXIMITY; + events[ID_PROXIMITY].distance = params[0]; + events[ID_PROXIMITY].type = SENSOR_TYPE_PROXIMITY; + continue; + } + /* "light:" */ + if (sscanf(buff, "light:%g", params+0) == 1) { + new_sensors |= SENSORS_LIGHT; + events[ID_LIGHT].light = params[0]; + events[ID_LIGHT].type = SENSOR_TYPE_LIGHT; + continue; + } + + /* "pressure:" */ + if (sscanf(buff, "pressure:%g", params+0) == 1) { + new_sensors |= SENSORS_PRESSURE; + events[ID_PRESSURE].pressure = params[0]; + events[ID_PRESSURE].type = SENSOR_TYPE_PRESSURE; + continue; + } + + /* "humidity:" */ + if (sscanf(buff, "humidity:%g", params+0) == 1) { + new_sensors |= SENSORS_HUMIDITY; + events[ID_HUMIDITY].relative_humidity = params[0]; + events[ID_HUMIDITY].type = SENSOR_TYPE_RELATIVE_HUMIDITY; + continue; + } + + /* "sync: