I'm using a 3rd party drawer that allows bottom- and top-edge drawers (https://gist.github.com/patrickfav/6284130 MultipleOrientationSlidingDrawer).
When I animate opening of the drawer, I get display tearing but only under particular circumstances. When the drawer header is clicked, animation is smooth and beautiful.
I have a RecyclerView in the main window. If users click on an entry in the list view, the drawer slides open showing details of the entry selected (click on a track, slide the media controls up from the bottom). Part of the drawer animation is to fade the main window contents to black as the drawer opens. So there's heavy overdraw going on. Oddly, when the animation is triggered from clicking in the RecyclerView, I get tearing of the display during animation (serious flickering, occurring about 2/3 of the way down from the top of the screen).
I'm looking for advice as to how to proceed: how to debug, or theories as to what might be causing flickering of the display during animation.
Here's what I've tried so far.
Initially, I though this was caused by RippleDrawable animations in the RecyclerView entries (both on the press and an activition change that is used to indicate selection. To prevent this, I've tried to cancel the ripple animations by calling recylerView.jumpDrawablesToCurrentState() at various points (start of animation, as well as during every animation update). As far as I can tell, the RippleDrawable animations have been effectively cancelled. But the display ripping still occurs. Things are a bit complicated. State change animations don't get triggered until after a dispatch of some kind occurs; but the call to startAnimation also doesn't appear to occur until after drawable state changes are complete. So I think I've done this right. Just in case, I've tried calling recyclerView.jumpDrawablesToCurrentState during each animation pass, which certinly should cancel the drawable animations. Still no joy.
I have deferred responses to the click itself until the drawer open animation completes, so there are no major background or foreground operations going on while the animation occurs. Also no audio running, no service activity to speak of. Profiling indicates that there's no code running that isn't related to drawing while the animation runs.
Since everything happens relatively quickly, it's hard to tell exactly what's happening, other than that there's serious flickering going on. Since there's an animation involved, there's no way to break to the debugger in the middle of the animation to see what's going on. Once I break to the debugger, the next redraw will be fully-open state, since the animation positions derive from the current device uptimeMillis().
If I profile the animation, I see an awful lot of text layout operations, which kind of suggest that the recycler view entries might be constantly performing layout during the animation.. Which doesn't really make sense. There's no reason I can think of for layout to occur. It could just be that the text calls are related to onDraw operation. But I mention this because what I did see in profiling seems a bit odd. The majority of CPU time during the animation seems to be spent performing text measurement operations, presumably for content in the RecyclerView entries.
There is heavy overdraw occurring. The drawer itself has a large bitmap containing album artwork, And it's possible that I may have stacked up semi-opaque layers and backgrounds. e.g. the RippleDrawable backgrounds on individual entries in the RecyclerView could very well cause a complete overdraw pass for most of the screen. In addition, there is a complete overdraw pass for the view that dims out the background content as the drawer animates into open position. That being said, the drawer animates beautifully when the animation is triggered by clicking the header of the drawer. Just not when the click that starts the animation comes from the RecyclerView. So I don't think overdraw is really the problem.
For what its worth, the location of display ripping seems to be independent of where the selection and press occurs. Clicking first or last entries in the RecyclerView doesn't affect where the display-ripping occurs. ADB shell dumpsys SurfaceFlinger indicates that hardware composition is being performed on three layers (status bar, navigaton bar, and main activity). So the drawer itself is not using SurfaceFlinger composition (which would, if it were happening at least point in the general direction of what's causing tearing of the display). However, I can't really get the SurfaceFlinger state while the animation is running. It's possible that hardware compositing is being used during the animation. It sure looks like display ripping, and I can't think of why ripping should occur if SurfaceFLinger isn't doing the compositing.
I'm completely mystified as to what the problem might be, or approaches to try and debug this. Any suggestions as to general debugging approach, or suggestions as to what the cause of the problem might would be much appreciated.