Search code examples
androidoptimizationsurfaceviewmidiframe-rate

Poor framerate when responding to non touch events


Here's my issue: I'm developing a sort of music game where the user can input to android from a midi keyboard (I am using this library: https://github.com/kshoji/USB-MIDI-Driver). For my main game layout, I use a surface view coupled with a game loop. I optimized my onDraw() to be very quick, but for whatever reason, my framerate is much slower when using the external midi keyboard, than when using touches on an on screen keyboard.

At first I though this was due to the overhead from the keyboard driver, but then I noticed that when I touch the screen, the framerate is no longer choppy, even when I am playing from the midi keyboard. Does anyone one know why this might be the case? Does android do some sort of background optimization for ui updates responding to a touch event? Thanks.

EDIT: I have scoped out some more information about my problem. Basically, what my device is doing is setting to CPU speed to low to save power. The policy (as defined by a CPU Governor) is to give the cpu a boost when the user touches the screen, and reduce the cpu clock speed when it doesnt detect any touches. My problem is that since I want to interact via an external device, and not through touch events, the cpu is slow and I get a bad framerate as a result. There are apparently ways to override this if you have root access... but I'd rather not resort to that :/. If anyone has any hacks or ideas, please let me know.


Solution

  • The issue, as you have noted, is aggressive power-saving code. Some notes and a few links are in this answer.

    If your app was doing lots of work on the CPU, it wouldn't be throttling down. So one hack / workaround is to have a thread that just sits and spins. This is a really bad idea though, as it will adversely impact the battery life of the device.

    If your only issue is with choppy display, and not something more serious like dropping data from an external device, then you can work around the problem by dropping frames when your app falls behind. Quoting the linked answer:

    The problem is that the system is aggressively reducing clock speeds to save power when it doesn't detect interaction with the user. (Qualcomm in particular seems fond of this.) The workaround is to drop frames when necessary. See this article on game loops, and a Choreographer-based trick demonstrated in Grafika's "record GL app" activity (in doFrame()).