* [PATCH 0/5] Initial Android IPC
@ 2013-10-18 23:01 Szymon Janc
2013-10-18 23:01 ` [PATCH 1/5] android: Fix cutils/log.h stubs Szymon Janc
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Szymon Janc @ 2013-10-18 23:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Hi,
This adds initial code for Android IPC
- only connection establishment
- connecting ipc from daemon to HAL after adapter is initialized
- daemon track HAL lib lifetime and shutdown if socket is closed
- HAL library starts daemon (via android init) and wait for it to
connect
- HAL library is *not* yet tracking lifetime of daemon
--
BR
Szymon Janc
Szymon Janc (5):
android: Fix cutils/log.h stubs
android: Define path for HAL communication socket
android: Connect daemon to HAL library
android: Make HAL library wait for daemon to connect on init
android: Remove not needed property_get function form cutils stubs
android/cutils/log.h | 12 ++--
android/cutils/properties.h | 27 ---------
android/hal-bluetooth.c | 127 ++++++++++++++++++++++++++++++++++--------
android/hal-msg.h | 2 +
android/main.c | 133 ++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 246 insertions(+), 55 deletions(-)
--
1.8.4.rc3
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/5] android: Fix cutils/log.h stubs
2013-10-18 23:01 [PATCH 0/5] Initial Android IPC Szymon Janc
@ 2013-10-18 23:01 ` Szymon Janc
2013-10-18 23:01 ` [PATCH 2/5] android: Define path for HAL communication socket Szymon Janc
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Szymon Janc @ 2013-10-18 23:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@tieto.com>
Provide dummy functions that will use macro parameters. This fix
build errors about set-but-not-used used local variables on linux.
---
android/cutils/log.h | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/android/cutils/log.h b/android/cutils/log.h
index d87da72..7374add 100644
--- a/android/cutils/log.h
+++ b/android/cutils/log.h
@@ -17,11 +17,13 @@
#ifndef _CUTILS_LOG_H
#define _CUTILS_LOG_H
-#define ALOGV(...)
-#define ALOGD(...)
-#define ALOGI(...)
-#define ALOGW(...)
-#define ALOGE(...)
+static inline void dummy_printf(const char *fmt, ...) { }
+
+#define ALOGV(...) dummy_printf("", __VA_ARGS__)
+#define ALOGD(...) dummy_printf("", __VA_ARGS__)
+#define ALOGI(...) dummy_printf("", __VA_ARGS__)
+#define ALOGW(...) dummy_printf("", __VA_ARGS__)
+#define ALOGE(...) dummy_printf("", __VA_ARGS__)
#define LOG_ALWAYS_FATAL(...) do { ALOGE(__VA_ARGS__); exit(1); } while (0)
#endif // _CUTILS_LOG_H
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/5] android: Define path for HAL communication socket
2013-10-18 23:01 [PATCH 0/5] Initial Android IPC Szymon Janc
2013-10-18 23:01 ` [PATCH 1/5] android: Fix cutils/log.h stubs Szymon Janc
@ 2013-10-18 23:01 ` Szymon Janc
2013-10-18 23:01 ` [PATCH 3/5] android: Connect daemon to HAL library Szymon Janc
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Szymon Janc @ 2013-10-18 23:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@tieto.com>
This socket will be used by android daemon and libhal to communitate.
---
android/hal-msg.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 4c5ca69..2da5e16 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -21,6 +21,8 @@
*
*/
+#define BLUEZ_HAL_SK_PATH "bluez_hal_socket"
+
struct hal_msg_hdr {
uint8_t service_id;
uint8_t opcode;
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/5] android: Connect daemon to HAL library
2013-10-18 23:01 [PATCH 0/5] Initial Android IPC Szymon Janc
2013-10-18 23:01 ` [PATCH 1/5] android: Fix cutils/log.h stubs Szymon Janc
2013-10-18 23:01 ` [PATCH 2/5] android: Define path for HAL communication socket Szymon Janc
@ 2013-10-18 23:01 ` Szymon Janc
2013-10-18 23:01 ` [PATCH 4/5] android: Make HAL library wait for daemon to connect on init Szymon Janc
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Szymon Janc @ 2013-10-18 23:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@tieto.com>
Connect to HAL when adapter initialization is finished. If any problem
with connection occurs or connected socket is closed by remote daemon
shutdowns.
---
android/main.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 133 insertions(+)
diff --git a/android/main.c b/android/main.c
index c3fb80e..5b71265 100644
--- a/android/main.c
+++ b/android/main.c
@@ -32,7 +32,10 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
+#include <errno.h>
#include <sys/signalfd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <glib.h>
@@ -44,6 +47,7 @@
#include "src/shared/mgmt.h"
#include "adapter.h"
+#include "hal-msg.h"
#define SHUTDOWN_GRACE_SECONDS 10
@@ -55,8 +59,135 @@ static uint8_t mgmt_revision = 0;
static uint16_t adapter_index = MGMT_INDEX_NONE;
+static GIOChannel *hal_cmd_io = NULL;
+static GIOChannel *hal_notif_io = NULL;
+
static volatile sig_atomic_t __terminated = 0;
+static gboolean watch_cb(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ info("HAL socket closed, terminating");
+ g_main_loop_quit(event_loop);
+
+ return FALSE;
+}
+
+static GIOChannel *create_io(void)
+{
+ int sk;
+ int err;
+ GIOChannel *io;
+
+ sk = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
+ if (sk < 0) {
+ err = errno;
+ error("Failed to create socket: %d (%s)", err, strerror(err));
+ return NULL;
+ }
+
+ io = g_io_channel_unix_new(sk);
+
+ g_io_channel_set_close_on_unref(io, TRUE);
+ g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
+
+ return io;
+}
+
+static int connect_io(GIOChannel *io, GIOFunc connect_cb)
+{
+ int err;
+ struct sockaddr_un addr;
+ GIOCondition cond;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+
+ /* Use abstract sockets so first byte needs to be \0 */
+ strcpy(addr.sun_path + 1, BLUEZ_HAL_SK_PATH);
+
+ err = connect(g_io_channel_unix_get_fd(io),
+ (struct sockaddr *) &addr, sizeof(addr));
+ if (err < 0) {
+ err = -errno;
+ error("Failed to connect HAL socket: %d (%s)", -err,
+ strerror(-err));
+ return err;
+ }
+
+ cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+
+ g_io_add_watch(io, cond, connect_cb, NULL);
+
+ return 0;
+}
+
+static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ DBG("");
+
+ if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+ g_main_loop_quit(event_loop);
+ return FALSE;
+ }
+
+ cond = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+
+ g_io_add_watch(io, cond, watch_cb, NULL);
+
+ info("Successfully connected to HAL");
+
+ /* TODO start handling commands */
+
+ return FALSE;
+}
+
+static void connect_notification_socket(void)
+{
+ DBG("");
+
+ hal_notif_io = create_io();
+
+ if (hal_notif_io && connect_io(hal_notif_io, notif_connect_cb) == 0)
+ return;
+
+ error("Cannot connect to HAL, terminating");
+ g_main_loop_quit(event_loop);
+}
+
+static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ DBG("");
+
+ if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+ g_main_loop_quit(event_loop);
+ return FALSE;
+ }
+
+ cond = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+
+ g_io_add_watch(io, cond, watch_cb, NULL);
+
+ connect_notification_socket();
+
+ return FALSE;
+}
+
+static void connect_cmd_socket(void)
+{
+ DBG("");
+
+ hal_cmd_io = create_io();
+
+ if (hal_cmd_io && connect_io(hal_cmd_io, cmd_connect_cb) == 0)
+ return;
+
+ error("Cannot connect to HAL, terminating");
+ g_main_loop_quit(event_loop);
+}
+
static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
gpointer user_data)
{
@@ -141,6 +272,8 @@ static void adapter_ready(struct bt_adapter *adapter, int err)
}
info("Adapter initialized");
+
+ connect_cmd_socket();
}
static void mgmt_index_added_event(uint16_t index, uint16_t length,
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/5] android: Make HAL library wait for daemon to connect on init
2013-10-18 23:01 [PATCH 0/5] Initial Android IPC Szymon Janc
` (2 preceding siblings ...)
2013-10-18 23:01 ` [PATCH 3/5] android: Connect daemon to HAL library Szymon Janc
@ 2013-10-18 23:01 ` Szymon Janc
2013-10-18 23:01 ` [PATCH 5/5] android: Remove not needed property_get function form cutils stubs Szymon Janc
2013-10-19 13:28 ` [PATCH 0/5] Initial Android IPC Szymon Janc
5 siblings, 0 replies; 7+ messages in thread
From: Szymon Janc @ 2013-10-18 23:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@tieto.com>
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 | 127 +++++++++++++++++++++++++++++++++++++++---------
1 file changed, 104 insertions(+), 23 deletions(-)
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 2c6c2eb..c91bc98 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -19,6 +19,10 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <poll.h>
#include <hardware/bluetooth.h>
#include <hardware/bt_sock.h>
@@ -31,41 +35,119 @@
#include <cutils/log.h>
#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;
+
+ /* Use abstract sockets so first byte needs to be \0 */
+ strcpy(addr.sun_path + 1, 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 +157,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 +189,8 @@ static void cleanup(void)
if (!interface_ready())
return;
+ stop_daemon();
+
bt_hal_cbacks = NULL;
}
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/5] android: Remove not needed property_get function form cutils stubs
2013-10-18 23:01 [PATCH 0/5] Initial Android IPC Szymon Janc
` (3 preceding siblings ...)
2013-10-18 23:01 ` [PATCH 4/5] android: Make HAL library wait for daemon to connect on init Szymon Janc
@ 2013-10-18 23:01 ` Szymon Janc
2013-10-19 13:28 ` [PATCH 0/5] Initial Android IPC Szymon Janc
5 siblings, 0 replies; 7+ messages in thread
From: Szymon Janc @ 2013-10-18 23:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
From: Szymon Janc <szymon.janc@tieto.com>
This is no longer used as daemon indicates its presence by connecting
socket.
---
android/cutils/properties.h | 27 ---------------------------
1 file changed, 27 deletions(-)
diff --git a/android/cutils/properties.h b/android/cutils/properties.h
index 44a712c..f318b01 100644
--- a/android/cutils/properties.h
+++ b/android/cutils/properties.h
@@ -24,33 +24,6 @@
extern "C" {
#endif
-#define PROPERTY_KEY_MAX 32
-#define PROPERTY_VALUE_MAX 92
-
-/* property_get: returns the length of the value which will never be
-** greater than PROPERTY_VALUE_MAX - 1 and will always be zero terminated.
-** (the length does not include the terminating zero).
-**
-** If the property read fails or returns an empty value, the default
-** value is used (if nonnull).
-*/
-static inline int property_get(const char *key, char *value,
- const char *default_value)
-{
- const char *env;
-
- env = getenv(key);
- if (!env)
- env = default_value;
-
- if (!value || !env)
- return 0;
-
- strncpy(value, env, PROPERTY_VALUE_MAX);
-
- return strlen(value);
-}
-
/* property_set: returns 0 on success, < 0 on failure
*/
static inline int property_set(const char *key, const char *value)
--
1.8.4.rc3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 0/5] Initial Android IPC
2013-10-18 23:01 [PATCH 0/5] Initial Android IPC Szymon Janc
` (4 preceding siblings ...)
2013-10-18 23:01 ` [PATCH 5/5] android: Remove not needed property_get function form cutils stubs Szymon Janc
@ 2013-10-19 13:28 ` Szymon Janc
5 siblings, 0 replies; 7+ messages in thread
From: Szymon Janc @ 2013-10-19 13:28 UTC (permalink / raw)
To: linux-bluetooth
> This adds initial code for Android IPC
> - only connection establishment
> - connecting ipc from daemon to HAL after adapter is initialized
> - daemon track HAL lib lifetime and shutdown if socket is closed
> - HAL library starts daemon (via android init) and wait for it to
> connect
> - HAL library is *not* yet tracking lifetime of daemon
One more note I forgot to mention: this is not yet runtime tested on Android.
(build was verified though)
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2013-10-19 13:28 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-18 23:01 [PATCH 0/5] Initial Android IPC Szymon Janc
2013-10-18 23:01 ` [PATCH 1/5] android: Fix cutils/log.h stubs Szymon Janc
2013-10-18 23:01 ` [PATCH 2/5] android: Define path for HAL communication socket Szymon Janc
2013-10-18 23:01 ` [PATCH 3/5] android: Connect daemon to HAL library Szymon Janc
2013-10-18 23:01 ` [PATCH 4/5] android: Make HAL library wait for daemon to connect on init Szymon Janc
2013-10-18 23:01 ` [PATCH 5/5] android: Remove not needed property_get function form cutils stubs Szymon Janc
2013-10-19 13:28 ` [PATCH 0/5] Initial Android IPC Szymon Janc
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox