diff --git a/src/admin_policy.c b/src/admin_policy.c
index eeae2722cc0a..6498dcf05319 100644
--- a/src/admin_policy.c
+++ b/src/admin_policy.c
@@ -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);
diff --git a/src/device.c b/src/device.c
index 2192346d5f8d..aa54f00441c1 100644
--- a/src/device.c
+++ b/src/device.c
@@ -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},
 	{ }
 };
 
diff --git a/src/device.h b/src/device.h
index 3ca4f2c56566..a24ae088b68e 100644
--- a/src/device.h
+++ b/src/device.h
@@ -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);
