I'm trying to chase some ANRs without any stack traces. I'm at a point where I just want to review every part of my code that uses the UI thread heavily.
Is there a way to graph this or do some sort of trace to see which methods took the longest without me modifying a ton of code?
First thing you can do is enable StrictMode. That will detect non-UI, potentially long operations running on the main thread.
Second thing you can do is profile the CPU, as stated above. You'll be able to see the activity per thread, so you can determine what is running where. In order to get accurate readings, don't run it from Android Studio. Run it directly from your code. The easiest way to do that is to use the Debug class, and start the sampling at the Application.onCreate && finish it when the app closes.
The third thing you can do is to observe the messages sent to the main thread looper and evaluate them. Pierre-Yves Ricau has a nice guide about this that you can adapt to your own processes.
After that, you can use custom approaches to evaluate critical parts of your code, like generating your own traces. Perfetto uses JSON files, so you can print logcat messages from the parts you suspect are causing trouble and parse those messages into a perfetto trace.