diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 3cca9c6b6e7b03a35d176b3dd55f8a1bacc593ca..11acdffe16ea2c2c76ac11a26e2feba0d7c196d5 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -219,10 +219,13 @@ static void chan_pjsip_get_codec(struct ast_channel *chan, struct ast_format_cap
 
 static int send_direct_media_request(void *data)
 {
-	RAII_VAR(struct ast_sip_session *, session, data, ao2_cleanup);
+	struct ast_sip_session *session = data;
+	int res;
 
-	return ast_sip_session_refresh(session, NULL, NULL, NULL,
-			session->endpoint->media.direct_media.method, 1);
+	res = ast_sip_session_refresh(session, NULL, NULL, NULL,
+		session->endpoint->media.direct_media.method, 1);
+	ao2_ref(session, -1);
+	return res;
 }
 
 /*! \brief Destructor function for \ref transport_info_data */
@@ -1057,17 +1060,66 @@ static int transmit_info_with_vidupdate(void *data)
 	return 0;
 }
 
+/*!
+ * \internal
+ * \brief TRUE if a COLP update can be sent to the peer.
+ * \since 13.3.0
+ *
+ * \param session The session to see if the COLP update is allowed.
+ *
+ * \retval 0 Update is not allowed.
+ * \retval 1 Update is allowed.
+ */
+static int is_colp_update_allowed(struct ast_sip_session *session)
+{
+	struct ast_party_id connected_id;
+	int update_allowed = 0;
+
+	if (!session->endpoint->id.send_pai && !session->endpoint->id.send_rpid) {
+		return 0;
+	}
+
+	/*
+	 * Check if privacy allows the update.  Check while the channel
+	 * is locked so we can work with the shallow connected_id copy.
+	 */
+	ast_channel_lock(session->channel);
+	connected_id = ast_channel_connected_effective_id(session->channel);
+	if (connected_id.number.valid
+		&& (session->endpoint->id.trust_outbound
+			|| (ast_party_id_presentation(&connected_id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED)) {
+		update_allowed = 1;
+	}
+	ast_channel_unlock(session->channel);
+
+	return update_allowed;
+}
+
 /*! \brief Update connected line information */
 static int update_connected_line_information(void *data)
 {
-	RAII_VAR(struct ast_sip_session *, session, data, ao2_cleanup);
+	struct ast_sip_session *session = data;
 
-	if ((ast_channel_state(session->channel) != AST_STATE_UP) && (session->inv_session->role == PJSIP_UAS_ROLE)) {
-		int response_code = 0;
+	if (ast_channel_state(session->channel) == AST_STATE_UP
+		|| session->inv_session->role == PJSIP_ROLE_UAC) {
+		if (is_colp_update_allowed(session)) {
+			enum ast_sip_session_refresh_method method;
+			int generate_new_sdp;
 
-		if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
-			return 0;
+			method = session->endpoint->id.refresh_method;
+			if (session->inv_session->invite_tsx
+				&& (session->inv_session->options & PJSIP_INV_SUPPORT_UPDATE)) {
+				method = AST_SIP_SESSION_REFRESH_METHOD_UPDATE;
+			}
+
+			/* Only the INVITE method actually needs SDP, UPDATE can do without */
+			generate_new_sdp = (method == AST_SIP_SESSION_REFRESH_METHOD_INVITE);
+
+			ast_sip_session_refresh(session, NULL, NULL, NULL, method, generate_new_sdp);
 		}
+	} else if (session->inv_session->state != PJSIP_INV_STATE_DISCONNECTED
+		&& is_colp_update_allowed(session)) {
+		int response_code = 0;
 
 		if (ast_channel_state(session->channel) == AST_STATE_RING) {
 			response_code = !session->endpoint->inband_progress ? 180 : 183;
@@ -1082,34 +1134,9 @@ static int update_connected_line_information(void *data)
 				ast_sip_session_send_response(session, packet);
 			}
 		}
-	} else {
-		enum ast_sip_session_refresh_method method = session->endpoint->id.refresh_method;
-		int generate_new_sdp;
-		struct ast_party_id connected_id;
-
-		if (session->inv_session->invite_tsx && (session->inv_session->options & PJSIP_INV_SUPPORT_UPDATE)) {
-			method = AST_SIP_SESSION_REFRESH_METHOD_UPDATE;
-		}
-
-		/* Only the INVITE method actually needs SDP, UPDATE can do without */
-		generate_new_sdp = (method == AST_SIP_SESSION_REFRESH_METHOD_INVITE);
-
-		/*
-		 * We can get away with a shallow copy here because we are
-		 * not looking at strings.
-		 */
-		ast_channel_lock(session->channel);
-		connected_id = ast_channel_connected_effective_id(session->channel);
-		ast_channel_unlock(session->channel);
-
-		if ((session->endpoint->id.send_pai || session->endpoint->id.send_rpid) &&
-		    (session->endpoint->id.trust_outbound ||
-		     ((connected_id.name.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED &&
-		      (connected_id.number.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED))) {
-			ast_sip_session_refresh(session, NULL, NULL, NULL, method, generate_new_sdp);
-		}
 	}
 
+	ao2_ref(session, -1);
 	return 0;
 }
 
diff --git a/res/res_pjsip_caller_id.c b/res/res_pjsip_caller_id.c
index dc595c4d8bc355b1406482ea8527cf0f273da8c7..63ef1f4d41cb40fa2872e251e5c03aa00950bf7b 100644
--- a/res/res_pjsip_caller_id.c
+++ b/res/res_pjsip_caller_id.c
@@ -131,12 +131,12 @@ static int set_id_from_pai(pjsip_rx_data *rdata, struct ast_party_id *id)
 	}
 
 	privacy = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &privacy_str, NULL);
-	if (!privacy) {
-		return 0;
-	}
-	if (!pj_stricmp2(&privacy->hvalue, "id")) {
+	if (privacy && !pj_stricmp2(&privacy->hvalue, "id")) {
 		id->number.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
 		id->name.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+	} else {
+		id->number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+		id->name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
 	}
 
 	return 0;
@@ -176,12 +176,18 @@ static int set_id_from_rpid(pjsip_rx_data *rdata, struct ast_party_id *id)
 	privacy = pjsip_param_find(&rpid_hdr->other_param, &privacy_str);
 	screen = pjsip_param_find(&rpid_hdr->other_param, &screen_str);
 	if (privacy && !pj_stricmp2(&privacy->value, "full")) {
-		id->number.presentation |= AST_PRES_RESTRICTED;
-		id->name.presentation |= AST_PRES_RESTRICTED;
+		id->number.presentation = AST_PRES_RESTRICTED;
+		id->name.presentation = AST_PRES_RESTRICTED;
+	} else {
+		id->number.presentation = AST_PRES_ALLOWED;
+		id->name.presentation = AST_PRES_ALLOWED;
 	}
 	if (screen && !pj_stricmp2(&screen->value, "yes")) {
 		id->number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
 		id->name.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
+	} else {
+		id->number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
+		id->name.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
 	}
 
 	return 0;
@@ -475,8 +481,7 @@ static void add_privacy_header(pjsip_tx_data *tdata, const struct ast_party_id *
 
 	old_privacy = pjsip_msg_find_hdr_by_name(tdata->msg, &pj_privacy_name, NULL);
 
-	if ((id->name.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED &&
-			(id->number.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
+	if ((ast_party_id_presentation(id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
 		if (old_privacy) {
 			pj_list_erase(old_privacy);
 		}
@@ -499,10 +504,6 @@ static void add_pai_header(pjsip_tx_data *tdata, const struct ast_party_id *id)
 	pjsip_fromto_hdr *pai_hdr;
 	pjsip_fromto_hdr *old_pai;
 
-	if (!id->number.valid) {
-		return;
-	}
-
 	/* Since inv_session reuses responses, we have to make sure there's not already
 	 * a P-Asserted-Identity present. If there is, we just modify the old one.
 	 */
@@ -546,6 +547,7 @@ static void add_privacy_params(pjsip_tx_data *tdata, pjsip_fromto_hdr *hdr, cons
 	pjsip_param *old_screen;
 	pjsip_param *privacy;
 	pjsip_param *screen;
+	int presentation;
 
 	old_privacy = pjsip_param_find(&hdr->other_param, &privacy_str);
 	old_screen = pjsip_param_find(&hdr->other_param, &screen_str);
@@ -566,15 +568,13 @@ static void add_privacy_params(pjsip_tx_data *tdata, pjsip_fromto_hdr *hdr, cons
 		screen = old_screen;
 	}
 
-	if ((id->name.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED &&
-			(id->name.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
+	presentation = ast_party_id_presentation(id);
+	if ((presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
 		privacy->value = privacy_off_str;
 	} else {
 		privacy->value = privacy_full_str;
 	}
-
-	if ((id->name.presentation & AST_PRES_NUMBER_TYPE) == AST_PRES_USER_NUMBER_PASSED_SCREEN &&
-			(id->number.presentation & AST_PRES_NUMBER_TYPE) == AST_PRES_USER_NUMBER_PASSED_SCREEN) {
+	if ((presentation & AST_PRES_NUMBER_TYPE) == AST_PRES_USER_NUMBER_PASSED_SCREEN) {
 		screen->value = screen_yes_str;
 	} else {
 		screen->value = screen_no_str;
@@ -593,10 +593,6 @@ static void add_rpid_header(pjsip_tx_data *tdata, const struct ast_party_id *id)
 	pjsip_fromto_hdr *rpid_hdr;
 	pjsip_fromto_hdr *old_rpid;
 
-	if (!id->number.valid) {
-		return;
-	}
-
 	/* Since inv_session reuses responses, we have to make sure there's not already
 	 * a P-Asserted-Identity present. If there is, we just modify the old one.
 	 */
@@ -628,9 +624,9 @@ static void add_rpid_header(pjsip_tx_data *tdata, const struct ast_party_id *id)
  */
 static void add_id_headers(const struct ast_sip_session *session, pjsip_tx_data *tdata, const struct ast_party_id *id)
 {
-	if (((id->name.presentation & AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED ||
-			(id->number.presentation & AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED) &&
-			!session->endpoint->id.trust_outbound) {
+	if (!id->number.valid
+		|| (!session->endpoint->id.trust_outbound
+			&& (ast_party_id_presentation(id) & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)) {
 		return;
 	}
 	if (session->endpoint->id.send_pai) {
@@ -679,10 +675,9 @@ static void caller_id_outgoing_request(struct ast_sip_session *session, pjsip_tx
 		from = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_FROM, tdata->msg->hdr.next);
 		dlg = session->inv_session->dlg;
 
-		if (ast_strlen_zero(session->endpoint->fromuser) &&
-			(session->endpoint->id.trust_outbound ||
-			((connected_id.name.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED &&
-			(connected_id.number.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED))) {
+		if (ast_strlen_zero(session->endpoint->fromuser)
+			&& (session->endpoint->id.trust_outbound
+				|| (ast_party_id_presentation(&connected_id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED)) {
 			modify_id_header(tdata->pool, from, &connected_id);
 			modify_id_header(dlg->pool, dlg->local.info, &connected_id);
 		}