Receiving a ping from Firebase Cloud Messaging triggers the app to whatever it does in order to display its notification. In the case of Signal, that probably means something like fetching the user's latest messages from the server, then deciding what to show in the notification based on the user's settings, metadata, and message content.
Here's example code for using FCM to show a notification. In this case, the notification content also passes through FCM, but Signal does not do that. https://www.geeksforgeeks.org/android/how-to-push-notificati...
Looks like there is a way to bypass Firebase by using something like UnifiedPush which runs a perpetual background process that acts similar to Google Play Services to pick up notifications from the server and calls the local notification API.
That's unreliable though since some OEM Android builds will kill it for that even if the user disables battery optimizations. Those OEMs sort of have a point; if lots of apps did that it would drain the battery fast.
This is more of a fundamental technical limitation of operating systems and networks; I don't think it is possible to design distributed communication between arbitrary service provider infrastructure and end-user devices without an always-online intermediary reachable from anywhere (a bouncer, in IRC terms) that accepts messages for non-present consumers.
The flip side of the coin: any possibly avenue to exfiltrate data and do (advertising) tracking by app developers will be used. The restrictions also protect my privacy.
And my phone battery.
I’ll note that whatever other reasons it’s also the only way to make this battery efficient. Having a bunch of different TCP connections signaling events at random times is not what you want.
Ideally the app also is responsible for rendering rather than having to disclose the message but that can be challenging to accomplish for all sorts of reasons).
Except you need an entitlement for that, because it requires that your app has the ability to receive a notification without actually showing it (Apple checks this).
Your app gets woken up, decrypts the message, and then shows a local notification.