2013-12-18 11:20:56

by Szymon Janc

[permalink] [raw]
Subject: [RFC 0/4] android: Permanent storage support

Hi All,

This is first RFC for storage format for Android daemon.

Some highlights:
- storage is much simple in format than Linux daemon (no addresses in paths
or filenames, only 1 adapter support etc)
- only info that requires persistency over daemon lifetime from Framework
perspective is stored
- settings file for adapter config
- devices file for remote device info (groups are remote devices addresses)
- Android storage path is /data/misc/bluez (I've decided to not use
/data/misc/bluetooth to avoid any clashes as there still seems to be
leftovers available in Android tree eg. there are still references to that
directory in CTS testcases and init files of Android 4.4)

I'm not sure how to handle storage on Linux host so for now it is set to
STORAGEDIR/android/ directory (if directory is missing it is not created
by daemon).

Storage format is as following sample:

settings file:
[General]
Address=20:68:9D:3A:52:5E
Name=BlueZ Android
DiscoverableTimeout=0

devices file:
[00:0D:3C:B1:C4:AC]
Type=0
Name=Nokia BH-503
Class=2360324
LinkKey=0x306A400930B0AE36D7AC45D8DC50F1A0
LinkKeyType=0
LinkKeyPINLength=4
Services=0x0000110B00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111E00001000800000805F9B34FB;0x0000110800001000800000805F9B34FB;

[00:1F:20:17:87:D7]
Type=0
Name=Bluetooth Laser Travel Mouse
Class=9600
LinkKey=0x3725CC552EAB8AB82D843BFEB14D2E47
LinkKeyType=0
LinkKeyPINLength=4
Services=0x0000112400001000800000805F9B34FB;0x0000120000001000800000805F9B34FB;

[40:B0:FA:39:FF:B8]
Type=0
Name=Nexus 4
Class=5898764
LinkKey=0x1E201EE8E82E1E50682622077D372F20
LinkKeyType=5
LinkKeyPINLength=0
Services=0x0000180100001000800000805F9B34FB;0x0000180000001000800000805F9B34FB;0x0000111200001000800000805F9B34FB;0x0000111F00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110A00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111600001000800000805F9B34FB;0x0000111500001000800000805F9B34FB;0x0000113200001000800000805F9B34FB;0x0000112F00001000800000805F9B34FB;0x0000110500001000800000805F9B34FB;


Comments are welcome.

Szymon Janc (4):
android/bluetooth: Add initial support for permanent storage
android/bluetooth: Add initial support for storing device info
android/bluetooth: Add support for storing link keys
android/bluetooth: Add support for restoring devices from storage

android/Android.mk | 3 +-
android/bluetooth.c | 317 ++++++++++++++++++++++++++++++++++++++++++++++++++--
configure.ac | 3 +
3 files changed, 311 insertions(+), 12 deletions(-)

--
1.8.3.2



2013-12-18 12:39:18

by Szymon Janc

[permalink] [raw]
Subject: Re: [RFC 0/4] android: Permanent storage support

Hi Andrei,

> Hi Szymon,
>
> On Wed, Dec 18, 2013 at 01:23:40PM +0100, Szymon Janc wrote:
> > Hi Marcel,
> >
> > > Hi Szymon,
> > >
> > > > This is first RFC for storage format for Android daemon.
> > > >
> > > > Some highlights:
> > > > - storage is much simple in format than Linux daemon (no addresses in paths
> > > > or filenames, only 1 adapter support etc)
> > > > - only info that requires persistency over daemon lifetime from Framework
> > > > perspective is stored
> > > > - settings file for adapter config
> > > > - devices file for remote device info (groups are remote devices addresses)
> > > > - Android storage path is /data/misc/bluez (I've decided to not use
> > > > /data/misc/bluetooth to avoid any clashes as there still seems to be
> > > > leftovers available in Android tree eg. there are still references to that
> > > > directory in CTS testcases and init files of Android 4.4)
> > >
> > > I would use /data/misc/bluetooth actually. Especially since the daemon is also called bluetoothd and not bluezd.
> > >
> > > What is the impact on just using /data/misc/bluetooth and see if anything really breaks.
> >
> > OK, this will require proper chown in device init.rc (as it is set to system/system
> > in system/core/rootdir/init.rc), but that would be needed for /data/misc/bluez path
> > anyway...
>
> I wonder can we find place without need to add extra chown... like using
> Bluedroid configuration location?

