All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] android/tester: Init profiles in separate thread
@ 2014-09-05  8:09 Marcin Kraglak
  2014-09-05  8:09 ` [PATCH 2/3] android/tester: Set ssp_request_cb to default value in teardown Marcin Kraglak
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-09-05  8:09 UTC (permalink / raw)
  To: linux-bluetooth

This is needed to not block mainloop while initializing stack.
In some cases, bluetooth->init blocks mainloop and bluetoothd
cannot properly initialize controller, because HCI frames are
not serviced in hciemu.
Because pthread_join() is blocking, it is added to mainloop
from thread right before pthread_exit() is called. Therefore
this time is extremely short.
---
 android/tester-main.c | 230 +++++++++++++++++++++++++++-----------------------
 android/tester-main.h |   2 +
 2 files changed, 127 insertions(+), 105 deletions(-)

diff --git a/android/tester-main.c b/android/tester-main.c
index f5f46fb..ce13bf7 100644
--- a/android/tester-main.c
+++ b/android/tester-main.c
@@ -15,8 +15,10 @@
  *
  */
 #include <stdbool.h>
+#include <pthread.h>
 
 #include "emulator/bthost.h"
+#include "src/shared/util.h"
 #include "tester-main.h"
 
 #include "monitor/bt.h"
@@ -1332,237 +1334,255 @@ static bool setup_base(struct test_data *data)
 	return true;
 }
 
-static void setup(const void *test_data)
+static int init_bluetooth(void)
 {
 	struct test_data *data = tester_get_data();
-	bt_status_t status;
-
-	if (!setup_base(data)) {
-		tester_setup_failed();
-		return;
-	}
-
-	status = data->if_bluetooth->init(&bt_callbacks);
-	if (status != BT_STATUS_SUCCESS) {
-		data->if_bluetooth = NULL;
-		tester_setup_failed();
-		return;
-	}
 
-	tester_setup_complete();
+	return data->if_bluetooth->init(&bt_callbacks);
 }
 
-static void setup_socket(const void *test_data)
+static int init_socket(void)
 {
 	struct test_data *data = tester_get_data();
-	bt_status_t status;
 	const void *sock;
-
-	if (!setup_base(data)) {
-		tester_setup_failed();
-		return;
-	}
+	int status;
 
 	status = data->if_bluetooth->init(&bt_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
 		data->if_bluetooth = NULL;
-		tester_setup_failed();
-		return;
+		return status;
 	}
 
 	sock = data->if_bluetooth->get_profile_interface(BT_PROFILE_SOCKETS_ID);
-	if (!sock) {
-		tester_setup_failed();
-		return;
-	}
+	if (!sock)
+		return BT_STATUS_FAIL;
 
 	data->if_sock = sock;
 
-	tester_setup_complete();
+	return BT_STATUS_SUCCESS;
 }
 
-static void setup_hidhost(const void *test_data)
+static int init_hidhost(void)
 {
 	struct test_data *data = tester_get_data();
 	bt_status_t status;
 	const void *hid;
 
-	if (!setup_base(data)) {
-		tester_setup_failed();
-		return;
-	}
-
 	status = data->if_bluetooth->init(&bt_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
 		data->if_bluetooth = NULL;
 		tester_setup_failed();
-		return;
+		return status;
 	}
 
 	hid = data->if_bluetooth->get_profile_interface(BT_PROFILE_HIDHOST_ID);
 	if (!hid) {
 		tester_setup_failed();
-		return;
+		return BT_STATUS_FAIL;
 	}
 
 	data->if_hid = hid;
 
 	status = data->if_hid->init(&bthh_callbacks);
-	if (status != BT_STATUS_SUCCESS) {
+	if (status != BT_STATUS_SUCCESS)
 		data->if_hid = NULL;
-		tester_setup_failed();
-		return;
-	}
 
-	tester_setup_complete();
+	return status;
 }
 
-static void setup_pan(const void *test_data)
+static int init_pan(void)
 {
 	struct test_data *data = tester_get_data();
 	bt_status_t status;
 	const void *pan;
 
-	if (!setup_base(data)) {
-		tester_setup_failed();
-		return;
-	}
-
 	status = data->if_bluetooth->init(&bt_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
 		data->if_bluetooth = NULL;
-		tester_setup_failed();
-		return;
+		return status;
 	}
 
 	pan = data->if_bluetooth->get_profile_interface(BT_PROFILE_PAN_ID);
 	if (!pan) {
-		tester_setup_failed();
-		return;
+		return BT_STATUS_FAIL;
 	}
 
 	data->if_pan = pan;
 
 	status = data->if_pan->init(&btpan_callbacks);
-	if (status != BT_STATUS_SUCCESS) {
+	if (status != BT_STATUS_SUCCESS)
 		data->if_pan = NULL;
-		tester_setup_failed();
-		return;
-	}
 
-	tester_setup_complete();
+	return status;
 }
 
-static void setup_hdp(const void *test_data)
+static int init_hdp(void)
 {
 	struct test_data *data = tester_get_data();
 	bt_status_t status;
 	const void *hdp;
 
-	if (!setup_base(data)) {
-		tester_setup_failed();
-		return;
-	}
-
 	status = data->if_bluetooth->init(&bt_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
 		data->if_bluetooth = NULL;
-		tester_setup_failed();
-		return;
+		return status;
 	}
 
 	hdp = data->if_bluetooth->get_profile_interface(BT_PROFILE_HEALTH_ID);
-	if (!hdp) {
-		tester_setup_failed();
-		return;
-	}
+	if (!hdp)
+		return BT_STATUS_FAIL;
 
 	data->if_hdp = hdp;
 
 	status = data->if_hdp->init(&bthl_callbacks);
-	if (status != BT_STATUS_SUCCESS) {
+	if (status != BT_STATUS_SUCCESS)
 		data->if_hdp = NULL;
-		tester_setup_failed();
-		return;
-	}
 
-	tester_setup_complete();
+	return status;
 }
 
-static void setup_a2dp(const void *test_data)
+static int init_a2dp(void)
 {
 	struct test_data *data = tester_get_data();
 	const bt_interface_t *if_bt;
 	bt_status_t status;
 	const void *a2dp;
 
-	if (!setup_base(data)) {
-		tester_setup_failed();
-		return;
-	}
-
 	if_bt = data->if_bluetooth;
 
 	status = if_bt->init(&bt_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
 		data->if_bluetooth = NULL;
-		tester_setup_failed();
-		return;
+		return status;
 	}
 
 	a2dp = if_bt->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID);
-	if (!a2dp) {
-		tester_setup_failed();
-		return;
-	}
+	if (!a2dp)
+		return  BT_STATUS_FAIL;
 
 	data->if_a2dp = a2dp;
 
 	status = data->if_a2dp->init(&bta2dp_callbacks);
-	if (status != BT_STATUS_SUCCESS) {
+	if (status != BT_STATUS_SUCCESS)
 		data->if_a2dp = NULL;
-		tester_setup_failed();
-		return;
-	}
 
-	tester_setup_complete();
+	return status;
 }
 
-static void setup_gatt(const void *test_data)
+static int init_gatt(void)
 {
 	struct test_data *data = tester_get_data();
 	bt_status_t status;
 	const void *gatt;
 
-	if (!setup_base(data)) {
-		tester_setup_failed();
-		return;
-	}
-
 	status = data->if_bluetooth->init(&bt_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
 		data->if_bluetooth = NULL;
-		tester_setup_failed();
-		return;
+		return status;
 	}
 
 	gatt = data->if_bluetooth->get_profile_interface(BT_PROFILE_GATT_ID);
-	if (!gatt) {
-		tester_setup_failed();
-		return;
-	}
+	if (!gatt)
+		return BT_STATUS_FAIL;
 
 	data->if_gatt = gatt;
 
 	status = data->if_gatt->init(&btgatt_callbacks);
-	if (status != BT_STATUS_SUCCESS) {
+	if (status != BT_STATUS_SUCCESS)
 		data->if_gatt = NULL;
 
+	return status;
+}
+
+static gboolean join_init_thread(gpointer user_data)
+{
+	struct test_data *data = tester_get_data();
+	int status;
+
+	/* Note that pthread_join is blocking mainloop,
+	 * therefore thread we want to join must
+	 * exit imediatelly. This is done in init_thread()*/
+	status = pthread_join(data->thread, NULL);
+	if (status != 0)
+		tester_warn("Failed to join init thread, status %d", status);
+
+	if (PTR_TO_INT(user_data) == BT_STATUS_SUCCESS)
+		tester_setup_complete();
+	else
+		tester_setup_failed();
+
+	return FALSE;
+}
+
+static void *init_thread(void *user_data)
+{
+	int (*setup_func)(void) = user_data;
+	int status;
+
+	status = setup_func();
+
+	g_idle_add(join_init_thread, INT_TO_PTR(status));
+
+	pthread_exit(NULL);
+}
+
+static bool start_init_thread(int (*init)(void))
+{
+	struct test_data *data = tester_get_data();
+
+	if (pthread_create(&data->thread, NULL, init_thread, init) != 0)
+		return false;
+
+	return true;
+}
+
+static void setup_generic(int (*setup)(void))
+{
+	struct test_data *data = tester_get_data();
+
+	if (!setup_base(data)) {
 		tester_setup_failed();
 		return;
 	}
 
-	tester_setup_complete();
+	if (!start_init_thread(setup))
+		tester_setup_failed();
+}
+
+static void setup(const void *test_data)
+{
+	setup_generic(init_bluetooth);
+}
+
+static void setup_socket(const void *test_data)
+{
+
+	setup_generic(init_socket);
+}
+
+static void setup_hidhost(const void *test_data)
+{
+	setup_generic(init_hidhost);
+}
+
+static void setup_pan(const void *test_data)
+{
+	setup_generic(init_pan);
+}
+
+static void setup_hdp(const void *test_data)
+{
+	setup_generic(init_hdp);
+}
+
+static void setup_a2dp(const void *test_data)
+{
+	setup_generic(init_a2dp);
+}
+
+static void setup_gatt(const void *test_data)
+{
+	setup_generic(init_gatt);
 }
 
 static void teardown(const void *test_data)
diff --git a/android/tester-main.h b/android/tester-main.h
index 46aacce..f90cf86 100644
--- a/android/tester-main.h
+++ b/android/tester-main.h
@@ -331,6 +331,8 @@ struct test_data {
 	pid_t bluetoothd_pid;
 
 	struct queue *pdus;
+
+	pthread_t thread;
 };
 
 /*
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] android/tester: Set ssp_request_cb to default value in teardown
  2014-09-05  8:09 [PATCH 1/3] android/tester: Init profiles in separate thread Marcin Kraglak
@ 2014-09-05  8:09 ` Marcin Kraglak
  2014-09-05  8:09 ` [PATCH 3/3] android/tester: Use default ssp handler in A2dp - Suspend test case Marcin Kraglak
  2014-09-05  9:50 ` [PATCH 1/3] android/tester: Init profiles in separate thread Szymon Janc
  2 siblings, 0 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-09-05  8:09 UTC (permalink / raw)
  To: linux-bluetooth

