* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.