I would avoid touching bluedroid configs (other than converting storage, but
this is future anyway). And anyone integrating BlueZ into product will need to
modify init.rc anyway so this is not that much of a problem.

--
BR
Szymon Janc

2013-12-18 12:35:44

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC 0/4] android: Permanent storage support

Hi Szymon,

>>> This is first RFC for storage format for Android daemon.
>>>
>>> Some highlights:
>>> - storage is much simple in format than Linux daemon (no addresses in paths
>>> or filenames, only 1 adapter support etc)
>>> - only info that requires persistency over daemon lifetime from Framework
>>> perspective is stored
>>> - settings file for adapter config
>>> - devices file for remote device info (groups are remote devices addresses)
>>> - Android storage path is /data/misc/bluez (I've decided to not use
>>> /data/misc/bluetooth to avoid any clashes as there still seems to be
>>> leftovers available in Android tree eg. there are still references to that
>>> directory in CTS testcases and init files of Android 4.4)
>>
>> I would use /data/misc/bluetooth actually. Especially since the daemon is also called bluetoothd and not bluezd.
>>
>> What is the impact on just using /data/misc/bluetooth and see if anything really breaks.
>
> OK, this will require proper chown in device init.rc (as it is set to system/system
> in system/core/rootdir/init.rc), but that would be needed for /data/misc/bluez path
> anyway...
>
>>
>>> I'm not sure how to handle storage on Linux host so for now it is set to
>>> STORAGEDIR/android/ directory (if directory is missing it is not created
>>> by daemon).
>>
>> That is actually fine. Works for me.
>>
>>> Storage format is as following sample:
>>>
>>> settings file:
>>> [General]
>>> Address=20:68:9D:3A:52:5E
>>> Name=BlueZ Android
>>> DiscoverableTimeout=0
>>>
>>> devices file:
>>> [00:0D:3C:B1:C4:AC]
>>> Type=0
>>> Name=Nokia BH-503
>>> Class=2360324
>>> LinkKey=0x306A400930B0AE36D7AC45D8DC50F1A0
>>
>> I would leave the 0x out of it. Just make it a hex encoded string.
>
> OK.
>
>>
>>> LinkKeyType=0
>>> LinkKeyPINLength=4
>>> Services=0x0000110B00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111E00001000800000805F9B34FB;0x0000110800001000800000805F9B34FB;
>>
>> Lets store these as UUID strings. We convert between them anyway.
>
> We actually don't use strings in Android daemon and keep UUIDs as 16bytes
> arrays (same format as HAL expects).
> So we would first need to convert to bt_uuid_t to be able to use lib/uuid.h
> uuid<->string helpers. We could also just add '-' where needed while converting
> array to hexstring if that really improves readability.

then just remove the 0x in front of it and store them the same way as the link keys.

>>> [00:1F:20:17:87:D7]
>>> Type=0
>>> Name=Bluetooth Laser Travel Mouse
>>> Class=9600
>>> LinkKey=0x3725CC552EAB8AB82D843BFEB14D2E47
>>> LinkKeyType=0
>>> LinkKeyPINLength=4
>>> Services=0x0000112400001000800000805F9B34FB;0x0000120000001000800000805F9B34FB;
>>>
>>> [40:B0:FA:39:FF:B8]
>>> Type=0
>>> Name=Nexus 4
>>> Class=5898764
>>> LinkKey=0x1E201EE8E82E1E50682622077D372F20
>>> LinkKeyType=5
>>> LinkKeyPINLength=0
>>> Services=0x0000180100001000800000805F9B34FB;0x0000180000001000800000805F9B34FB;0x0000111200001000800000805F9B34FB;0x0000111F00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110A00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111600001000800000805F9B34FB;0x0000111500001000800000805F9B34FB;0x0000113200001000800000805F9B34FB;0x0000112F00001000800000805F9B34FB;0x0000110500001000800000805F9B34FB;
>>>
>>>
>>> Comments are welcome.
>>
>> I think the only discussion we could have is if we want to store them as 1 file per remote device or all devices in one file. I am personally fine with this approach since it is a limited scope with Android anyway. Also upgrading to a more complex storage later is easily possible.
>
> FWIW, we could also always keep g_key_file in memory and only write on update
> (to reduce reads). And that would be more complicated if we use multiple files.