It could be set te default_ssp_req_cb and should be set again to
ssp_request_cb.
---
 android/tester-main.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/android/tester-main.c b/android/tester-main.c
index ce13bf7..be3d785 100644
--- a/android/tester-main.c
+++ b/android/tester-main.c
@@ -1633,6 +1633,12 @@ static void teardown(const void *test_data)
 	data->device->close(data->device);
 	audio_hw_device_close(data->audio);
 
+	/*
+	 * Ssp_request_cb pointer can be set do default_ssp_req_cb.
+	 * Set it back to ssp_request_cb
+	 */
+	bt_callbacks.ssp_request_cb = ssp_request_cb;
+
 	if (!data->bluetoothd_pid)
 		tester_teardown_complete();
 }
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] android/tester: Use default ssp handler in A2dp - Suspend test case
  2014-09-05  8:09 [PATCH 1/3] android/tester: Init profiles in separate thread Marcin Kraglak
  2014-09-05  8:09 ` [PATCH 2/3] android/tester: Set ssp_request_cb to default value in teardown Marcin Kraglak
@ 2014-09-05  8:09 ` Marcin Kraglak
  2014-09-05  9:50 ` [PATCH 1/3] android/tester: Init profiles in separate thread Szymon Janc
  2 siblings, 0 replies; 6+ messages in thread
From: Marcin Kraglak @ 2014-09-05  8:09 UTC (permalink / raw)
  To: linux-bluetooth

Because ssp_handler was incorrectly overriden with default_ssp_req_cb
in previous test case, this test case used it also. Now it is needed
to define it for each test case where it should be used.
---
 android/tester-a2dp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/android/tester-a2dp.c b/android/tester-a2dp.c
index 6d4043b..1b2a8ce 100644
--- a/android/tester-a2dp.c
+++ b/android/tester-a2dp.c
@@ -243,6 +243,7 @@ static struct test_case test_cases[] = {
 		CALLBACK_STATE(CB_BT_ADAPTER_STATE_CHANGED, BT_STATE_OFF),
 	),
 	TEST_CASE_BREDRLE("A2DP Suspend - Success",
+		ACTION_SUCCESS(set_default_ssp_request_handler, NULL),
 		ACTION_SUCCESS(bluetooth_enable_action, NULL),
 		CALLBACK_STATE(CB_BT_ADAPTER_STATE_CHANGED, BT_STATE_ON),
 		ACTION_SUCCESS(emu_setup_powered_remote_action, NULL),
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] android/tester: Init profiles in separate thread
  2014-09-05  8:09 [PATCH 1/3] android/tester: Init profiles in separate thread Marcin Kraglak
  2014-09-05  8:09 ` [PATCH 2/3] android/tester: Set ssp_request_cb to default value in teardown Marcin Kraglak
  2014-09-05  8:09 ` [PATCH 3/3] android/tester: Use default ssp handler in A2dp - Suspend test case Marcin Kraglak
@ 2014-09-05  9:50 ` Szymon Janc
  2014-09-05 11:19   ` Luiz Augusto von Dentz
  2 siblings, 1 reply; 6+ messages in thread
From: Szymon Janc @ 2014-09-05  9:50 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth

Hi Marcin,

On Friday 05 of September 2014 10:09:54 Marcin Kraglak wrote:
> This is needed to not block mainloop while initializing stack.
> In some cases, bluetooth->init blocks mainloop and bluetoothd
> cannot properly initialize controller, because HCI frames are
> not serviced in hciemu.
> Because pthread_join() is blocking, it is added to mainloop
> from thread right before pthread_exit() is called. Therefore
> this time is extremely short.
> ---
>  android/tester-main.c | 230 +++++++++++++++++++++++++++-----------------------
>  android/tester-main.h |   2 +
>  2 files changed, 127 insertions(+), 105 deletions(-)
> 
> diff --git a/android/tester-main.c b/android/tester-main.c
> index f5f46fb..ce13bf7 100644
> --- a/android/tester-main.c
> +++ b/android/tester-main.c
> @@ -15,8 +15,10 @@
>   *
>   */
>  #include <stdbool.h>
> +#include <pthread.h>
>  
>  #include "emulator/bthost.h"
> +#include "src/shared/util.h"
>  #include "tester-main.h"
>  
>  #include "monitor/bt.h"
> @@ -1332,237 +1334,255 @@ static bool setup_base(struct test_data *data)
>  	return true;
>  }
>  
> -static void setup(const void *test_data)
> +static int init_bluetooth(void)
>  {
>  	struct test_data *data = tester_get_data();
> -	bt_status_t status;
> -
> -	if (!setup_base(data)) {
> -		tester_setup_failed();
> -		return;
> -	}
> -
> -	status = data->if_bluetooth->init(&bt_callbacks);
> -	if (status != BT_STATUS_SUCCESS) {
> -		data->if_bluetooth = NULL;
> -		tester_setup_failed();
> -		return;
> -	}
>  
> -	tester_setup_complete();
> +	return data->if_bluetooth->init(&bt_callbacks);
>  }
>  
> -static void setup_socket(const void *test_data)
> +static int init_socket(void)
>  {
>  	struct test_data *data = tester_get_data();
> -	bt_status_t status;
>  	const void *sock;
> -
> -	if (!setup_base(data)) {
> -		tester_setup_failed();
> -		return;
> -	}
> +	int status;
>  
>  	status = data->if_bluetooth->init(&bt_callbacks);
>  	if (status != BT_STATUS_SUCCESS) {
>  		data->if_bluetooth = NULL;
> -		tester_setup_failed();
> -		return;
> +		return status;
>  	}
>  
>  	sock = data->if_bluetooth->get_profile_interface(BT_PROFILE_SOCKETS_ID);
> -	if (!sock) {
> -		tester_setup_failed();
> -		return;
> -	}
> +	if (!sock)
> +		return BT_STATUS_FAIL;
>  
>  	data->if_sock = sock;
>  
> -	tester_setup_complete();
> +	return BT_STATUS_SUCCESS;
>  }
>  
> -static void setup_hidhost(const void *test_data)
> +static int init_hidhost(void)
>  {
>  	struct test_data *data = tester_get_data();
>  	bt_status_t status;
>  	const void *hid;
>  
> -	if (!setup_base(data)) {
> -		tester_setup_failed();
> -		return;
> -	}
> -
>  	status = data->if_bluetooth->init(&bt_callbacks);
>  	if (status != BT_STATUS_SUCCESS) {
>  		data->if_bluetooth = NULL;
>  		tester_setup_failed();
> -		return;
> +		return status;
>  	}
>  
>  	hid = data->if_bluetooth->get_profile_interface(BT_PROFILE_HIDHOST_ID);
>  	if (!hid) {
>  		tester_setup_failed();
> -		return;
> +		return BT_STATUS_FAIL;
>  	}
>  
>  	data->if_hid = hid;
>  
>  	status = data->if_hid->init(&bthh_callbacks);
> -	if (status != BT_STATUS_SUCCESS) {
> +	if (status != BT_STATUS_SUCCESS)
>  		data->if_hid = NULL;
> -		tester_setup_failed();
> -		return;
> -	}
>  
> -	tester_setup_complete();
> +	return status;
>  }
>  
> -static void setup_pan(const void *test_data)
> +static int init_pan(void)
>  {
>  	struct test_data *data = tester_get_data();
>  	bt_status_t status;
>  	const void *pan;
>  
> -	if (!setup_base(data)) {
> -		tester_setup_failed();
> -		return;
> -	}
> -
>  	status = data->if_bluetooth->init(&bt_callbacks);
>  	if (status != BT_STATUS_SUCCESS) {
>  		data->if_bluetooth = NULL;
> -		tester_setup_failed();
> -		return;
> +		return status;
>  	}
>  
>  	pan = data->if_bluetooth->get_profile_interface(BT_PROFILE_PAN_ID);
>  	if (!pan) {
> -		tester_setup_failed();
> -		return;
> +		return BT_STATUS_FAIL;
>  	}
>  
>  	data->if_pan = pan;
>  
>  	status = data->if_pan->init(&btpan_callbacks);
> -	if (status != BT_STATUS_SUCCESS) {
> +	if (status != BT_STATUS_SUCCESS)
>  		data->if_pan = NULL;
> -		tester_setup_failed();
> -		return;
> -	}
>  
> -	tester_setup_complete();
> +	return status;
>  }
>  
> -static void setup_hdp(const void *test_data)
> +static int init_hdp(void)
>  {
>  	struct test_data *data = tester_get_data();
>  	bt_status_t status;
>  	const void *hdp;
>  
> -	if (!setup_base(data)) {
> -		tester_setup_failed();
> -		return;
> -	}
> -
>  	status = data->if_bluetooth->init(&bt_callbacks);
>  	if (status != BT_STATUS_SUCCESS) {
>  		data->if_bluetooth = NULL;
> -		tester_setup_failed();
> -		return;
> +		return status;
>  	}
>  
>  	hdp = data->if_bluetooth->get_profile_interface(BT_PROFILE_HEALTH_ID);
> -	if (!hdp) {
> -		tester_setup_failed();
> -		return;
> -	}
> +	if (!hdp)
> +		return BT_STATUS_FAIL;
>  
>  	data->if_hdp = hdp;
>  
>  	status = data->if_hdp->init(&bthl_callbacks);
> -	if (status != BT_STATUS_SUCCESS) {
> +	if (status != BT_STATUS_SUCCESS)
>  		data->if_hdp = NULL;
> -		tester_setup_failed();
> -		return;
> -	}
>  
> -	tester_setup_complete();
> +	return status;
>  }
>  
> -static void setup_a2dp(const void *test_data)
> +static int init_a2dp(void)
>  {
>  	struct test_data *data = tester_get_data();
>  	const bt_interface_t *if_bt;
>  	bt_status_t status;
>  	const void *a2dp;
>  
> -	if (!setup_base(data)) {
> -		tester_setup_failed();
> -		return;
> -	}
> -
>  	if_bt = data->if_bluetooth;
>  
>  	status = if_bt->init(&bt_callbacks);
>  	if (status != BT_STATUS_SUCCESS) {
>  		data->if_bluetooth = NULL;
> -		tester_setup_failed();
> -		return;
> +		return status;
>  	}
>  
>  	a2dp = if_bt->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID);
> -	if (!a2dp) {
> -		tester_setup_failed();
> -		return;
> -	}
> +	if (!a2dp)
> +		return  BT_STATUS_FAIL;
>  
>  	data->if_a2dp = a2dp;
>  
>  	status = data->if_a2dp->init(&bta2dp_callbacks);
> -	if (status != BT_STATUS_SUCCESS) {
> +	if (status != BT_STATUS_SUCCESS)
>  		data->if_a2dp = NULL;
> -		tester_setup_failed();
> -		return;
> -	}
>  
> -	tester_setup_complete();
> +	return status;
>  }
>  
> -static void setup_gatt(const void *test_data)
> +static int init_gatt(void)
>  {
>  	struct test_data *data = tester_get_data();
>  	bt_status_t status;
>  	const void *gatt;
>  
> -	if (!setup_base(data)) {
> -		tester_setup_failed();
> -		return;
> -	}
> -
>  	status = data->if_bluetooth->init(&bt_callbacks);
>  	if (status != BT_STATUS_SUCCESS) {
>  		data->if_bluetooth = NULL;
> -		tester_setup_failed();
> -		return;
> +		return status;
>  	}
>  
>  	gatt = data->if_bluetooth->get_profile_interface(BT_PROFILE_GATT_ID);
> -	if (!gatt) {
> -		tester_setup_failed();
> -		return;
> -	}
> +	if (!gatt)
> +		return BT_STATUS_FAIL;
>  
>  	data->if_gatt = gatt;
>  
>  	status = data->if_gatt->init(&btgatt_callbacks);
> -	if (status != BT_STATUS_SUCCESS) {
> +	if (status != BT_STATUS_SUCCESS)
>  		data->if_gatt = NULL;
>  
> +	return status;
> +}
> +
> +static gboolean join_init_thread(gpointer user_data)
> +{
> +	struct test_data *data = tester_get_data();
> +	int status;
> +
> +	/* Note that pthread_join is blocking mainloop,
> +	 * therefore thread we want to join must
> +	 * exit imediatelly. This is done in init_thread()*/
> +	status = pthread_join(data->thread, NULL);
> +	if (status != 0)
> +		tester_warn("Failed to join init thread, status %d", status);
> +
> +	if (PTR_TO_INT(user_data) == BT_STATUS_SUCCESS)
> +		tester_setup_complete();
> +	else
> +		tester_setup_failed();
> +
> +	return FALSE;
> +}
> +
> +static void *init_thread(void *user_data)
> +{
> +	int (*setup_func)(void) = user_data;
> +	int status;
> +
> +	status = setup_func();
> +
> +	g_idle_add(join_init_thread, INT_TO_PTR(status));
> +
> +	pthread_exit(NULL);
> +}
> +
> +static bool start_init_thread(int (*init)(void))
> +{
> +	struct test_data *data = tester_get_data();
> +
> +	if (pthread_create(&data->thread, NULL, init_thread, init) != 0)
> +		return false;
> +
> +	return true;
> +}
> +
> +static void setup_generic(int (*setup)(void))
> +{
> +	struct test_data *data = tester_get_data();
> +
> +	if (!setup_base(data)) {
>  		tester_setup_failed();
>  		return;
>  	}
>  
> -	tester_setup_complete();
> +	if (!start_init_thread(setup))
> +		tester_setup_failed();
> +}
> +
> +static void setup(const void *test_data)
> +{
> +	setup_generic(init_bluetooth);
> +}
> +
> +static void setup_socket(const void *test_data)
> +{
> +
> +	setup_generic(init_socket);
> +}
> +
> +static void setup_hidhost(const void *test_data)
> +{
> +	setup_generic(init_hidhost);
> +}
> +
> +static void setup_pan(const void *test_data)
> +{
> +	setup_generic(init_pan);
> +}
> +
> +static void setup_hdp(const void *test_data)
> +{
> +	setup_generic(init_hdp);
> +}
> +
> +static void setup_a2dp(const void *test_data)
> +{
> +	setup_generic(init_a2dp);
> +}
> +
> +static void setup_gatt(const void *test_data)
> +{
> +	setup_generic(init_gatt);
>  }
>  
>  static void teardown(const void *test_data)
> diff --git a/android/tester-main.h b/android/tester-main.h
> index 46aacce..f90cf86 100644
> --- a/android/tester-main.h
> +++ b/android/tester-main.h
> @@ -331,6 +331,8 @@ struct test_data {
>  	pid_t bluetoothd_pid;
>  
>  	struct queue *pdus;
> +
> +	pthread_t thread;
>  };
>  
>  /*
> 

I've applied patches 2 and 3. Patch 1 needs to be modified as we discussed
offline. Thanks.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] android/tester: Init profiles in separate thread
  2014-09-05  9:50 ` [PATCH 1/3] android/tester: Init profiles in separate thread Szymon Janc
