@@ -118,8 +118,13 @@ void btd_admin_policy_allowlist_set(struct btd_admin_policy *admin_policy,
*/
btd_profile_policy_update(admin_policy->adapter);
- /* Update auto-connect status to all devices */
+ /* Update auto-connect and IsBlockedByPolicy status to all devices */
btd_adapter_refresh_is_blocked_by_policy(admin_policy->adapter);
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ adapter_get_path(admin_policy->adapter),
+ ADMIN_POLICY_INTERFACE,
+ "ServiceAllowList");
}
static DBusMessage *set_service_allowlist(DBusConnection *conn,
@@ -201,6 +206,51 @@ static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)
return admin_policy;
}
+static void append_uuid_set(gpointer key, gpointer value, gpointer user_data)
+{
+ const bt_uuid_t *uuid = key;
+ DBusMessageIter *entry = user_data;
+ char uuid_str[MAX_LEN_UUID_STR];
+ const char *uuid_str_ptr = uuid_str;
+
+ bt_uuid_to_string(uuid, uuid_str, MAX_LEN_UUID_STR);
+ dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &uuid_str_ptr);
+}
+
+static gboolean
+property_get_service_allowlist(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct btd_admin_policy *admin_policy = user_data;
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &entry);
+
+ g_hash_table_foreach(admin_policy->allowed_uuid_set, append_uuid_set,
+ &entry);
+
+ dbus_message_iter_close_container(iter, &entry);
+
+ return TRUE;
+}
+
+static gboolean
+property_exists_service_allowlist(const GDBusPropertyTable *property,
+ void *user_data)
+{
+ struct btd_admin_policy *admin_policy = user_data;
+
+ return admin_policy->allowed_uuid_set != NULL ? TRUE : FALSE;
+}
+
+static const GDBusPropertyTable admin_policy_properties[] = {
+ {"ServiceAllowList", "as", property_get_service_allowlist, NULL,
+ property_exists_service_allowlist,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL},
+ { }
+};
+
struct btd_admin_policy *btd_admin_policy_create(struct btd_adapter *adapter)
{
struct btd_admin_policy *admin_policy;
@@ -212,8 +262,9 @@ struct btd_admin_policy *btd_admin_policy_create(struct btd_adapter *adapter)
if (!g_dbus_register_interface(btd_get_dbus_connection(),
adapter_get_path(admin_policy->adapter),
ADMIN_POLICY_INTERFACE,
- admin_policy_methods, NULL, NULL,
- admin_policy, NULL)) {
+ admin_policy_methods, NULL,
+ admin_policy_properties, admin_policy,
+ NULL)) {
btd_error(admin_policy->adapter_id,
"Failed to register "
ADMIN_POLICY_INTERFACE);
@@ -265,6 +265,7 @@ struct btd_device {
gboolean auto_connect;
gboolean disable_auto_connect;
gboolean general_connect;
+ gboolean is_blocked_by_policy;
bool legacy;
int8_t rssi;
@@ -1470,6 +1471,18 @@ static gboolean dev_property_wake_allowed_exist(
return device_get_wake_support(device);
}
+static gboolean
+dev_property_get_is_blocked_by_policy(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *device = data;
+ dbus_bool_t is_blocked = device->is_blocked_by_policy;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &is_blocked);
+
+ return TRUE;
+}
+
static bool disconnect_all(gpointer user_data)
{
struct btd_device *device = user_data;
@@ -1929,6 +1942,16 @@ static int service_prio_cmp(gconstpointer a, gconstpointer b)
return p2->priority - p1->priority;
}
+static void refresh_is_blocked_by_policy(struct btd_device *dev, bool value)
+{
+ if (value == dev->is_blocked_by_policy)
+ return;
+
+ dev->is_blocked_by_policy = value;
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
+ DEVICE_INTERFACE, "IsBlockedByPolicy");
+}
+
void btd_device_update_is_blocked_by_policy(struct btd_device *dev)
{
struct btd_adapter *adapter = dev->adapter;
@@ -1936,6 +1959,7 @@ void btd_device_update_is_blocked_by_policy(struct btd_device *dev)
struct btd_profile *profile;
GSList *l;
bool auto_connect = false;
+ bool is_blocked = false;
/* If service discover is ongoing, let the service discover complete
* callback call this function.
@@ -1950,13 +1974,16 @@ void btd_device_update_is_blocked_by_policy(struct btd_device *dev)
if (!profile->auto_connect)
continue;
- if (profile->accept &&
- !btd_service_is_blocked_by_policy(service))
+ if (btd_service_is_blocked_by_policy(service))
+ is_blocked = true;
+ else if (profile->accept)
auto_connect = true;
}
if (!dev->disable_auto_connect)
device_set_auto_connect(dev, auto_connect);
+
+ refresh_is_blocked_by_policy(dev, is_blocked);
}
static GSList *create_pending_list(struct btd_device *dev, const char *uuid)
@@ -2994,6 +3021,7 @@ static const GDBusPropertyTable device_properties[] = {
{ "WakeAllowed", "b", dev_property_get_wake_allowed,
dev_property_set_wake_allowed,
dev_property_wake_allowed_exist },
+ { "IsBlockedByPolicy", "b", dev_property_get_is_blocked_by_policy},
{ }
};
@@ -74,6 +74,7 @@ void device_set_service_data(struct btd_device *dev, GSList *list,
bool duplicate);
void device_set_data(struct btd_device *dev, GSList *list,
bool duplicate);
+void btd_device_update_is_blocked_by_policy(struct btd_device *dev);
void device_probe_profile(gpointer a, gpointer b);
void device_remove_profile(gpointer a, gpointer b);
struct btd_adapter *device_get_adapter(struct btd_device *device);
This adds IsBlockedByPolicy to indicate if the remote device is currently blocked by policy. ServiceAllowlist is also introduced to indicate the current service allowlist. Reviewed-by: Miao-chen Chou <mcchou@chromium.org> --- src/admin_policy.c | 57 +++++++++++++++++++++++++++++++++++++++++++--- src/device.c | 32 ++++++++++++++++++++++++-- src/device.h | 1 + 3 files changed, 85 insertions(+), 5 deletions(-)