static void gps_state_init( GpsState* state ) { state->init = 1; state->control[0] = -1; state->control[1] = -1; state->fd = -1; state->fd = qemud_channel_open(QEMU_CHANNEL_NAME); if (state->fd < 0) { D("no gps emulation detected"); return; } D("gps emulation will read from '%s' qemud channel", QEMU_CHANNEL_NAME ); if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) { LOGE("could not create thread control socket pair: %s", strerror(errno)); goto Fail; } if ( pthread_create( &state->thread, NULL, gps_state_thread, state ) != 0 ) { LOGE("could not create gps thread: %s", strerror(errno)); goto Fail; } D("gps state initialized"); return; Fail: gps_state_done( state ); }
/* 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; }
/* this must return a file descriptor that will be used to read * the sensors data (it is passed to data__data_open() below */ static native_handle_t* control__open_data_source(struct sensors_poll_device_t *dev) { SensorPoll* ctl = (void*)dev; native_handle_t* handle; if (ctl->fd < 0) { ctl->fd = qemud_channel_open(SENSORS_SERVICE_NAME); } D("%s: fd=%d", __FUNCTION__, ctl->fd); handle = native_handle_create(1, 0); handle->data[0] = dup(ctl->fd); return handle; }
static int control__activate(struct sensors_poll_device_t *dev, int handle, int enabled) { SensorPoll* ctl = (void*)dev; uint32_t mask, sensors, active, new_sensors, changed; char command[128]; int ret; D("%s: handle=%s (%d) fd=%d enabled=%d", __FUNCTION__, _sensorIdToName(handle), handle, ctl->fd, enabled); if (!ID_CHECK(handle)) { E("%s: bad handle ID", __FUNCTION__); return -1; } mask = (1<<handle); sensors = enabled ? mask : 0; active = ctl->active_sensors; new_sensors = (active & ~mask) | (sensors & mask); changed = active ^ new_sensors; if (!changed) return 0; snprintf(command, sizeof command, "set:%s:%d", _sensorIdToName(handle), enabled != 0); if (ctl->fd < 0) { ctl->fd = qemud_channel_open(SENSORS_SERVICE_NAME); } ret = qemud_channel_send(ctl->fd, command, -1); if (ret < 0) { E("%s: when sending command errno=%d: %s", __FUNCTION__, errno, strerror(errno)); return -1; } ctl->active_sensors = new_sensors; return 0; }
static int sensors__get_sensors_list(struct sensors_module_t* module, struct sensor_t const** list) { int fd = qemud_channel_open(SENSORS_SERVICE_NAME); char buffer[12]; int mask, nn, count; int ret; if (fd < 0) { E("%s: no qemud connection", __FUNCTION__); return 0; } ret = qemud_channel_send(fd, "list-sensors", -1); if (ret < 0) { E("%s: could not query sensor list: %s", __FUNCTION__, strerror(errno)); close(fd); return 0; } ret = qemud_channel_recv(fd, buffer, sizeof buffer-1); if (ret < 0) { E("%s: could not receive sensor list: %s", __FUNCTION__, strerror(errno)); close(fd); return 0; } buffer[ret] = 0; close(fd); /* the result is a integer used as a mask for available sensors */ mask = atoi(buffer); count = 0; for (nn = 0; nn < MAX_NUM_SENSORS; nn++) { if (((1 << nn) & mask) == 0) continue; sSensorList[count++] = sSensorListInit[nn]; } D("%s: returned %d sensors (mask=%d)", __FUNCTION__, count, mask); *list = sSensorList; return count; }
.version = 1, .handle = ID_PROXIMITY, .type = SENSOR_TYPE_PROXIMITY, .maxRange = 1.0f, .resolution = 1.0f, .power = 20.0f, .reserved = {} }, }; static struct sensor_t sSensorList[MAX_NUM_SENSORS]; static int sensors__get_sensors_list(struct sensors_module_t* module __unused, struct sensor_t const** list) { int fd = qemud_channel_open(SENSORS_SERVICE_NAME); char buffer[12]; int mask, nn, count; int ret = 0; if (fd < 0) { E("%s: no qemud connection", __FUNCTION__); goto out; } ret = qemud_channel_send(fd, "list-sensors", -1); if (ret < 0) { E("%s: could not query sensor list: %s", __FUNCTION__, strerror(errno)); goto out; } ret = qemud_channel_recv(fd, buffer, sizeof buffer-1);
/** * This a very simple event loop for the fingerprint sensor. For a given state (enroll, scan), * this would receive events from the sensor and forward them to fingerprintd using the * notify() method. * * In this simple example, we open a qemu channel (a pipe) where the developer can inject events to * exercise the API and test application code. * * The scanner should remain in the scanning state until either an error occurs or the operation * completes. * * Recoverable errors such as EINTR should be handled locally; they should not * be propagated unless there's something the user can do about it (e.g. "clean sensor"). Such * messages should go through the onAcquired() interface. * * If an unrecoverable error occurs, an acquired message (e.g. ACQUIRED_PARTIAL) should be sent, * followed by an error message (e.g. FINGERPRINT_ERROR_UNABLE_TO_PROCESS). * * Note that this event loop would typically run in TEE since it must interact with the sensor * hardware and handle raw fingerprint data and encrypted templates. It is expected that * this code monitors the TEE for resulting events, such as enrollment and authentication status. * Here we just have a very simple event loop that monitors a qemu channel for pseudo events. */ static void* listenerFunction(void* data) { ALOGD("----------------> %s ----------------->", __FUNCTION__); qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)data; int fd = qemud_channel_open(FINGERPRINT_LISTEN_SERVICE_NAME); pthread_mutex_lock(&qdev->lock); qdev->qchanfd = fd; if (qdev->qchanfd < 0) { ALOGE("listener cannot open fingerprint listener service exit"); pthread_mutex_unlock(&qdev->lock); return NULL; } qdev->listener.state = STATE_IDLE; pthread_mutex_unlock(&qdev->lock); const char* cmd = "listen"; if (qemud_channel_send(qdev->qchanfd, cmd, strlen(cmd)) < 0) { ALOGE("cannot write fingerprint 'listen' to host"); goto done_quiet; } int comm_errors = 0; struct pollfd pfd = { .fd = qdev->qchanfd, .events = POLLIN, }; while (1) { int size = 0; int fid = 0; char buffer[MAX_COMM_CHARS] = {0}; bool disconnected = false; while (1) { if (getListenerState(qdev) == STATE_EXIT) { ALOGD("Received request to exit listener thread"); goto done; } // Reset revents before poll() (just to be safe) pfd.revents = 0; // Poll qemud channel for 5 seconds // TODO: Eliminate the timeout so that polling can be interrupted // instantly. One possible solution is to follow the example of // android::Looper ($AOSP/system/core/include/utils/Looper.h and // $AOSP/system/core/libutils/Looper.cpp), which makes use of an // additional file descriptor ("wake event fd"). int nfds = poll(&pfd, 1, 5000); if (nfds < 0) { ALOGE("Could not poll qemud channel: %s", strerror(errno)); goto done; } if (!nfds) { // poll() timed out - try again continue; } // assert(nfds == 1) if (pfd.revents & POLLIN) { // Input data being available doesn't rule out a disconnection disconnected = pfd.revents & (POLLERR | POLLHUP); break; // Exit inner while loop } else { // Some event(s) other than "input data available" occurred, // i.e. POLLERR or POLLHUP, indicating a disconnection ALOGW("Lost connection to qemud channel"); goto done; } } // Shouldn't block since we were just notified of a POLLIN event if ((size = qemud_channel_recv(qdev->qchanfd, buffer, sizeof(buffer) - 1)) > 0) { buffer[size] = '\0'; if (sscanf(buffer, "on:%d", &fid) == 1) { if (fid > 0 && fid <= MAX_FID_VALUE) { switch (qdev->listener.state) { case STATE_ENROLL: send_enroll_notice(qdev, fid); break; case STATE_SCAN: send_scan_notice(qdev, fid); break; default: ALOGE("fingerprint event listener at unexpected " "state 0%x", qdev->listener.state); } } else { ALOGE("fingerprintid %d not in valid range [%d, %d] and " "will be " "ignored", fid, 1, MAX_FID_VALUE); continue; } } else if (strncmp("off", buffer, 3) == 0) { // TODO: Nothing to do here ? Looks valid ALOGD("fingerprint ID %d off", fid); } else { ALOGE("Invalid command '%s' to fingerprint listener", buffer); } if (disconnected) { ALOGW("Connection to qemud channel has been lost"); break; } } else { ALOGE("fingerprint listener receive failure"); if (comm_errors > MAX_COMM_ERRORS) break; } } done: ALOGD("Listener exit with %d receive errors", comm_errors); done_quiet: close(qdev->qchanfd); return NULL; } static int fingerprint_close(hw_device_t* device) { ALOGD("----------------> %s ----------------->", __FUNCTION__); if (device == NULL) { ALOGE("fingerprint hw device is NULL"); return -1; } qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device; pthread_mutex_lock(&qdev->lock); // Ask listener thread to exit qdev->listener.state = STATE_EXIT; pthread_mutex_unlock(&qdev->lock); pthread_join(qdev->listener.thread, NULL); pthread_mutex_destroy(&qdev->lock); free(qdev); return 0; }
/* * Main sensor sim routine */ int main(int argc, char **argv) { int rc; int qfd; char command[128]; char ip[16]; int port; int ssock = -1; /* simulator socket */ int sensor_id = -1; (void)bionic_signal(SIGPIPE, sighandler); (void)bionic_signal(SIGKILL, sighandler); (void)bionic_signal(SIGQUIT, sighandler); qfd = qemud_channel_open(SENSORS_SERVICE_NAME); if (qfd < 0) { err("Can't get a connection to qemud!\n"); return EXIT_FAILURE; } /* list available / enabled sensors */ info("Emulator-enabled sensors:\n"); emu_sensors_list(qfd); /* if we're passed arguments, use them to connect to a sensorsimulator.java instance somewhere on the network */ if (argc > 2) { strncpy(ip, argv[1], sizeof(ip)); port = atoi(argv[2]); ssock = sensorsimulator_open_socket(ip, port); if (ssock < 0) { err("Error connecting to %s:%d (%s)", ip, port, strerror(errno)); goto exit_socket_failure; } if (argc > 3) sensor_id = atoi(argv[3]); else { /* ask the user for a sensor ID */ char line[64]; get_param("SensorID: ", line, "%d", &sensor_id); } if (!ID_CHECK(sensor_id)) { err("Invalid SensorID"); goto exit_data_error; } if (sensorsimulator_enable_sensor(ssock, sensor_id) < 0) { err("Error enabling SensorID=%d (%s)", sensor_id, strerror(errno)); goto exit_data_error; } daemonize(); } /* quick fix; enable orientation sensor */ qemud_channel_send(qfd, "set:orientation:1", -1); while (!s_should_exit) { float x, y, z; char *sensor_name; if (ssock > 0) { usleep(SENSOR_UPDATE_PERIOD_MS * 1000); if (sensorsimulator_get_params(ssock, sensor_id, &x, &y, &z) < 0) { err("Error receiving data from sensorsimulator" " (%s)", strerror(errno)); goto exit_data_error; } } else { if (get_parameters(&sensor_id, &x, &y, &z) < 0) { err("Error receiving parameters from cmdline"); continue; } if (!ID_CHECK(sensor_id)) { err("Invalid SensorID"); continue; } } sensor_name = (char *)sensorId_to_name(sensor_id); if (ssock < 0 && sensor_id == ID_ORIENTATION) { /* the user just input X,Y,Z (pitch,roll,azimuth) the qemu pipe is expecting Z,X,Y (azimuth,pitch,roll) */ float tmpX = x; float tmpY = y; x = z; y = tmpX; z = tmpY; } if (y > 180 || y < -180) { err("pitch out of range\n"); continue; } if (z > 90 || z < -90) { err("roll out of range\n"); continue; } if (x >= 360 || x < 0) { err("azimuth out of range\n"); continue; } snprintf(command, sizeof(command), "update-sensor:%d:%g:%g:%g:", sensor_id, x, y, z); dbg("simulating %s event: %s\n", sensor_name, command); rc = qemud_channel_send(qfd, command, -1); if (rc < 0) { err("Error sending emulator command: %s\n", strerror(errno)); sleep(2); /* let the user know there was a problem */ } } { char tbuf[32]; time_t tm = time(NULL); info("sensorsim exiting at %s\n", ctime_r(&tm, tbuf)); } close(ssock); close(qfd); return EXIT_SUCCESS; exit_data_error: close(ssock); exit_socket_failure: close(qfd); return EXIT_FAILURE; }
int main(void) { int qemud_fd, count = 0; /* try to connect to the qemud service */ { int tries = MAX_TRIES; while (1) { qemud_fd = qemud_channel_open( "boot-properties" ); if (qemud_fd >= 0) break; if (--tries <= 0) { DD("Could not connect after too many tries. Aborting"); return 1; } DD("waiting 1s to wait for qemud."); sleep(1); } } DD("connected to '%s' qemud service.", QEMUD_SERVICE); /* send the 'list' command to the service */ if (qemud_channel_send(qemud_fd, "list", -1) < 0) { DD("could not send command to '%s' service", QEMUD_SERVICE); return 1; } /* read each system property as a single line from the service, * until exhaustion. */ for (;;) { #define BUFF_SIZE (PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 2) char* q; char temp[BUFF_SIZE]; int len = qemud_channel_recv(qemud_fd, temp, sizeof temp - 1); if (len < 0 || len > BUFF_SIZE-1) break; temp[len] = '\0'; /* zero-terminate string */ DD("received: %.*s", len, temp); /* separate propery name from value */ q = strchr(temp, '='); if (q == NULL) { DD("invalid format, ignored."); continue; } *q++ = '\0'; if (property_set(temp, q) < 0) { DD("could not set property '%s' to '%s'", temp, q); } else { count += 1; } } /* finally, close the channel and exit */ close(qemud_fd); DD("exiting (%d properties set).", count); return 0; }
int main(void) { int qemud_fd, count = 0; /* try to connect to the qemud service */ { int tries = MAX_TRIES; while (1) { qemud_fd = qemud_channel_open( "boot-properties" ); if (qemud_fd >= 0) break; if (--tries <= 0) { DD("Could not connect after too many tries. Aborting"); return 1; } DD("waiting 1s to wait for qemud."); sleep(1); } } DD("connected to '%s' qemud service.", QEMUD_SERVICE); /* send the 'list' command to the service */ if (qemud_channel_send(qemud_fd, "list", -1) < 0) { DD("could not send command to '%s' service", QEMUD_SERVICE); return 1; } /* read each system property as a single line from the service, * until exhaustion. */ for (;;) { #define BUFF_SIZE (PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 2) DD("receiving.."); char* q; char temp[BUFF_SIZE]; int len = qemud_channel_recv(qemud_fd, temp, sizeof temp - 1); /* lone NUL-byte signals end of properties */ if (len < 0 || len > BUFF_SIZE-1 || temp[0] == '\0') break; temp[len] = '\0'; /* zero-terminate string */ DD("received: %.*s", len, temp); /* separate propery name from value */ q = strchr(temp, '='); if (q == NULL) { DD("invalid format, ignored."); continue; } *q++ = '\0'; if (property_set(temp, q) < 0) { DD("could not set property '%s' to '%s'", temp, q); } else { count += 1; } } char temp[BUFF_SIZE]; for (;;) { usleep(5000000); /* 5 seconds */ property_get("sys.boot_completed", temp, ""); int is_boot_completed = (strncmp(temp, "1", 1) == 0) ? 1 : 0; if (is_boot_completed) { notifyHostBootComplete(); break; } } /* HACK start adbd periodically every minute, if adbd is already running, this is a no-op */ for(;;) { usleep(60000000); /* 1 minute */ property_set("qemu.adbd", "start"); } /* finally, close the channel and exit */ if (s_QemuMiscPipe >= 0) { close(s_QemuMiscPipe); s_QemuMiscPipe = -1; } close(qemud_fd); DD("exiting (%d properties set).", count); return 0; }