@ 2014-09-05 11:19   ` Luiz Augusto von Dentz
  2014-09-05 11:30     ` Szymon Janc
  0 siblings, 1 reply; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2014-09-05 11:19 UTC (permalink / raw)
  To: Szymon Janc; +Cc: Marcin Kraglak, linux-bluetooth

Hi Szymon,

On Fri, Sep 5, 2014 at 12:50 PM, Szymon Janc <szymon.janc@tieto.com> wrote:
> Hi Marcin,
>
> On Friday 05 of September 2014 10:09:54 Marcin Kraglak wrote:
>> This is needed to not block mainloop while initializing stack.
>> In some cases, bluetooth->init blocks mainloop and bluetoothd
>> cannot properly initialize controller, because HCI frames are
>> not serviced in hciemu.
>> Because pthread_join() is blocking, it is added to mainloop
>> from thread right before pthread_exit() is called. Therefore
>> this time is extremely short.
>> ---
>>  android/tester-main.c | 230 +++++++++++++++++++++++++++-----------------------
>>  android/tester-main.h |   2 +
>>  2 files changed, 127 insertions(+), 105 deletions(-)
>>
>> diff --git a/android/tester-main.c b/android/tester-main.c
>> index f5f46fb..ce13bf7 100644
>> --- a/android/tester-main.c
>> +++ b/android/tester-main.c
>> @@ -15,8 +15,10 @@
>>   *
>>   */
>>  #include <stdbool.h>
>> +#include <pthread.h>
>>
>>  #include "emulator/bthost.h"
>> +#include "src/shared/util.h"
>>  #include "tester-main.h"
>>
>>  #include "monitor/bt.h"
>> @@ -1332,237 +1334,255 @@ static bool setup_base(struct test_data *data)
>>       return true;
>>  }
>>
>> -static void setup(const void *test_data)
>> +static int init_bluetooth(void)
>>  {
>>       struct test_data *data = tester_get_data();
>> -     bt_status_t status;
>> -
>> -     if (!setup_base(data)) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> -
>> -     status = data->if_bluetooth->init(&bt_callbacks);
>> -     if (status != BT_STATUS_SUCCESS) {
>> -             data->if_bluetooth = NULL;
>> -             tester_setup_failed();
>> -             return;
>> -     }
>>
>> -     tester_setup_complete();
>> +     return data->if_bluetooth->init(&bt_callbacks);
>>  }
>>
>> -static void setup_socket(const void *test_data)
>> +static int init_socket(void)
>>  {
>>       struct test_data *data = tester_get_data();
>> -     bt_status_t status;
>>       const void *sock;
>> -
>> -     if (!setup_base(data)) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> +     int status;
>>
>>       status = data->if_bluetooth->init(&bt_callbacks);
>>       if (status != BT_STATUS_SUCCESS) {
>>               data->if_bluetooth = NULL;
>> -             tester_setup_failed();
>> -             return;
>> +             return status;
>>       }
>>
>>       sock = data->if_bluetooth->get_profile_interface(BT_PROFILE_SOCKETS_ID);
>> -     if (!sock) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> +     if (!sock)
>> +             return BT_STATUS_FAIL;
>>
>>       data->if_sock = sock;
>>
>> -     tester_setup_complete();
>> +     return BT_STATUS_SUCCESS;
>>  }
>>
>> -static void setup_hidhost(const void *test_data)
>> +static int init_hidhost(void)
>>  {
>>       struct test_data *data = tester_get_data();
>>       bt_status_t status;
>>       const void *hid;
>>
>> -     if (!setup_base(data)) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> -
>>       status = data->if_bluetooth->init(&bt_callbacks);
>>       if (status != BT_STATUS_SUCCESS) {
>>               data->if_bluetooth = NULL;
>>               tester_setup_failed();
>> -             return;
>> +             return status;
>>       }
>>
>>       hid = data->if_bluetooth->get_profile_interface(BT_PROFILE_HIDHOST_ID);
>>       if (!hid) {
>>               tester_setup_failed();
>> -             return;
>> +             return BT_STATUS_FAIL;
>>       }
>>
>>       data->if_hid = hid;
>>
>>       status = data->if_hid->init(&bthh_callbacks);
>> -     if (status != BT_STATUS_SUCCESS) {
>> +     if (status != BT_STATUS_SUCCESS)
>>               data->if_hid = NULL;
>> -             tester_setup_failed();
>> -             return;
>> -     }
>>
>> -     tester_setup_complete();
>> +     return status;
>>  }
>>
>> -static void setup_pan(const void *test_data)
>> +static int init_pan(void)
>>  {
>>       struct test_data *data = tester_get_data();
>>       bt_status_t status;
>>       const void *pan;
>>
>> -     if (!setup_base(data)) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> -
>>       status = data->if_bluetooth->init(&bt_callbacks);
>>       if (status != BT_STATUS_SUCCESS) {
>>               data->if_bluetooth = NULL;
>> -             tester_setup_failed();
>> -             return;
>> +             return status;
>>       }
>>
>>       pan = data->if_bluetooth->get_profile_interface(BT_PROFILE_PAN_ID);
>>       if (!pan) {
>> -             tester_setup_failed();
>> -             return;
>> +             return BT_STATUS_FAIL;
>>       }
>>
>>       data->if_pan = pan;
>>
>>       status = data->if_pan->init(&btpan_callbacks);
>> -     if (status != BT_STATUS_SUCCESS) {
>> +     if (status != BT_STATUS_SUCCESS)
>>               data->if_pan = NULL;
>> -             tester_setup_failed();
>> -             return;
>> -     }
>>
>> -     tester_setup_complete();
>> +     return status;
>>  }
>>
>> -static void setup_hdp(const void *test_data)
>> +static int init_hdp(void)
>>  {
>>       struct test_data *data = tester_get_data();
>>       bt_status_t status;
>>       const void *hdp;
>>
>> -     if (!setup_base(data)) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> -
>>       status = data->if_bluetooth->init(&bt_callbacks);
>>       if (status != BT_STATUS_SUCCESS) {
>>               data->if_bluetooth = NULL;
>> -             tester_setup_failed();
>> -             return;
>> +             return status;
>>       }
>>
>>       hdp = data->if_bluetooth->get_profile_interface(BT_PROFILE_HEALTH_ID);
>> -     if (!hdp) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> +     if (!hdp)
>> +             return BT_STATUS_FAIL;
>>
>>       data->if_hdp = hdp;
>>
>>       status = data->if_hdp->init(&bthl_callbacks);
>> -     if (status != BT_STATUS_SUCCESS) {
>> +     if (status != BT_STATUS_SUCCESS)
>>               data->if_hdp = NULL;
>> -             tester_setup_failed();
>> -             return;
>> -     }
>>
>> -     tester_setup_complete();
>> +     return status;
>>  }
>>
>> -static void setup_a2dp(const void *test_data)
>> +static int init_a2dp(void)
>>  {
>>       struct test_data *data = tester_get_data();
>>       const bt_interface_t *if_bt;
>>       bt_status_t status;
>>       const void *a2dp;
>>
>> -     if (!setup_base(data)) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> -
>>       if_bt = data->if_bluetooth;
>>
>>       status = if_bt->init(&bt_callbacks);
>>       if (status != BT_STATUS_SUCCESS) {
>>               data->if_bluetooth = NULL;
>> -             tester_setup_failed();
>> -             return;
>> +             return status;
>>       }
>>
>>       a2dp = if_bt->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID);
>> -     if (!a2dp) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> +     if (!a2dp)
>> +             return  BT_STATUS_FAIL;
>>
>>       data->if_a2dp = a2dp;
>>
>>       status = data->if_a2dp->init(&bta2dp_callbacks);
>> -     if (status != BT_STATUS_SUCCESS) {
>> +     if (status != BT_STATUS_SUCCESS)
>>               data->if_a2dp = NULL;
>> -             tester_setup_failed();
>> -             return;
>> -     }
>>
>> -     tester_setup_complete();
>> +     return status;
>>  }
>>
>> -static void setup_gatt(const void *test_data)
>> +static int init_gatt(void)
>>  {
>>       struct test_data *data = tester_get_data();
>>       bt_status_t status;
>>       const void *gatt;
>>
>> -     if (!setup_base(data)) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> -
>>       status = data->if_bluetooth->init(&bt_callbacks);
>>       if (status != BT_STATUS_SUCCESS) {
>>               data->if_bluetooth = NULL;
>> -             tester_setup_failed();
>> -             return;
>> +             return status;
>>       }
>>
>>       gatt = data->if_bluetooth->get_profile_interface(BT_PROFILE_GATT_ID);
>> -     if (!gatt) {
>> -             tester_setup_failed();
>> -             return;
>> -     }
>> +     if (!gatt)
>> +             return BT_STATUS_FAIL;
>>
>>       data->if_gatt = gatt;
>>
>>       status = data->if_gatt->init(&btgatt_callbacks);
>> -     if (status != BT_STATUS_SUCCESS) {
>> +     if (status != BT_STATUS_SUCCESS)
>>               data->if_gatt = NULL;
>>
>> +     return status;
>> +}
>> +
>> +static gboolean join_init_thread(gpointer user_data)
>> +{
>> +     struct test_data *data = tester_get_data();
>> +     int status;
>> +
>> +     /* Note that pthread_join is blocking mainloop,
>> +      * therefore thread we want to join must
>> +      * exit imediatelly. This is done in init_thread()*/
>> +     status = pthread_join(data->thread, NULL);
>> +     if (status != 0)
>> +             tester_warn("Failed to join init thread, status %d", status);
>> +
>> +     if (PTR_TO_INT(user_data) == BT_STATUS_SUCCESS)
>> +             tester_setup_complete();
>> +     else
>> +             tester_setup_failed();
>> +
>> +     return FALSE;
>> +}
>> +
>> +static void *init_thread(void *user_data)
>> +{
>> +     int (*setup_func)(void) = user_data;
>> +     int status;
>> +
>> +     status = setup_func();
>> +
>> +     g_idle_add(join_init_thread, INT_TO_PTR(status));
>> +
>> +     pthread_exit(NULL);
>> +}
>> +
>> +static bool start_init_thread(int (*init)(void))
>> +{
>> +     struct test_data *data = tester_get_data();
>> +
>> +     if (pthread_create(&data->thread, NULL, init_thread, init) != 0)
>> +             return false;
>> +
>> +     return true;
>> +}
>> +
>> +static void setup_generic(int (*setup)(void))
>> +{
>> +     struct test_data *data = tester_get_data();
>> +
>> +     if (!setup_base(data)) {
>>               tester_setup_failed();
>>               return;
>>       }
>>
>> -     tester_setup_complete();
>> +     if (!start_init_thread(setup))
>> +             tester_setup_failed();
>> +}
>> +
>> +static void setup(const void *test_data)
>> +{
>> +     setup_generic(init_bluetooth);
>> +}
>> +
>> +static void setup_socket(const void *test_data)
>> +{
>> +
>> +     setup_generic(init_socket);
>> +}
>> +
>> +static void setup_hidhost(const void *test_data)
>> +{
>> +     setup_generic(init_hidhost);
>> +}
>> +
>> +static void setup_pan(const void *test_data)
>> +{
>> +     setup_generic(init_pan);
>> +}
>> +
>> +static void setup_hdp(const void *test_data)
>> +{
>> +     setup_generic(init_hdp);
>> +}
>> +
>> +static void setup_a2dp(const void *test_data)
>> +{
>> +     setup_generic(init_a2dp);
>> +}
>> +
>> +static void setup_gatt(const void *test_data)
>> +{
>> +     setup_generic(init_gatt);
>>  }
>>
>>  static void teardown(const void *test_data)
>> diff --git a/android/tester-main.h b/android/tester-main.h
>> index 46aacce..f90cf86 100644
>> --- a/android/tester-main.h
>> +++ b/android/tester-main.h
>> @@ -331,6 +331,8 @@ struct test_data {
>>       pid_t bluetoothd_pid;
>>
>>       struct queue *pdus;
>> +
>> +     pthread_t thread;
>>  };
>>
>>  /*
>>
>
> I've applied patches 2 and 3. Patch 1 needs to be modified as we discussed
> offline. Thanks.

We used to fork bluetoothd when bringing up the interface with ioctl,
so I guess we could for here as well just to initialize.


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] android/tester: Init profiles in separate thread
  2014-09-05 11:19   ` Luiz Augusto von Dentz
@ 2014-09-05 11:30     ` Szymon Janc
  0 siblings, 0 replies; 6+ messages in thread
From: Szymon Janc @ 2014-09-05 11:30 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: Marcin Kraglak, linux-bluetooth

Hi Luiz,

On Friday 05 of September 2014 14:19:48 Luiz Augusto von Dentz wrote:
> Hi Szymon,
> 
> On Fri, Sep 5, 2014 at 12:50 PM, Szymon Janc <szymon.janc@tieto.com> wrote:
> > Hi Marcin,
> >
> > On Friday 05 of September 2014 10:09:54 Marcin Kraglak wrote:
> >> This is needed to not block mainloop while initializing stack.
> >> In some cases, bluetooth->init blocks mainloop and bluetoothd
> >> cannot properly initialize controller, because HCI frames are
> >> not serviced in hciemu.
> >> Because pthread_join() is blocking, it is added to mainloop
> >> from thread right before pthread_exit() is called. Therefore
> >> this time is extremely short.
> >> ---
> >>  android/tester-main.c | 230 +++++++++++++++++++++++++++-----------------------
> >>  android/tester-main.h |   2 +
> >>  2 files changed, 127 insertions(+), 105 deletions(-)
> >>
> >> diff --git a/android/tester-main.c b/android/tester-main.c
> >> index f5f46fb..ce13bf7 100644
> >> --- a/android/tester-main.c
> >> +++ b/android/tester-main.c
> >> @@ -15,8 +15,10 @@
> >>   *
> >>   */
> >>  #include <stdbool.h>
> >> +#include <pthread.h>
> >>
> >>  #include "emulator/bthost.h"
> >> +#include "src/shared/util.h"
> >>  #include "tester-main.h"
> >>
> >>  #include "monitor/bt.h"
> >> @@ -1332,237 +1334,255 @@ static bool setup_base(struct test_data *data)
> >>       return true;
> >>  }
> >>
> >> -static void setup(const void *test_data)
> >> +static int init_bluetooth(void)
> >>  {
> >>       struct test_data *data = tester_get_data();
> >> -     bt_status_t status;
> >> -
> >> -     if (!setup_base(data)) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> -
> >> -     status = data->if_bluetooth->init(&bt_callbacks);
> >> -     if (status != BT_STATUS_SUCCESS) {
> >> -             data->if_bluetooth = NULL;
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >>
> >> -     tester_setup_complete();
> >> +     return data->if_bluetooth->init(&bt_callbacks);
> >>  }
> >>
> >> -static void setup_socket(const void *test_data)
> >> +static int init_socket(void)
> >>  {
> >>       struct test_data *data = tester_get_data();
> >> -     bt_status_t status;
> >>       const void *sock;
> >> -
> >> -     if (!setup_base(data)) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> +     int status;
> >>
> >>       status = data->if_bluetooth->init(&bt_callbacks);
> >>       if (status != BT_STATUS_SUCCESS) {
> >>               data->if_bluetooth = NULL;
> >> -             tester_setup_failed();
> >> -             return;
> >> +             return status;
> >>       }
> >>
> >>       sock = data->if_bluetooth->get_profile_interface(BT_PROFILE_SOCKETS_ID);
> >> -     if (!sock) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> +     if (!sock)
> >> +             return BT_STATUS_FAIL;
> >>
> >>       data->if_sock = sock;
> >>
> >> -     tester_setup_complete();
> >> +     return BT_STATUS_SUCCESS;
> >>  }
> >>
> >> -static void setup_hidhost(const void *test_data)
> >> +static int init_hidhost(void)
> >>  {
> >>       struct test_data *data = tester_get_data();
> >>       bt_status_t status;
> >>       const void *hid;
> >>
> >> -     if (!setup_base(data)) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> -
> >>       status = data->if_bluetooth->init(&bt_callbacks);
> >>       if (status != BT_STATUS_SUCCESS) {
> >>               data->if_bluetooth = NULL;
> >>               tester_setup_failed();
> >> -             return;
> >> +             return status;
> >>       }
> >>
> >>       hid = data->if_bluetooth->get_profile_interface(BT_PROFILE_HIDHOST_ID);
> >>       if (!hid) {
> >>               tester_setup_failed();
> >> -             return;
> >> +             return BT_STATUS_FAIL;
> >>       }
> >>
> >>       data->if_hid = hid;
> >>
> >>       status = data->if_hid->init(&bthh_callbacks);
> >> -     if (status != BT_STATUS_SUCCESS) {
> >> +     if (status != BT_STATUS_SUCCESS)
> >>               data->if_hid = NULL;
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >>
> >> -     tester_setup_complete();
> >> +     return status;
> >>  }
> >>
> >> -static void setup_pan(const void *test_data)
> >> +static int init_pan(void)
> >>  {
> >>       struct test_data *data = tester_get_data();
> >>       bt_status_t status;
> >>       const void *pan;
> >>
> >> -     if (!setup_base(data)) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> -
> >>       status = data->if_bluetooth->init(&bt_callbacks);
> >>       if (status != BT_STATUS_SUCCESS) {
> >>               data->if_bluetooth = NULL;
> >> -             tester_setup_failed();
> >> -             return;
> >> +             return status;
> >>       }
> >>
> >>       pan = data->if_bluetooth->get_profile_interface(BT_PROFILE_PAN_ID);
> >>       if (!pan) {
> >> -             tester_setup_failed();
> >> -             return;
> >> +             return BT_STATUS_FAIL;
> >>       }
> >>
> >>       data->if_pan = pan;
> >>
> >>       status = data->if_pan->init(&btpan_callbacks);
> >> -     if (status != BT_STATUS_SUCCESS) {
> >> +     if (status != BT_STATUS_SUCCESS)
> >>               data->if_pan = NULL;
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >>
> >> -     tester_setup_complete();
> >> +     return status;
> >>  }
> >>
> >> -static void setup_hdp(const void *test_data)
> >> +static int init_hdp(void)
> >>  {
> >>       struct test_data *data = tester_get_data();
> >>       bt_status_t status;
> >>       const void *hdp;
> >>
> >> -     if (!setup_base(data)) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> -
> >>       status = data->if_bluetooth->init(&bt_callbacks);
> >>       if (status != BT_STATUS_SUCCESS) {
> >>               data->if_bluetooth = NULL;
> >> -             tester_setup_failed();
> >> -             return;
> >> +             return status;
> >>       }
> >>
> >>       hdp = data->if_bluetooth->get_profile_interface(BT_PROFILE_HEALTH_ID);
> >> -     if (!hdp) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> +     if (!hdp)
> >> +             return BT_STATUS_FAIL;
> >>
> >>       data->if_hdp = hdp;
> >>
> >>       status = data->if_hdp->init(&bthl_callbacks);
> >> -     if (status != BT_STATUS_SUCCESS) {
> >> +     if (status != BT_STATUS_SUCCESS)
> >>               data->if_hdp = NULL;
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >>
> >> -     tester_setup_complete();
> >> +     return status;
> >>  }
> >>
> >> -static void setup_a2dp(const void *test_data)
> >> +static int init_a2dp(void)
> >>  {
> >>       struct test_data *data = tester_get_data();
> >>       const bt_interface_t *if_bt;
> >>       bt_status_t status;
> >>       const void *a2dp;
> >>
> >> -     if (!setup_base(data)) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> -
> >>       if_bt = data->if_bluetooth;
> >>
> >>       status = if_bt->init(&bt_callbacks);
> >>       if (status != BT_STATUS_SUCCESS) {
> >>               data->if_bluetooth = NULL;
> >> -             tester_setup_failed();
> >> -             return;
> >> +             return status;
> >>       }
> >>
> >>       a2dp = if_bt->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID);
> >> -     if (!a2dp) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> +     if (!a2dp)
> >> +             return  BT_STATUS_FAIL;
> >>
> >>       data->if_a2dp = a2dp;
> >>
> >>       status = data->if_a2dp->init(&bta2dp_callbacks);
> >> -     if (status != BT_STATUS_SUCCESS) {
> >> +     if (status != BT_STATUS_SUCCESS)
> >>               data->if_a2dp = NULL;
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >>
> >> -     tester_setup_complete();
> >> +     return status;
> >>  }
> >>
> >> -static void setup_gatt(const void *test_data)
> >> +static int init_gatt(void)
> >>  {
> >>       struct test_data *data = tester_get_data();
> >>       bt_status_t status;
> >>       const void *gatt;
> >>
> >> -     if (!setup_base(data)) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> -
> >>       status = data->if_bluetooth->init(&bt_callbacks);
> >>       if (status != BT_STATUS_SUCCESS) {
> >>               data->if_bluetooth = NULL;
> >> -             tester_setup_failed();
> >> -             return;
> >> +             return status;
> >>       }
> >>
> >>       gatt = data->if_bluetooth->get_profile_interface(BT_PROFILE_GATT_ID);
> >> -     if (!gatt) {
> >> -             tester_setup_failed();
> >> -             return;
> >> -     }
> >> +     if (!gatt)
> >> +             return BT_STATUS_FAIL;
> >>
> >>       data->if_gatt = gatt;
> >>
> >>       status = data->if_gatt->init(&btgatt_callbacks);
> >> -     if (status != BT_STATUS_SUCCESS) {
> >> +     if (status != BT_STATUS_SUCCESS)
> >>               data->if_gatt = NULL;
> >>
> >> +     return status;
> >> +}
> >> +
> >> +static gboolean join_init_thread(gpointer user_data)
> >> +{
> >> +     struct test_data *data = tester_get_data();
> >> +     int status;
> >> +
> >> +     /* Note that pthread_join is blocking mainloop,
> >> +      * therefore thread we want to join must
> >> +      * exit imediatelly. This is done in init_thread()*/
> >> +     status = pthread_join(data->thread, NULL);
> >> +     if (status != 0)
> >> +             tester_warn("Failed to join init thread, status %d", status);
> >> +
> >> +     if (PTR_TO_INT(user_data) == BT_STATUS_SUCCESS)
> >> +             tester_setup_complete();
> >> +     else
> >> +             tester_setup_failed();
> >> +
> >> +     return FALSE;
> >> +}
> >> +
> >> +static void *init_thread(void *user_data)
> >> +{
> >> +     int (*setup_func)(void) = user_data;
> >> +     int status;
> >> +
> >> +     status = setup_func();
> >> +
> >> +     g_idle_add(join_init_thread, INT_TO_PTR(status));
> >> +
> >> +     pthread_exit(NULL);
> >> +}
> >> +
> >> +static bool start_init_thread(int (*init)(void))
> >> +{
> >> +     struct test_data *data = tester_get_data();
> >> +
> >> +     if (pthread_create(&data->thread, NULL, init_thread, init) != 0)
> >> +             return false;
> >> +
> >> +     return true;
> >> +}
> >> +
> >> +static void setup_generic(int (*setup)(void))
> >> +{
> >> +     struct test_data *data = tester_get_data();
> >> +
> >> +     if (!setup_base(data)) {
> >>               tester_setup_failed();
> >>               return;
> >>       }
> >>
> >> -     tester_setup_complete();
> >> +     if (!start_init_thread(setup))
> >> +             tester_setup_failed();
> >> +}
> >> +
> >> +static void setup(const void *test_data)
> >> +{
> >> +     setup_generic(init_bluetooth);
> >> +}
> >> +
> >> +static void setup_socket(const void *test_data)
> >> +{
> >> +
> >> +     setup_generic(init_socket);
> >> +}
> >> +
> >> +static void setup_hidhost(const void *test_data)
> >> +{
> >> +     setup_generic(init_hidhost);
> >> +}
> >> +
> >> +static void setup_pan(const void *test_data)
> >> +{
> >> +     setup_generic(init_pan);
> >> +}
> >> +
> >> +static void setup_hdp(const void *test_data)
> >> +{
> >> +     setup_generic(init_hdp);
> >> +}
> >> +
> >> +static void setup_a2dp(const void *test_data)
> >> +{
> >> +     setup_generic(init_a2dp);
> >> +}
> >> +
> >> +static void setup_gatt(const void *test_data)
> >> +{
> >> +     setup_generic(init_gatt);
> >>  }
> >>
> >>  static void teardown(const void *test_data)
> >> diff --git a/android/tester-main.h b/android/tester-main.h
> >> index 46aacce..f90cf86 100644
> >> --- a/android/tester-main.h
> >> +++ b/android/tester-main.h
> >> @@ -331,6 +331,8 @@ struct test_data {
> >>       pid_t bluetoothd_pid;
> >>
> >>       struct queue *pdus;
> >> +
> >> +     pthread_t thread;
> >>  };
> >>
> >>  /*
> >>
> >
> > I've applied patches 2 and 3. Patch 1 needs to be modified as we discussed
> > offline. Thanks.
> 
> We used to fork bluetoothd when bringing up the interface with ioctl,
> so I guess we could for here as well just to initialize.

We can't use fork here since we would initialize HAL in child process, not
parent.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-09-05 11:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-05  8:09 [PATCH 1/3] android/tester: Init profiles in separate thread Marcin Kraglak
2014-09-05  8:09 ` [PATCH 2/3] android/tester: Set ssp_request_cb to default value in teardown Marcin Kraglak
2014-09-05  8:09 ` [PATCH 3/3] android/tester: Use default ssp handler in A2dp - Suspend test case Marcin Kraglak
2014-09-05  9:50 ` [PATCH 1/3] android/tester: Init profiles in separate thread Szymon Janc
2014-09-05 11:19   ` Luiz Augusto von Dentz
2014-09-05 11:30     ` 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.