Sure. That could be done as well.

Regards

Marcel


2013-12-18 12:31:13

by Andrei Emeltchenko

[permalink] [raw]
Subject: Re: [RFC 0/4] android: Permanent storage support

Hi Szymon,

On Wed, Dec 18, 2013 at 01:23:40PM +0100, Szymon Janc wrote:
> Hi Marcel,
>
> > Hi Szymon,
> >
> > > This is first RFC for storage format for Android daemon.
> > >
> > > Some highlights:
> > > - storage is much simple in format than Linux daemon (no addresses in paths
> > > or filenames, only 1 adapter support etc)
> > > - only info that requires persistency over daemon lifetime from Framework
> > > perspective is stored
> > > - settings file for adapter config
> > > - devices file for remote device info (groups are remote devices addresses)
> > > - Android storage path is /data/misc/bluez (I've decided to not use
> > > /data/misc/bluetooth to avoid any clashes as there still seems to be
> > > leftovers available in Android tree eg. there are still references to that
> > > directory in CTS testcases and init files of Android 4.4)
> >
> > I would use /data/misc/bluetooth actually. Especially since the daemon is also called bluetoothd and not bluezd.
> >
> > What is the impact on just using /data/misc/bluetooth and see if anything really breaks.
>
> OK, this will require proper chown in device init.rc (as it is set to system/system
> in system/core/rootdir/init.rc), but that would be needed for /data/misc/bluez path
> anyway...

I wonder can we find place without need to add extra chown... like using
Bluedroid configuration location?

Best regards
Andrei Emeltchenko

2013-12-18 12:23:40

by Szymon Janc

[permalink] [raw]
Subject: Re: [RFC 0/4] android: Permanent storage support

Hi Marcel,

> Hi Szymon,
>
> > This is first RFC for storage format for Android daemon.
> >
> > Some highlights:
> > - storage is much simple in format than Linux daemon (no addresses in paths
> > or filenames, only 1 adapter support etc)
> > - only info that requires persistency over daemon lifetime from Framework
> > perspective is stored
> > - settings file for adapter config
> > - devices file for remote device info (groups are remote devices addresses)
> > - Android storage path is /data/misc/bluez (I've decided to not use
> > /data/misc/bluetooth to avoid any clashes as there still seems to be
> > leftovers available in Android tree eg. there are still references to that
> > directory in CTS testcases and init files of Android 4.4)
>
> I would use /data/misc/bluetooth actually. Especially since the daemon is also called bluetoothd and not bluezd.
>
> What is the impact on just using /data/misc/bluetooth and see if anything really breaks.

OK, this will require proper chown in device init.rc (as it is set to system/system
in system/core/rootdir/init.rc), but that would be needed for /data/misc/bluez path
anyway...

>
> > I'm not sure how to handle storage on Linux host so for now it is set to
> > STORAGEDIR/android/ directory (if directory is missing it is not created
> > by daemon).
>
> That is actually fine. Works for me.
>
> > Storage format is as following sample:
> >
> > settings file:
> > [General]
> > Address=20:68:9D:3A:52:5E
> > Name=BlueZ Android
> > DiscoverableTimeout=0
> >
> > devices file:
> > [00:0D:3C:B1:C4:AC]
> > Type=0
> > Name=Nokia BH-503
> > Class=2360324
> > LinkKey=0x306A400930B0AE36D7AC45D8DC50F1A0
>
> I would leave the 0x out of it. Just make it a hex encoded string.

OK.

>
> > LinkKeyType=0
> > LinkKeyPINLength=4
> > Services=0x0000110B00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111E00001000800000805F9B34FB;0x0000110800001000800000805F9B34FB;
>
> Lets store these as UUID strings. We convert between them anyway.

