Tag Archives: Android

AOSP Code Growth

~11 million lines of Java in Marshmellow release 1 (tag 6.0.1_r1)!

aosplinesofcodewwatermark

The XML trend line is linear and both Java and CPP are polynomial to the 2nd order. Is it possible there will be ~20 million lines of Java by release ‘O’?

aospcodegrowthtrendlineswatermark

 

Custom Android Resource Files

Android resource files are a great way to keep your data separate from your code. It works great as long, as all you need is one of the supported types. What do you do if you have a more complex static data type that you’d like to manage independently of the code?

The answer is to create a ‘raw’ XML file under the /res/xml directory and write the parser logic yourself. For example, let’s say you want to compare the elevation of the mountains in your state. As mountains tend to stick around a while, there is no reason to query a database every time you want an elevation. Instead, you can simply create a static XML file like so:

/res/xml/mountain_data.xml

<?xml version="1.0" encoding="utf-8"?>
<mountains>

    <mountain
        name="Mt. Elbert"
        county="Lake"
        elevation="14433"
        lat="39.11807"
        long="-106.445417"
        range="Sawatch"
        rank="1" />
    <mountain
        name="Mt. Massive"
        county="Lake"
        elevation="14421"
        lat="39.187298"
        long="-106.475548"
        range="Sawatch"
        rank="2" />
    <mountain
        name="Mt. Harvard"
        county="Chaffee"
        elevation="14420"
        lat="38.924328"
        long="-106.320618"
        range="Sawatch"
        rank="3" />

</mountains>

Custom resource types don’t get fully precompiled into the ‘R’ class, and hence, you need to load and parse them yourself. At runtime simply load the file using
Resources.getXML(R.fileId) and then parse the data using XmlResourceParser. This parser is very basic and steps through each element every time you call
next(). With each element you can call getEventType() to determine if its a close or open tag. The following code will load, parse and store the elevation
of each mountain in the resource file into a list.

        List<String> elevations = new ArrayList<String>();
        Resources res = getResources();
        XmlResourceParser xrp = res.getXml(R.xml.mountain_data);
        try{
            xrp.next(); // skip first 'mountains' element
            while (xrp.getEventType() != XmlResourceParser.END_DOCUMENT) {
                xrp.next(); // get first 'mountain' element
                if(xrp.getEventType() == XmlResourceParser.START_TAG) {
                    // double check its the right element
                    if(xrp.getName().equals("mountain")) {
                        // extract the data you want
                        int count = xrp.getAttributeCount();
                        String name = xrp.getAttributeValue(null, "name");
                        String elev = xrp.getAttributeValue(null, "elevation");

                        // add elevation to the list
                        elevations.add(elev);

                        Log.v(TAG, "Attribute Count " + count);
                        Log.v(TAG, "Peak Name " + name);
                    }
                }
            }
        } catch (Exception e) {
            Log.w(TAG, e.toString());
        } finally {
            xrp.close();
            Log.i(TAG, elevations.toString());
        }

Doing this allows you to shrink or expanded the number of mountains without impacting or touching any code.

Android App Collection Widgets

Adding a “launcher” widget to your application can be a little convoluted even in recent 4.x AOSP releases. If you’re heading down this path, check out Google’s App Widget tutorial first. Take note that one of the more powerful concepts covered in the tutorial is “collections” or RemoteViews. I created the following UML static structure to help aid in designing your new collection widget.

appwidgetproviderwatermark

Sniffing Android Emulator

The emulator shipped with ADT is a great tool for both early stage framework development and late stage application development. A large majority of the Android emulator users will only use a small portion of the features for app development. For the developers working on distributed framework development, it is a necessity to be able to sniff emulator network traffic (no Wireshark can’t see the makeshift emulator router). Fortunately, the ADT developers provided two ways to accomplish this.

1) Using the telnet interface (start emulator first)

telnet localhost 5554
network capture start emulator.cap
-- Do Something Cool --
network capture stop

2) Using the emulator command line option

emulator -avd myavd -verbose -tcpdump emulator.cap

Afterwords, simply open the cap file with Wireshark. That’s it.

Speeding up AOSP Builds – System Temp Directory

The Android Development Tools (ADT) is a massive project and is very well done. Getting your hands on and compiling the Android Open Source Project (AOSP) is very easy too. So easy, you’ll quickly want to improve your compile performance. An initial compile of AOSP can take about ~46 minutes on an Intel i7 @ 3.4 GHz. Using the compile cache will definitely speed up sequential builds but more can still be done. Sacrificing just a few MB of RAM (~60 MB) for a system temp directory (/tmp) ramdisk can reduce compile time anywhere from ~2%-10% depending on total system throughput (other hardware specs). The C/C++ compiler creates, writes and deletes a temporary file for each source file crunched. Keeping this I/O traffic in RAM offers efficiency gains.

compiling

System:
PC Desktop i7 @ 3.4 GHz x 8 w/16 GB RAM and 7200 RPM Drive
Without Ramdisk: ~44 minutes
With Ramdisk: ~41 minutes
Reduction in time playing swords: ~7%

System:
PC Laptop Intel Core 2 Duo CPU T8300 @ 2.4 Gz x 2 w/4 GB RAM and 5600 RPM Drive
Without Ramdisk: 705 minutes
With Ramdisk: 650 minutes
Reduction in time playing swords: ~8%

To setup your /tmp directory to be a ramdisk on Ubuntu systems add the following to your /etc/fstab file and reboot

ramdisk /tmp tmpfs mode=1777,size=2g

There are two quick ways to make sure the ramdisk is working.
1) run the ‘df’ command and confirm /tmp is mounted with the correct size
2) copy a large file to your home directory and again to the /tmp directory and compare speeds

chris@chis-devpc:~/ServerBackups$ time cp 2012.11.04.04.00.MySQL_Backup.sql.gz ~/

real	0m2.657s
user	0m0.000s
sys	0m0.240s
chris@chis-devpc:~/ServerBackups$ time cp 2012.11.04.04.00.MySQL_Backup.sql.gz /tmp

real	0m0.224s
user	0m0.000s
sys	0m0.140s

The file copied above is 208MB. As you can see, the ramdisk was an order of magnitude faster.