For some insane reason, Google seem to think that the market app should get constantly larger and larger with every update. In essence, it’s a customised web browser — it’s making requests to a server and displaying the appropriate page. Why on earth it’s twice the size of an actual browser, I do not know.
Here’s the top five space users on my HTC Desire
- Google Play Store: 9.24MB (9.03MB application; 220kB data)
- k9-mail: 6.75MB (4.09MB application; 2.67MB data)
- Google+ : 5.95MB (5.4MB application; 564kB data)
- Browser: 5.84MB (348kB application; 5.5MB data)
- Maps: 5.09MB (3.95MB application; 1.95MB data)
I am willing to forgive the mail, the browser and the maps — they actually do have a good reason to use lots of data. I don’t even use google+ on my phone; and what in the name of all that is holy does google play need 9MB for?
All it does is make a request to the app server, show the list then download the APK file for installation (an APK being the file that represents an Android App package). I remember when I got the phone the Market app (which is what this Play Store used to be called) was a few MB, and even that was excessive.
Normally a large app you can simply not upgrade, or not use. You don’t get the choice with the market app — it forcibly upgrades itself and cannot be uninstalled.
The HTC desire’s main fault is that the internal phone storage is very small; and the nature of Android is that it stores apps on the internal storage (don’t believe the lies about moving to SD card, Android makes a cached, precompiled version of every app and stores it on the internal storage).
Annoyingly, all this wastefulness has pushed my phone into the “less than 15MB available” state. At which point, Google Talk stops working. DAMNIT. So, spring cleaning time. I’ve got a rooted phone thanks to CyanogenMod so there is scope for a bit more space finding than is normally possible. This article is my notes of what I’ve done.
Let’s look at the state of play to start. I’ve got the Android SDK installed which gives me access to the
adb program, and hence
adb shell; I’ve also activated USB debugging in the Applications—Development menu. I’ve run that to get a shell on the USB-connected phone (it’s pretty cool that one can do this to a phone). Everything I’ll do will therefore be at the android command line.
# df -h Filesystem Size Used Available Use% Mounted on tmpfs 202.8M 32.0K 202.7M 0% /dev tmpfs 202.8M 0 202.8M 0% /mnt/asec tmpfs 202.8M 0 202.8M 0% /mnt/obb /dev/block/mtdblock3 250.0M 170.3M 79.7M 68% /system /dev/block/mtdblock5 147.6M 136.3M 11.3M 92% /data /dev/block/mtdblock4 40.0M 13.7M 26.3M 34% /cache /dev/block/vold/179:1 14.8G 12.8G 2.0G 86% /mnt/sdcard
The important partitions are clear here.
/system is the readonly operating system. This is the bit that gets upgraded when you do an over-the-air update. It can only (easily) be written to by the bootloader (I might resort to that).
/data is the read-write internal phone partition, this is what shows as “phone memory” in the application manager. You can see I’ve got 11.4M free; hence the annoying “phone storage space is getting low” message.
/cache is also read-writable but isn’t considered available for any kind of permanent storage. I think HTC made a mistake with that choice. It would be far more flexible to have combined
cache on one partition to maximise space. You can see that I’ve got another 26.3M free on
cache going completely unused.
/mnt/sdcard is the SD card (unsurprisingly), it’s not much use to use for my purposes here, it’s holding a lot of the uncompiled versions of apps I have installed so is saving a lot of internal space, but that’s about all it’s good for (in this context), so we’ll have to forget about that 2G that would have solved all our problems.
Let’s go poking in
# du /data -d 1 -h 17.0K /data/tombstones 85.5K /data/app-private 2.0K /data/dontpanic 85.4M /data/dalvik-cache 9.9M /data/app 4.0K /data/secure 5.5K /data/property 13.5K /data/backup 6.0K /data/local 34.4M /data/data 50.5K /data/anr 53.5K /data/misc 343.5K /data/system 2.0K /data/lost+found 130.3M /data
The major users of space then are
/data/data. Dalvik is the Android Java engine, and
dalvik-cache is where Android stores the compiled versions of your installed apps. When you download an APK you’re getting the Java Bytecode form of an application; the first time you run it it is compiled by Dalvik into a native form (they have a
.dex extension, so I’ll call them DEX files). To save time the next time you want to run that application it makes and stores a copy of that compiled version. Here’s a huge design fault in Android:
- The app won’t run if the APK isn’t present. That is to say that any app stored on the SD card won’t run when the SD card isn’t mounted.
- The DEX file is always stored on internal phone memory, regardless of where the APK is.
Why couldn’t the DEX version be stored right next to the APK? So if the APK is on SD card, so is the compiled version. Further, why can’t I trade the speed increase from permanently keeping these DEX files gives for the space they take up? A little tick box in the manage applications page to say “hey, I don’t use this app often, I’d rather have the space”. Finally, since Android is calling this a
cache why isn’t it managed like a cache — temporary files, oldest unused get sacrificed; and maybe store it on the damned cache partition?
So.. that’s exactly what I’ll do. That 23M on the
/cache partition can have some of the crap from
/data/dalvik-cache. Note: deleting them would do us no good, as Android will simply remake them exactly where they already are, so any space gain would be very temporary.
# ls /data/dalvik-cache -s | sort -n | tail 1768 system@firstname.lastname@example.org@classes.dex 1874 data@email@example.com@classes.dex 2290 mnt@firstname.lastname@example.org@email@example.com 2301 system@app@Gmail.firstname.lastname@example.org 3612 mnt@email@example.com@firstname.lastname@example.org 4042 data@email@example.com@classes.dex 4047 system@app@Maps.firstname.lastname@example.org 4422 system@app@Vending.email@example.com 4686 system@firstname.lastname@example.org@classes.dex 7865 system@email@example.com@classes.dex
It should be no surprise at all to see all the big apps in this list (although they’ve got weird internal filenames instead of the ones we’re used to). What I’m going to do is move some of them to
/cache/dalvik-cache and leave symbolic links in their place. That is, essentially, what Android itself should be doing. (I’ve actually already done this before, so my
/cache/ partition probably has a little less space than yours).
# mkdir /cache/dalvik-cache
I think I’ll leave the
framework items. To avoid busting something fundamental. Two steps for each app: move the
/cache/, then create a symbolic link from that new location back to the original location.
I’m using a variable to store the filename for clarity and speed of typing:
# export DEX=system@app@Vending.firstname.lastname@example.org # mv /data/dalvik-cache/$DEX /cache/dalvik-cache/ # ln -s /cache/dalvik-cache/$DEX /data/dalvik-cache/
You repeat this process for every DEX you want to move, changing
$DEX each time. Here’s what I ended up with:
# ls /data/dalvik-cache -s | sort -n | tail 1646 mnt@email@example.com@firstname.lastname@example.org 1656 mnt@email@example.com@firstname.lastname@example.org 1706 system@app@GoogleDocs.email@example.com 1768 mnt@firstname.lastname@example.org@email@example.com 1768 system@firstname.lastname@example.org@classes.dex 1874 data@email@example.com@classes.dex 2290 mnt@firstname.lastname@example.org@email@example.com 2301 system@app@Gmail.firstname.lastname@example.org 4686 system@email@example.com@classes.dex 7865 system@firstname.lastname@example.org@classes.dex
How are we looking now:
# df -h Filesystem Size Used Available Use% Mounted on tmpfs 202.8M 32.0K 202.7M 0% /dev tmpfs 202.8M 0 202.8M 0% /mnt/asec tmpfs 202.8M 0 202.8M 0% /mnt/obb /dev/block/mtdblock3 250.0M 170.3M 79.7M 68% /system /dev/block/mtdblock5 147.6M 124.5M 23.1M 84% /data /dev/block/mtdblock4 40.0M 29.4M 10.6M 74% /cache /dev/block/vold/179:1 14.8G 12.8G 2.0G 86% /mnt/sdcard
/cache free space has reversed. That’ll do me for now. I’ve got a working system again. My temptation for the future will be to do what I said Android should be doing: put the DEX next to the APK. Then the appropriate files will be on the SD card.
A quick check shows me that the moved apps are all still working and that phone is reporting 22.95MB free.
There is another option, which I won’t do this time: moving some applications to the
/system partition. That’s a bit tougher though because we would have to mess around with bootloader scripts. I’m satisfied for now, and I’ve left enough space for Google to bloat that damned market app a bit more without killing my phone again.