We actually don't use strings in Android daemon and keep UUIDs as 16bytes
arrays (same format as HAL expects).
So we would first need to convert to bt_uuid_t to be able to use lib/uuid.h
uuid<->string helpers. We could also just add '-' where needed while converting
array to hexstring if that really improves readability.

>
> > [00:1F:20:17:87:D7]
> > Type=0
> > Name=Bluetooth Laser Travel Mouse
> > Class=9600
> > LinkKey=0x3725CC552EAB8AB82D843BFEB14D2E47
> > LinkKeyType=0
> > LinkKeyPINLength=4
> > Services=0x0000112400001000800000805F9B34FB;0x0000120000001000800000805F9B34FB;
> >
> > [40:B0:FA:39:FF:B8]
> > Type=0
> > Name=Nexus 4
> > Class=5898764
> > LinkKey=0x1E201EE8E82E1E50682622077D372F20
> > LinkKeyType=5
> > LinkKeyPINLength=0
> > Services=0x0000180100001000800000805F9B34FB;0x0000180000001000800000805F9B34FB;0x0000111200001000800000805F9B34FB;0x0000111F00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110A00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111600001000800000805F9B34FB;0x0000111500001000800000805F9B34FB;0x0000113200001000800000805F9B34FB;0x0000112F00001000800000805F9B34FB;0x0000110500001000800000805F9B34FB;
> >
> >
> > Comments are welcome.
>
> I think the only discussion we could have is if we want to store them as 1 file per remote device or all devices in one file. I am personally fine with this approach since it is a limited scope with Android anyway. Also upgrading to a more complex storage later is easily possible.

FWIW, we could also always keep g_key_file in memory and only write on update
(to reduce reads). And that would be more complicated if we use multiple files.

--
BR
Szymon Janc

2013-12-18 11:37:22

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC 0/4] android: Permanent storage support

Hi Szymon,

> This is first RFC for storage format for Android daemon.
>
> Some highlights:
> - storage is much simple in format than Linux daemon (no addresses in paths
> or filenames, only 1 adapter support etc)
> - only info that requires persistency over daemon lifetime from Framework
> perspective is stored
> - settings file for adapter config
> - devices file for remote device info (groups are remote devices addresses)
> - Android storage path is /data/misc/bluez (I've decided to not use
> /data/misc/bluetooth to avoid any clashes as there still seems to be
> leftovers available in Android tree eg. there are still references to that
> directory in CTS testcases and init files of Android 4.4)

I would use /data/misc/bluetooth actually. Especially since the daemon is also called bluetoothd and not bluezd.

What is the impact on just using /data/misc/bluetooth and see if anything really breaks.

> I'm not sure how to handle storage on Linux host so for now it is set to
> STORAGEDIR/android/ directory (if directory is missing it is not created
> by daemon).

That is actually fine. Works for me.

> Storage format is as following sample:
>
> settings file:
> [General]
> Address=20:68:9D:3A:52:5E
> Name=BlueZ Android
> DiscoverableTimeout=0
>
> devices file:
> [00:0D:3C:B1:C4:AC]
> Type=0
> Name=Nokia BH-503
> Class=2360324
> LinkKey=0x306A400930B0AE36D7AC45D8DC50F1A0

I would leave the 0x out of it. Just make it a hex encoded string.

> LinkKeyType=0
> LinkKeyPINLength=4
> Services=0x0000110B00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111E00001000800000805F9B34FB;0x0000110800001000800000805F9B34FB;

Lets store these as UUID strings. We convert between them anyway.

> [00:1F:20:17:87:D7]
> Type=0
> Name=Bluetooth Laser Travel Mouse
> Class=9600
> LinkKey=0x3725CC552EAB8AB82D843BFEB14D2E47
> LinkKeyType=0
> LinkKeyPINLength=4
> Services=0x0000112400001000800000805F9B34FB;0x0000120000001000800000805F9B34FB;
>
> [40:B0:FA:39:FF:B8]
> Type=0
> Name=Nexus 4
> Class=5898764
> LinkKey=0x1E201EE8E82E1E50682622077D372F20
> LinkKeyType=5
> LinkKeyPINLength=0
> Services=0x0000180100001000800000805F9B34FB;0x0000180000001000800000805F9B34FB;0x0000111200001000800000805F9B34FB;0x0000111F00001000800000805F9B34FB;0x0000110C00001000800000805F9B34FB;0x0000110A00001000800000805F9B34FB;0x0000110E00001000800000805F9B34FB;0x0000111600001000800000805F9B34FB;0x0000111500001000800000805F9B34FB;0x0000113200001000800000805F9B34FB;0x0000112F00001000800000805F9B34FB;0x0000110500001000800000805F9B34FB;
>
>
> Comments are welcome.

