Media session has "no title" on AOD (Always on display)

I just answer my own question because I have found and solved the problem.

I have only set the notification's media description adapter, but in fact, the media session needs to set metadata too. Since we are using mediaSessionConnector, it can be setup by passing a QueueNavigator to the mediaSessionConnector, so we can use the player instance and window index to build current media's metadata. e.x:

    val timelineQueueNavigator = object : TimelineQueueNavigator(mediaSession) {
        override fun getMediaDescription(player: Player?, windowIndex: Int): MediaDescriptionCompat {
            player?.let { safePlayer ->
                return MediaDescriptionCompat.Builder().apply {
                    setTitle("......")
                    setSubtitle("......")
                }.build()
            }
            return MediaDescriptionCompat.Builder().build()
        }
    }
    mediaSessionConnector.setQueueNavigator(timelineQueueNavigator)

Another point is, by default the mediaSessionConnector use MediaSessionConnector.DefaultMediaMetadataProvider. It doesn't setup METADATA_KEY_ARTIST which will be used in AOD mode as the artist. So I have created my own MediaMetadataProvider, adding METADATA_KEY_ARTIST.

if (description.subtitle != null) {
    val subTitle = description.subtitle.toString()
    builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, subTitle)
    builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, subTitle)
}