Mobile data tracking working on Tab 7 Plus CM9

With Android 4.0 “Ice Cream Sandwich” came an interesting new feature: mobile data usage tracking. It tracks, graphs, and logs your data usage (and the applications which were responsible for using the data).

I just got it working on my alpha CM9 port for the Galaxy Tab 7.0 Plus

I don’t know how accurate it is, but it does appear to work; you can see it has named and shamed Google Play Store and Chrome.

Background

The Android platform apparently requires the kernel network data logging functionality, but many pre-ICS devices using Linux kernels < 3.0 don't have it. The Honeycomb-based Galaxy Tab 7.0 Plus and Tab 7.7, for example, are using Linux kernel 2.6.36. Android is quite noisy about the missing stats when using a device without the appropriate kernel support:

F/NetworkStats( 3434): problem reading network stats
F/NetworkStats( 3434): java.lang.IllegalStateException: problem parsing idx 1
F/NetworkStats( 3434):  at com.android.internal.net.NetworkStatsFactory.readNetworkStatsDetail(NetworkStatsFactory.java:300)
F/NetworkStats( 3434):  at com.android.server.NetworkManagementService.getNetworkStatsUidDetail(NetworkManagementService.java:1284)
F/NetworkStats( 3434):  at com.android.server.net.NetworkStatsService.performPollLocked(NetworkStatsService.java:831)
F/NetworkStats( 3434):  at com.android.server.net.NetworkStatsService.updateIfacesLocked(NetworkStatsService.java:743)
F/NetworkStats( 3434):  at com.android.server.net.NetworkStatsService.updateIfaces(NetworkStatsService.java:721)
F/NetworkStats( 3434):  at com.android.server.net.NetworkStatsService.access$000(NetworkStatsService.java:128)
F/NetworkStats( 3434):  at com.android.server.net.NetworkStatsService$8.handleMessage(NetworkStatsService.java:1633)
F/NetworkStats( 3434):  at android.os.Handler.dispatchMessage(Handler.java:95)
F/NetworkStats( 3434):  at android.os.Looper.loop(Looper.java:137)
F/NetworkStats( 3434):  at android.os.HandlerThread.run(HandlerThread.java:60)
F/NetworkStats( 3434): Caused by: java.io.FileNotFoundException: /proc/net/xt_qtaguid/stats: open failed: ENOENT (No such file or directory)
F/NetworkStats( 3434):  at libcore.io.IoBridge.open(IoBridge.java:406)
F/NetworkStats( 3434):  at java.io.FileInputStream.(FileInputStream.java:78)
F/NetworkStats( 3434):  at com.android.internal.net.NetworkStatsFactory.readNetworkStatsDetail(NetworkStatsFactory.java:269)
F/NetworkStats( 3434):  ... 9 more
F/NetworkStats( 3434): Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
F/NetworkStats( 3434):  at libcore.io.Posix.open(Native Method)
F/NetworkStats( 3434):  at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
F/NetworkStats( 3434):  at libcore.io.IoBridge.open(IoBridge.java:390)
F/NetworkStats( 3434):  ... 11 more

The fix(es)

You need to patch your kernel to have the appropriate "Quota, tag, owner" match and stats support for netfilter. If you’re lucky you’ll find someone who’s already backported the support for your kernel version (or at least something close). In our case, I found that Cyanogen himself had already patched another 2.6.36 kernel with this functionality and, much to my surprise, the patches applied cleanly to our kernel.

After that, you need to make sure CONFIG_NETFILTER_XT_MATCH_QTAGUID=y in your kernel config, and then you should be golden.