I think the only discussion we could have is if we want to store them as 1 file per remote device or all devices in one file. I am personally fine with this approach since it is a limited scope with Android anyway. Also upgrading to a more complex storage later is easily possible.

Regards

Marcel


2013-12-18 11:20:59

by Szymon Janc

[permalink] [raw]
Subject: [RFC 3/4] android/bluetooth: Add support for storing link keys

When new linkkey event is received store linkkey in devices info file.
Stored info includes linkkey, linkkey type and pin length.
---
android/bluetooth.c | 38 ++++++++++++++++++++++++++++++++++----
1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 69412dd..0ef6191 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -496,7 +496,37 @@ static void mgmt_dev_class_changed_event(uint16_t index, uint16_t length,
static void store_link_key(const bdaddr_t *dst, const uint8_t *key,
uint8_t type, uint8_t pin_length)
{
- /* TODO store link key */
+ GKeyFile *key_file;
+ char key_str[35];
+ gsize length = 0;
+ char addr[18];
+ char *data;
+ int i;
+
+ key_file = g_key_file_new();
+
+ if (!g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices",
+ 0, NULL))
+ return;
+
+ ba2str(dst, addr);
+
+ DBG("%s type %u pin_len %u", addr, type, pin_length);
+
+ key_str[0] = '0';
+ key_str[1] = 'x';
+ for (i = 0; i < 16; i++)
+ sprintf(key_str + 2 + (i * 2), "%2.2X", key[i]);
+
+ g_key_file_set_string(key_file, addr, "LinkKey", key_str);
+ g_key_file_set_integer(key_file, addr, "LinkKeyType", type);
+ g_key_file_set_integer(key_file, addr, "LinkKeyPINLength", pin_length);
+
+ data = g_key_file_to_data(key_file, &length, NULL);
+ g_file_set_contents(ANDROID_STORAGEDIR"/devices", data, length, NULL);
+ g_free(data);
+
+ g_key_file_free(key_file);
}

static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
@@ -723,6 +753,9 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
return;
}

+ set_device_bond_state(&addr->bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_BONDED);
+
if (ev->store_hint) {
const struct mgmt_link_key_info *key = &ev->key;

@@ -730,9 +763,6 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
key->pin_len);
}

- set_device_bond_state(&addr->bdaddr, HAL_STATUS_SUCCESS,
- HAL_BOND_STATE_BONDED);
-
browse_remote_sdp(&addr->bdaddr);
}

--
1.8.3.2


2013-12-18 11:21:00

by Szymon Janc

[permalink] [raw]
Subject: [RFC 4/4] android/bluetooth: Add support for restoring devices from storage

This adds support to restore bonded devices from storage (including
linkkeys).
---
android/bluetooth.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 112 insertions(+), 1 deletion(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 0ef6191..d1fc9e4 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1581,6 +1581,117 @@ static void clear_uuids(void)
sizeof(cp), &cp, NULL, NULL, NULL);
}

