From d0cd4f3fd6a6c146e5e9779dad602a6f765b6cc8 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 20 Oct 2013 11:53:57 +0200 Subject: [PATCH] android: Make HAL library wait for daemon to connect on init After starting up, daemon is responsible for connecting to HAL library. If this doesn't happen before timeout occured init will fail. --- android/hal-bluetooth.c | 126 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 103 insertions(+), 23 deletions(-) diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c index 2c6c2eb2e..4667f9aa1 100644 --- a/android/hal-bluetooth.c +++ b/android/hal-bluetooth.c @@ -19,6 +19,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -31,41 +35,118 @@ #include #include "hal.h" +#include "hal-msg.h" #define SERVICE_NAME "bluetoothd" +#define CONNECT_TIMEOUT (5 * 1000) bt_callbacks_t *bt_hal_cbacks = NULL; +static int cmd_sk = -1; +static int notif_sk = -1; + static bool interface_ready(void) { return bt_hal_cbacks != NULL; } -static bool start_bt_daemon(void) +static int accept_connection(int sk) { - int tries = 40; /* wait 4 seconds for completion */ + int err; + struct pollfd pfd; + int new_sk; + + memset(&pfd, 0 , sizeof(pfd)); + pfd.fd = sk; + pfd.events = POLLIN; + + err = poll(&pfd, 1, CONNECT_TIMEOUT); + if (err < 0) { + err = errno; + ALOGE("Failed to poll: %d (%s)", err, strerror(err)); + return -1; + } - ALOGD(__func__); + if (err == 0) { + ALOGE("bluetoothd connect timeout"); + return -1; + } + + new_sk = accept(sk, NULL, NULL); + if (new_sk < 0) { + err = errno; + ALOGE("Failed to accept socket: %d (%s)", err, strerror(err)); + return -1; + } + + return new_sk; +} + +static bool start_daemon(void) +{ + struct sockaddr_un addr; + int sk; + int err; + + sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0); + if (sk < 0) { + err = errno; + ALOGE("Failed to create socket: %d (%s)", err, + strerror(err)); + return false; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + + memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH)); + + if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + err = errno; + ALOGE("Failed to bind socket: %d (%s)", err, strerror(err)); + close(sk); + return false; + } + + if (listen(sk, 2) < 0) { + err = errno; + ALOGE("Failed to listen on socket: %d (%s)", err, + strerror(err)); + close(sk); + return false; + } /* Start Android Bluetooth daemon service */ property_set("ctl.start", SERVICE_NAME); - while (tries-- > 0) { - char val[PROPERTY_VALUE_MAX]; - - if (property_get("init.svc." SERVICE_NAME, val, NULL)) { - if (!strcmp(val, "running")) { - ALOGI("Android BlueZ daemon started"); - return true; - } - } else { - return false; - } + cmd_sk = accept_connection(sk); + if (cmd_sk < 0) { + close(sk); + return false; + } - usleep(100000); + notif_sk = accept_connection(sk); + if (notif_sk < 0) { + close(sk); + close(cmd_sk); + cmd_sk = -1; + return false; } - return false; + ALOGI("bluetoothd connected"); + + close(sk); + + return true; +} + +static void stop_daemon(void) +{ + close(cmd_sk); + cmd_sk = -1; + + close(notif_sk); + notif_sk = -1; } static int init(bt_callbacks_t *callbacks) @@ -75,15 +156,12 @@ static int init(bt_callbacks_t *callbacks) if (interface_ready()) return BT_STATUS_SUCCESS; - if (start_bt_daemon()) { - /* TODO: open channel */ + if (!start_daemon()) + return BT_STATUS_FAIL; - bt_hal_cbacks = callbacks; + bt_hal_cbacks = callbacks; - return BT_STATUS_SUCCESS; - } - - return BT_STATUS_UNSUPPORTED; + return BT_STATUS_SUCCESS; } static int enable(void) @@ -110,6 +188,8 @@ static void cleanup(void) if (!interface_ready()) return; + stop_daemon(); + bt_hal_cbacks = NULL; } -- 2.11.0