I think you could also use Camera2Interop's
setSessionCaptureCallback to receive the preview CaptureResult objects in
onCaptureCompleted, which include a timestamp for
start of exposure.
Then you can calculate the time between starts of exposure to get the current frame duration and thus the frame rate. Note that this is a bit tricky because when exposure time changes, the time between exposure starts isn't equal to the frame duration, so ideally you'd also include the
exposure time in the calculation (but that's not available on every device):
frame_duration = (frame[N+1].timestamp + frame[N+1].exposureTime) - (frame[N].timestamp + frame[N].exposureTime)
fps = 1/ frame_duration
You can also just look at the frame duration field when the device supports listing that, but the timestamp is always available.