+static void create_device_from_info(GKeyFile *key_file, const char *peer)
+{
+ struct device *dev;
+ uint8_t type;
+ bdaddr_t bdaddr;
+ char **uuids;
+ char *str;
+
+ DBG("%s", peer);
+
+ type = g_key_file_get_integer(key_file, peer, "Type", NULL);
+
+ str2ba(peer, &bdaddr);
+ dev = create_device(&bdaddr, type);
+
+ dev->bond_state = HAL_BOND_STATE_BONDED;
+
+ str = g_key_file_get_string(key_file, peer, "Name", NULL);
+ if (str) {
+ g_free(dev->name);
+ dev->name = str;
+ }
+
+ str = g_key_file_get_string(key_file, peer, "FriendlyName", NULL);
+ if (str) {
+ g_free(dev->friendly_name);
+ dev->friendly_name = str;
+ }
+
+ dev->class = g_key_file_get_integer(key_file, peer, "Class", NULL);
+
+ uuids = g_key_file_get_string_list(key_file, peer, "Services", NULL,
+ NULL);
+ if (uuids) {
+ char **uuid;
+
+ for (uuid = uuids; *uuid; uuid++) {
+ uint8_t *u = g_malloc0(16);
+ int i;
+
+ for (i = 0; i < 16; i++)
+ sscanf((*uuid) + 2 + (i * 2), "%02hhX", &u[i]);
+
+ dev->uuids = g_slist_append(dev->uuids, u);
+ }
+
+ g_strfreev(uuids);
+ }
+}
+
+static struct mgmt_link_key_info *get_key_info(GKeyFile *key_file, const char *peer)
+{
+ struct mgmt_link_key_info *info = NULL;
+ char *str;
+ unsigned int i;
+
+ str = g_key_file_get_string(key_file, peer, "LinkKey", NULL);
+ if (!str || strlen(str) != 34)
+ goto failed;
+
+ info = g_new0(struct mgmt_link_key_info, 1);
+
+ str2ba(peer, &info->addr.bdaddr);
+
+ info->addr.type = g_key_file_get_integer(key_file, peer, "Type", NULL);
+
+ for (i = 0; i < sizeof(info->val); i++)
+ sscanf(str + 2 + (i * 2), "%02hhX", &info->val[i]);
+
+ info->type = g_key_file_get_integer(key_file, peer, "LinkKeyType",
+ NULL);
+ info->pin_len = g_key_file_get_integer(key_file, peer,
+ "LinkKeyPINLength", NULL);
+
+failed:
+ g_free(str);
+
+ return info;
+}
+
+static void load_devices_info(bt_bluetooth_ready cb)
+{
+ GKeyFile *key_file;
+ gchar **devs;
+ gsize len = 0;
+ unsigned int i;
+ GSList *keys = NULL;
+
+ key_file = g_key_file_new();
+
+ g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices", 0,
+ NULL);
+
+ devs = g_key_file_get_groups(key_file, &len);
+
+ for (i = 0; i < len; i++) {
+ struct mgmt_link_key_info *key_info;
+
+ create_device_from_info(key_file, devs[i]);
+
+ key_info = get_key_info(key_file, devs[i]);
+ if (key_info)
+ keys = g_slist_prepend(keys, key_info);
+
+ /* TODO ltk */
+ }
+
+ load_link_keys(keys, cb);
+ g_slist_free_full(keys, g_free);
+}
+
static void read_info_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
@@ -1635,7 +1746,7 @@ static void read_info_complete(uint8_t status, uint16_t length,

clear_uuids();

- load_link_keys(NULL, cb);
+ load_devices_info(cb);

set_io_capability();
set_device_id();
--
1.8.3.2


2013-12-18 11:20:58

by Szymon Janc

[permalink] [raw]
Subject: [RFC 2/4] android/bluetooth: Add initial support for storing device info

This allows to store information about remote device. For now this is
stored only for bonded devices. Currently stored data includes devices
ddress, type, name, friendly name, class and uuids.
---
android/bluetooth.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 114a466..69412dd 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -196,6 +196,72 @@ static void load_adapter_config(void)
g_key_file_free(key_file);
}

