diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index 6f0601dde401613677a155459d4d416aedee500b..8507b4ed8caa143c40535e5b5ce342a50ef245c5 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -1502,6 +1502,19 @@
                            ; Time Asterisk should wait, in milliseconds,
                            ; before sending notifications.
 
+;resource_display_name=no  ; Indicates whether display name of resource
+                           ; or the resource name being reported.
+                           ; If this option is enabled, the Display Name
+                           ; will be reported as resource name.
+                           ; If the event set to presence or dialog,
+                           ; the HINT name will be set as the Display Name.
+                           ; For example:
+                           ;  exten => 1234,hint,PJSIP/user1234(Alice)
+                           ; If enabled the resource name will be 'Alice'.
+                           ; If disabled the resource name will be '1234'.
+                           ; The message-summary is not supported yet.
+
+
 ;==========================INBOUND_PUBLICATION================================
 ; See https://wiki.asterisk.org/wiki/display/AST/Exchanging+Device+and+Mailbox+State+Using+PJSIP
 ; for more information.
diff --git a/contrib/ast-db-manage/config/versions/8f72185e437f_res_pjsip_pubsub_add_resource_list_.py b/contrib/ast-db-manage/config/versions/8f72185e437f_res_pjsip_pubsub_add_resource_list_.py
new file mode 100644
index 0000000000000000000000000000000000000000..8af67bfc20a1353ad97cc5ffe9741c6f9df10ebb
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/8f72185e437f_res_pjsip_pubsub_add_resource_list_.py
@@ -0,0 +1,29 @@
+"""res_pjsip_pubsub add resource_list option resource_display_name
+
+Revision ID: 8f72185e437f
+Revises: a06d8f8462d9
+Create Date: 2022-02-01 10:53:55.875438
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '8f72185e437f'
+down_revision = 'a06d8f8462d9'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+AST_BOOL_NAME = 'ast_bool_values'
+AST_BOOL_VALUES = [ '0', '1',
+                    'off', 'on',
+                    'false', 'true',
+                    'no', 'yes' ]
+
+def upgrade():
+    ast_bool_values = ENUM(*AST_BOOL_VALUES, name=AST_BOOL_NAME, create_type=False)
+    op.add_column('ps_resource_list', sa.Column('resource_display_name', ast_bool_values))
+
+def downgrade():
+    op.drop_column('ps_resource_list', 'resource_display_name')
+
diff --git a/doc/CHANGES-staging/rls_display_name.txt b/doc/CHANGES-staging/rls_display_name.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0d95b08fa3e07fb6d867642259ffdc9ab7267904
--- /dev/null
+++ b/doc/CHANGES-staging/rls_display_name.txt
@@ -0,0 +1,10 @@
+Subject: res_pjsip_pubsub
+
+A new resource_list option, resource_display_name, indicates
+whether display name of resource or the resource name being
+provided for RLS entries.
+If this option is enabled, the Display Name will be provided.
+This option is disabled by default to remain the previous behavior.
+If the 'event' set to 'presence' or 'dialog' the non-empty HINT name
+will be set as the Display Name.
+The 'message-summary' is not supported yet.
diff --git a/include/asterisk/res_pjsip_pubsub.h b/include/asterisk/res_pjsip_pubsub.h
index 354b0b2506040adcd2d3bc3cb5bbe6999cc35a90..aca1141d851c5702ab0a220f1e3102f324661363 100644
--- a/include/asterisk/res_pjsip_pubsub.h
+++ b/include/asterisk/res_pjsip_pubsub.h
@@ -292,6 +292,17 @@ struct ast_sip_notifier {
 	 * \return An ao2 object that can be used to create a NOTIFY body.
 	 */
 	void *(*get_notify_data)(struct ast_sip_subscription *sub);
+	/*!
+	 * \brief Supply Display Name for resource
+	 *
+	 * \param endpoint The endpoint from which we received the SUBSCRIBE
+	 * \param resource The name of the resource to which the subscription is being made
+	 * \param display_name buffer for Display Name
+	 * \param display_name_size size of display_name buffer
+	 * \retval 0 Success
+	 * \retval -1 Failure
+	 */
+	int (*get_resource_display_name)(struct ast_sip_endpoint *endpoint, const char *resource, char *display_name, int display_name_size);
 };
 
 struct ast_sip_subscriber {
diff --git a/res/res_pjsip_exten_state.c b/res/res_pjsip_exten_state.c
index df9a35f3326b36a01703c900d939478dfbce71e8..b51df87b622287a2c12607d4933e33c7b8191c09 100644
--- a/res/res_pjsip_exten_state.c
+++ b/res/res_pjsip_exten_state.c
@@ -117,6 +117,7 @@ static void subscription_shutdown(struct ast_sip_subscription *sub);
 static int new_subscribe(struct ast_sip_endpoint *endpoint, const char *resource);
 static int subscription_established(struct ast_sip_subscription *sub);
 static void *get_notify_data(struct ast_sip_subscription *sub);
+static int get_resource_display_name(struct ast_sip_endpoint *endpoint, const char *resource, char *display_name, int display_name_size);
 static void to_ami(struct ast_sip_subscription *sub,
 		   struct ast_str **buf);
 static int publisher_start(struct ast_sip_outbound_publish *configuration,
@@ -128,6 +129,7 @@ struct ast_sip_notifier presence_notifier = {
 	.new_subscribe = new_subscribe,
 	.subscription_established = subscription_established,
 	.get_notify_data = get_notify_data,
+	.get_resource_display_name = get_resource_display_name,
 };
 
 struct ast_sip_notifier dialog_notifier = {
@@ -135,6 +137,7 @@ struct ast_sip_notifier dialog_notifier = {
 	.new_subscribe = new_subscribe,
 	.subscription_established = subscription_established,
 	.get_notify_data = get_notify_data,
+	.get_resource_display_name = get_resource_display_name,
 };
 
 struct ast_sip_subscription_handler presence_handler = {
@@ -424,6 +427,27 @@ static int new_subscribe(struct ast_sip_endpoint *endpoint,
 	return 200;
 }
 
+static int get_resource_display_name(struct ast_sip_endpoint *endpoint,
+		const char *resource, char *display_name, int display_name_size)
+{
+	const char *context;
+
+	if (!endpoint || ast_strlen_zero(resource) || !display_name || display_name_size <= 0) {
+		return -1;
+	}
+
+	context = S_OR(endpoint->subscription.context, endpoint->context);
+
+	if (!ast_get_hint(NULL, 0, display_name, display_name_size, NULL, context, resource)) {
+		ast_log(LOG_NOTICE, "Endpoint '%s': "
+			"Extension '%s' does not exist in context '%s' or has no associated hint\n",
+			ast_sorcery_object_get_id(endpoint), resource, context);
+		return -1;
+	}
+
+	return 0;
+}
+
 static int subscription_established(struct ast_sip_subscription *sip_sub)
 {
 	struct ast_sip_endpoint *endpoint = ast_sip_subscription_get_endpoint(sip_sub);
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 31394e28a8f647bd1265b19a85cbb1179970ed7e..60506db5c9ee1c34e5b4db1b8c1e0b226f2483b1 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -210,6 +210,15 @@
 						many notifications.</para>
 					</description>
 				</configOption>
+				<configOption name="resource_display_name" default="no">
+					<synopsis>Indicates whether display name of resource or the resource name being reported.</synopsis>
+					<description>
+						<para>If this option is enabled, the Display Name will be reported as resource name.
+						If the <replaceable>event</replaceable> set to <literal>presence</literal> or <literal>dialog</literal>,
+						the non-empty HINT name will be set as the Display Name.
+						The <literal>message-summary</literal> is not supported yet.</para>
+					</description>
+				</configOption>
 			</configObject>
 			<configObject name="inbound-publication">
 				<synopsis>The configuration for inbound publications</synopsis>
@@ -332,6 +341,8 @@ struct resource_list {
 	unsigned int full_state;
 	/*! Time, in milliseconds Asterisk waits before sending a batched notification.*/
 	unsigned int notification_batch_interval;
+	/*! Indicates whether display name of resource or the resource name being reported.*/
+	unsigned int resource_display_name;
 };
 
 /*!
@@ -499,6 +510,8 @@ struct ast_sip_subscription {
 	pjsip_sip_uri *uri;
 	/*! Data to be persisted with the subscription */
 	struct ast_json *persistence_data;
+	/*! Display Name of resource */
+	char *display_name;
 	/*! Name of resource being subscribed to */
 	char resource[0];
 };
@@ -886,6 +899,7 @@ struct resource_tree;
 struct tree_node {
 	AST_VECTOR(, struct tree_node *) children;
 	unsigned int full_state;
+	char *display_name;
 	char resource[0];
 };
 
@@ -929,7 +943,7 @@ static struct resource_list *retrieve_resource_list(const char *resource, const
  * \retval NULL Allocation failure.
  * \retval non-NULL The newly-allocated tree_node
  */
-static struct tree_node *tree_node_alloc(const char *resource, struct resources *visited, unsigned int full_state)
+static struct tree_node *tree_node_alloc(const char *resource, struct resources *visited, unsigned int full_state, const char *display_name)
 {
 	struct tree_node *node;
 
@@ -944,6 +958,7 @@ static struct tree_node *tree_node_alloc(const char *resource, struct resources
 		return NULL;
 	}
 	node->full_state = full_state;
+	node->display_name = ast_strdup(display_name);
 
 	if (visited) {
 		AST_VECTOR_APPEND(visited, resource);
@@ -971,6 +986,7 @@ static void tree_node_destroy(struct tree_node *node)
 		tree_node_destroy(AST_VECTOR_GET(&node->children, i));
 	}
 	AST_VECTOR_FREE(&node->children);
+	ast_free(node->display_name);
 	ast_free(node);
 }
 
@@ -1035,7 +1051,11 @@ static void build_node_children(struct ast_sip_endpoint *endpoint, const struct
 		if (!child_list) {
 			int resp = handler->notifier->new_subscribe(endpoint, resource);
 			if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
-				current = tree_node_alloc(resource, visited, 0);
+				char display_name[AST_MAX_EXTENSION] = "";
+				if (list->resource_display_name && handler->notifier->get_resource_display_name) {
+					handler->notifier->get_resource_display_name(endpoint, resource, display_name, sizeof(display_name));
+				}
+				current = tree_node_alloc(resource, visited, 0, ast_strlen_zero(display_name) ? NULL : display_name);
 				if (!current) {
 					ast_debug(1,
 						"Subscription to leaf resource %s was successful, but encountered allocation error afterwards\n",
@@ -1053,7 +1073,7 @@ static void build_node_children(struct ast_sip_endpoint *endpoint, const struct
 			}
 		} else {
 			ast_debug(2, "Resource %s (child of %s) is a list\n", resource, parent->resource);
-			current = tree_node_alloc(resource, visited, child_list->full_state);
+			current = tree_node_alloc(resource, visited, child_list->full_state, NULL);
 			if (!current) {
 				ast_debug(1, "Cannot build children of resource %s due to allocation failure\n", resource);
 				continue;
@@ -1139,7 +1159,7 @@ static int build_resource_tree(struct ast_sip_endpoint *endpoint, const struct a
 	if (!has_eventlist_support || !(list = retrieve_resource_list(resource, handler->event_name))) {
 		ast_debug(2, "Subscription '%s->%s' is not to a list\n",
 			ast_sorcery_object_get_id(endpoint), resource);
-		tree->root = tree_node_alloc(resource, NULL, 0);
+		tree->root = tree_node_alloc(resource, NULL, 0, NULL);
 		if (!tree->root) {
 			return 500;
 		}
@@ -1152,7 +1172,7 @@ static int build_resource_tree(struct ast_sip_endpoint *endpoint, const struct a
 		return 500;
 	}
 
-	tree->root = tree_node_alloc(resource, &visited, list->full_state);
+	tree->root = tree_node_alloc(resource, &visited, list->full_state, NULL);
 	if (!tree->root) {
 		AST_VECTOR_FREE(&visited);
 		return 500;
@@ -1207,6 +1227,7 @@ static void destroy_subscription(struct ast_sip_subscription *sub)
 	AST_VECTOR_FREE(&sub->children);
 	ao2_cleanup(sub->datastores);
 	ast_json_unref(sub->persistence_data);
+	ast_free(sub->display_name);
 	ast_free(sub);
 }
 
@@ -1229,7 +1250,7 @@ static void destroy_subscriptions(struct ast_sip_subscription *root)
 }
 
 static struct ast_sip_subscription *allocate_subscription(const struct ast_sip_subscription_handler *handler,
-		const char *resource, struct sip_subscription_tree *tree)
+		const char *resource, const char *display_name, struct sip_subscription_tree *tree)
 {
 	struct ast_sip_subscription *sub;
 	pjsip_sip_uri *contact_uri;
@@ -1240,6 +1261,8 @@ static struct ast_sip_subscription *allocate_subscription(const struct ast_sip_s
 	}
 	strcpy(sub->resource, resource); /* Safe */
 
+	sub->display_name = ast_strdup(display_name);
+
 	sub->datastores = ast_datastores_alloc();
 	if (!sub->datastores) {
 		destroy_subscription(sub);
@@ -1288,7 +1311,7 @@ static struct ast_sip_subscription *create_virtual_subscriptions(const struct as
 	int i;
 	struct ast_sip_subscription *sub;
 
-	sub = allocate_subscription(handler, resource, tree);
+	sub = allocate_subscription(handler, resource, current->display_name, tree);
 	if (!sub) {
 		return NULL;
 	}
@@ -1880,7 +1903,7 @@ struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_su
 		return NULL;
 	}
 
-	sub = allocate_subscription(handler, resource, sub_tree);
+	sub = allocate_subscription(handler, resource, NULL, sub_tree);
 	if (!sub) {
 		ao2_cleanup(sub_tree);
 		return NULL;
@@ -2088,6 +2111,8 @@ struct body_part {
 	pjsip_evsub_state state;
 	/*! The actual body part that will be present in the multipart body */
 	pjsip_multipart_part *part;
+	/*! Display name for the resource */
+	const char *display_name;
 };
 
 /*!
@@ -2186,7 +2211,7 @@ static pjsip_multipart_part *build_rlmi_body(pj_pool_t *pool, struct ast_sip_sub
 	for (i = 0; i < AST_VECTOR_SIZE(body_parts); ++i) {
 		const struct body_part *part = AST_VECTOR_GET(body_parts, i);
 
-		add_rlmi_resource(pool, rlmi, part->cid, part->resource, part->uri, part->state);
+		add_rlmi_resource(pool, rlmi, part->cid, S_OR(part->display_name, part->resource), part->uri, part->state);
 	}
 
 	rlmi_part = pjsip_multipart_create_part(pool);
@@ -2243,6 +2268,7 @@ static struct body_part *allocate_body_part(pj_pool_t *pool, const struct ast_si
 	bp->resource = sub->resource;
 	bp->state = sub->subscription_state;
 	bp->uri = sub->uri;
+	bp->display_name = sub->display_name;
 
 	return bp;
 }
@@ -4873,6 +4899,8 @@ static int apply_list_configuration(struct ast_sorcery *sorcery)
 			"0", OPT_UINT_T, 0, FLDSET(struct resource_list, notification_batch_interval));
 	ast_sorcery_object_field_register_custom(sorcery, "resource_list", "list_item",
 			"", list_item_handler, list_item_to_str, NULL, 0, 0);
+	ast_sorcery_object_field_register(sorcery, "resource_list", "resource_display_name", "no",
+			OPT_BOOL_T, 1, FLDSET(struct resource_list, resource_display_name));
 
 	ast_sorcery_reload_object(sorcery, "resource_list");