diff --git a/android/ipc-tester.c b/android/ipc-tester.c index 021919eb3..c8d1f0bbb 100644 --- a/android/ipc-tester.c +++ b/android/ipc-tester.c @@ -21,8 +21,14 @@ * */ +#include #include +#include +#include +#include +#include +#include #include #include "lib/bluetooth.h" @@ -33,13 +39,19 @@ #include "src/shared/hciemu.h" +#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */ +#define EMULATOR_SIGNAL "emulator_started" + struct test_data { struct mgmt *mgmt; uint16_t mgmt_index; struct hciemu *hciemu; enum hciemu_type hciemu_type; + pid_t bluetoothd_pid; }; +static char exec_dir[PATH_MAX + 1]; + static void read_info_callback(uint8_t status, uint16_t length, const void *param, void *user_data) { @@ -170,14 +182,123 @@ static void test_post_teardown(const void *data) } } +static void bluetoothd_start(int hci_index) +{ + char prg_name[PATH_MAX + 1]; + char index[8]; + char *prg_argv[4]; + + snprintf(prg_name, sizeof(prg_name), "%s/%s", exec_dir, "bluetoothd"); + snprintf(index, sizeof(index), "%d", hci_index); + + prg_argv[0] = prg_name; + prg_argv[1] = "-i"; + prg_argv[2] = index; + prg_argv[3] = NULL; + + if (!tester_use_debug()) + fclose(stderr); + + execve(prg_argv[0], prg_argv, NULL); +} + +static void emulator(int pipe, int hci_index) +{ + static const char SYSTEM_SOCKET_PATH[] = "\0android_system"; + char buf[1024]; + struct sockaddr_un addr; + struct timeval tv; + int fd; + ssize_t len; + + fd = socket(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (fd < 0) + goto failed; + + tv.tv_sec = WAIT_FOR_SIGNAL_TIME; + tv.tv_usec = 0; + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, SYSTEM_SOCKET_PATH, sizeof(SYSTEM_SOCKET_PATH)); + + if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + perror("Failed to bind system socket"); + goto failed; + } + + len = write(pipe, EMULATOR_SIGNAL, sizeof(EMULATOR_SIGNAL)); + + if (len != sizeof(EMULATOR_SIGNAL)) + goto failed; + + memset(buf, 0, sizeof(buf)); + + len = read(fd, buf, sizeof(buf)); + if (len <= 0 || (strcmp(buf, "ctl.start=bluetoothd"))) + goto failed; + + close(pipe); + close(fd); + bluetoothd_start(hci_index); + +failed: + close(pipe); + close(fd); +} + static void setup(const void *data) { + struct test_data *test_data = tester_get_data(); + int signal_fd[2]; + char buf[1024]; + pid_t pid; + int len; + + if (pipe(signal_fd)) + goto failed; + + pid = fork(); + + if (pid < 0) { + close(signal_fd[0]); + close(signal_fd[1]); + goto failed; + } + + if (pid == 0) { + if (!tester_use_debug()) + fclose(stderr); + + close(signal_fd[0]); + emulator(signal_fd[1], test_data->mgmt_index); + exit(0); + } + + close(signal_fd[1]); + test_data->bluetoothd_pid = pid; + + len = read(signal_fd[0], buf, sizeof(buf)); + if (len <= 0 || (strcmp(buf, EMULATOR_SIGNAL))) { + close(signal_fd[0]); + goto failed; + } + + return; + +failed: tester_setup_failed(); test_post_teardown(data); } static void teardown(const void *data) { + struct test_data *test_data = tester_get_data(); + + if (test_data->bluetoothd_pid) + waitpid(test_data->bluetoothd_pid, NULL, 0); + tester_teardown_complete(); } @@ -199,6 +320,8 @@ static void ipc_send_tc(const void *data) int main(int argc, char *argv[]) { + snprintf(exec_dir, sizeof(exec_dir), "%s", dirname(argv[0])); + tester_init(&argc, &argv); test_generic("Test Dummy", NULL, setup, ipc_send_tc, teardown);