+static void store_device_info(struct device *dev)
+{
+ GKeyFile *key_file;
+ char addr[18];
+ gsize length = 0;
+ char **uuids = NULL;
+ char *str;
+
+ if (dev->bond_state != HAL_BOND_STATE_BONDED)
+ return;
+
+ ba2str(&dev->bdaddr, addr);
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices", 0,
+ NULL);
+
+ g_key_file_set_integer(key_file, addr, "Type", dev->bdaddr_type);
+
+ g_key_file_set_string(key_file, addr, "Name", dev->name);
+
+ if (dev->friendly_name)
+ g_key_file_set_string(key_file, addr, "FriendlyName",
+ dev->friendly_name);
+ else
+ g_key_file_remove_key(key_file, addr, "FriendlyName", NULL);
+
+ if (dev->class)
+ g_key_file_set_integer(key_file, addr, "Class", dev->class);
+ else
+ g_key_file_remove_key(key_file, addr, "Class", NULL);
+
+ if (dev->uuids) {
+ GSList *l;
+ int i;
+
+ uuids = g_new0(char *, g_slist_length(dev->uuids) + 1);
+
+ for (i = 0, l = dev->uuids; l; l = g_slist_next(l), i++) {
+ int j;
+ uint8_t *u = l->data;
+ char *uuid_str = g_malloc0(35);
+
+ uuid_str[0] = '0';
+ uuid_str[1] = 'x';
+
+ for (j = 0; j < 16; j++)
+ sprintf(uuid_str + 2 + (j * 2), "%2.2X", u[j]);
+
+ uuids[i] = uuid_str;
+ }
+
+ g_key_file_set_string_list(key_file, addr, "Services",
+ (const char **)uuids, i);
+ } else {
+ g_key_file_remove_key(key_file, addr, "Services", NULL);
+ }
+
+ str = g_key_file_to_data(key_file, &length, NULL);
+ g_file_set_contents(ANDROID_STORAGEDIR"/devices", str, length, NULL);
+ g_free(str);
+
+ g_key_file_free(key_file);
+ g_strfreev(uuids);
+}
+
static int bdaddr_cmp(gconstpointer a, gconstpointer b)
{
const bdaddr_t *bda = a;
@@ -458,6 +524,8 @@ static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
if (dev->bond_state != state) {
dev->bond_state = state;
send_bond_state_change(&dev->bdaddr, status, state);
+
+ store_device_info(dev);
}
}

@@ -498,6 +566,8 @@ static void set_device_uuids(struct device *dev, GSList *uuids)
g_slist_free_full(dev->uuids, g_free);
dev->uuids = uuids;

+ store_device_info(dev);
+
send_device_uuids_notif(dev);
}

@@ -2539,7 +2609,7 @@ static uint8_t set_device_friendly_name(struct device *dev, const uint8_t *val,
g_free(dev->friendly_name);
dev->friendly_name = g_strndup((const char *) val, len);

- /* TODO store friendly name */
+ store_device_info(dev);

send_device_property(&dev->bdaddr, HAL_PROP_DEVICE_FRIENDLY_NAME,
strlen(dev->friendly_name), dev->friendly_name);
--
1.8.3.2


2013-12-18 11:20:57

by Szymon Janc

[permalink] [raw]
Subject: [RFC 1/4] android/bluetooth: Add initial support for permanent storage

This patch adds initial support for storing adapter configuration.
Currently stored data is address, name and discoverable timeout.

Since Android daemon storage format is to be simpler than Linux check
if correct adapter is used before going operational. This is
a precaution to avoid e.g. using linkkeys generated for different
controller.
---
android/Android.mk | 3 +-
android/bluetooth.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++---
configure.ac | 3 ++
3 files changed, 95 insertions(+), 6 deletions(-)

diff --git a/android/Android.mk b/android/Android.mk
index ebc3219..1411092 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -8,7 +8,8 @@ pathmap_INCL += glib:external/bluetooth/glib

# Specify common compiler flags
BLUEZ_COMMON_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\" \
- -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
+ -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) \
+ -DANDROID_STORAGEDIR=\"/data/misc/bluez\" \

# Disable warnings enabled by Android but not enabled in autotools build
BLUEZ_COMMON_CFLAGS += -Wno-pointer-arith -Wno-missing-field-initializers
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 97d4aae..114a466 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -27,6 +27,10 @@

#include <errno.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>

#include <glib.h>

@@ -123,6 +127,75 @@ static GSList *devices = NULL;
/* This list contains addresses which are asked for records */
static GSList *browse_reqs;

