One thing I regret over the past couple of years, is reducing my blog output. I think I used to blog fairly regularly in the past, and that seemed to stop when I joined Intel (though I’d love to blame someone other than myself, unfortunately, it is entirely my fault). So I’d like to get back into the habit of writing again, by writing about what I’m doing here at Mozilla.
Always good to start with an easy one, so I’m starting with the first bug I fixed. Bug #661843, “GeckoSurfaceView may double memory requirement for painting”. Doug Turner assigned this to me as I joined, and I’m still very grateful as it turned out to be pretty easy to fix and a massive win for Firefox Mobile on android.
Getting stuff to the screen from a native app on Android was quite difficult up until Gingerbread and we target Android 2.0 and up, so moving to the new native app SDK isn’t currently an option. It’s a lot easier if you cheat (by using undocumented interfaces), but winners don’t cheat. Or at least they don’t get caught. Or something. To get around the lack of ‘native’ interfaces to the Android app components, Firefox Mobile on android consists of a small Java shim and the main application. This shim acts as our input/output to the device and interfaces via JNI to the various internal services.
For drawing to the screen, our Java shim builds up a simple Android application and provides a buffer for the native code to draw into. When the native code wants to draw, it calls the Java methods to get the buffer, does its thing and sends a signal back to the Java code to let it know that it’s finished drawing – this can be seen mostly in nsWindow.cpp, in the OnDraw method. Prior to Android 2.2, there was no way for native code to draw straight into an Android Bitmap, and no way to copy a raw data buffer onto the application’s Canvas. The only option in this case is to create a Bitmap based on the data buffer (which ends up copying that buffer), then blit that Bitmap onto the Canvas.
Android 2.2 added native access to the Bitmap class, allowing native code to directly manipulate the memory backing it – this is exactly what we needed. Unfortunately, this pushes our requirement up, which isn’t something we want to do just yet. My fix for this patch involved loading the new native graphics access library at runtime and using it if it’s available. To make things easier, I reshuffled the code on the Java side (which can be seen in GeckoSurfaceView.java) so that the two paths share most of the code. The slow path backs the browser canvas with a ByteBuffer (which allows direct access via JNI, but can’t be copied directly to the Canvas), the fast path uses a Bitmap and Android’s libjnigraphics. This halved the memory usage required for updates to the screen and reduced the amount of allocation/copying going on, providing a nice speed boost.
I believe you should see this if you’re running Firefox Mobile Beta, available on the Android Market and it’ll be incorporated in Firefox Mobile 6.]]>