示例#1
0
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;
}
示例#8
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;
}
示例#9
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)

        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;
}
示例#10
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;
}