+static void store_adapter_config(void)
+{
+ GKeyFile *key_file;
+ gsize length = 0;
+ char addr[18];
+ char *data;
+
+ key_file = g_key_file_new();
+
+ if (!g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/settings",
+ 0, NULL)) {
+ int fd = open(ANDROID_STORAGEDIR"/settings", O_CREAT, 0600);
+ if (fd < 0) {
+ error("Failed to create adapter config file: %d (%s)",
+ errno, strerror(errno));
+ return;
+ }
+
+ close(fd);
+ }
+
+ ba2str(&adapter.bdaddr, addr);
+
+ g_key_file_set_string(key_file, "General", "Address", addr);
+ g_key_file_set_string(key_file, "General", "Name", adapter.name);
+ g_key_file_set_integer(key_file, "General", "DiscoverableTimeout",
+ adapter.discoverable_timeout);
+
+ data = g_key_file_to_data(key_file, &length, NULL);
+
+ g_file_set_contents(ANDROID_STORAGEDIR"/settings", data, length, NULL);
+
+ g_free(data);
+ g_key_file_free(key_file);
+}
+
+static void load_adapter_config(void)
+{
+ GError *gerr = NULL;
+ GKeyFile *key_file;
+ char *str;
+
+ key_file = g_key_file_new();
+
+ g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/settings", 0,
+ NULL);
+
+ str = g_key_file_get_string(key_file, "General", "Address", NULL);
+ if (!str) {
+ g_key_file_free(key_file);
+ return;
+ }
+
+ str2ba(str, &adapter.bdaddr);
+ g_free(str);
+
+ adapter.name = g_key_file_get_string(key_file, "General", "Name", NULL);
+
+ adapter.discoverable_timeout = g_key_file_get_integer(key_file,
+ "General", "DiscoverableTimeout", &gerr);
+ if (gerr) {
+ adapter.discoverable_timeout = DEFAULT_DISCOVERABLE_TIMEOUT;
+ g_error_free(gerr);
+ gerr = NULL;
+ }
+
+ g_key_file_free(key_file);
+}
+
static int bdaddr_cmp(gconstpointer a, gconstpointer b)
{
const bdaddr_t *bda = a;
@@ -215,6 +288,8 @@ static void adapter_set_name(const uint8_t *name)
g_free(adapter.name);
adapter.name = g_strdup((const char *) name);

+ store_adapter_config();
+
adapter_name_changed(name);
}

@@ -1385,9 +1460,10 @@ static uint8_t set_adapter_discoverable_timeout(const void *buf, uint16_t len)
* There is no need to use kernel feature for that.
* Just need to store this value here */

- /* TODO: This should be in some storage */
memcpy(&adapter.discoverable_timeout, timeout, sizeof(uint32_t));

+ store_adapter_config();
+
send_adapter_property(HAL_PROP_ADAPTER_DISC_TIMEOUT,
sizeof(adapter.discoverable_timeout),
&adapter.discoverable_timeout);
@@ -1434,17 +1510,26 @@ static void read_info_complete(uint8_t status, uint16_t length,
goto failed;
}

+ load_adapter_config();
+
+ if (!bacmp(&adapter.bdaddr, BDADDR_ANY)) {
+ bacpy(&adapter.bdaddr, &rp->bdaddr);
+ adapter.name = g_strdup((const char *) rp->name);
+ store_adapter_config();
+ set_adapter_name(rp->name, strlen((char *)rp->name));
+ } else if (bacmp(&adapter.bdaddr, &rp->bdaddr)) {
+ error("Bluetooth address mismatch");
+ err = -ENODEV;
+ goto failed;
+ }
+
/* Store adapter information */
- bacpy(&adapter.bdaddr, &rp->bdaddr);
adapter.dev_class = rp->dev_class[0] | (rp->dev_class[1] << 8) |
(rp->dev_class[2] << 16);
- adapter.name = g_strdup((const char *) rp->name);

supported_settings = btohs(rp->supported_settings);
adapter.current_settings = btohs(rp->current_settings);

- /* TODO: Read discoverable timeout from storage here */
-
/* TODO: Register all event notification handlers */
register_mgmt_handlers();

diff --git a/configure.ac b/configure.ac
index 18d0b55..5171c38 100644
--- a/configure.ac
+++ b/configure.ac
@@ -252,4 +252,7 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
[enable_android=${enableval}])
AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")

+AC_DEFINE_UNQUOTED(ANDROID_STORAGEDIR, "${storagedir}/android",
+ [Directory for the Android daemon storage files])
+
AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
--
1.8.3.2