2012 December 29
This recipe written December 2012. Keep in mind that techniques vary a lot over time. And, yeah, sorry for the SEOriffic title.
I like a lot about the HTC Nexus One phone, but one of its annoying problems is that it has a tiny amount of storage space for apps. Maps, Twitter, Firefox, Go SMS Pro, and K-9 Mail are pretty much must-haves for me, and they alone almost fill up the phone’s “internal storage” for apps. It’s basically one-in-one-out for installing apps, and the constant “space is running low” messages are not only annoying but also indicate that the phone won’t perform certain important functions.
If you Google around, you’ll see various “app2SD” or “apps2SD” apps or scripts that promise to let you move apps to the SD card, which isn’t huge (4 GB for me) but is bigger than the 180 MB of the internal storage. There’s built-in support for this with some apps on Android 2.3.6, and some of the app2sd tools seem to be remnants from an earlier time. (Others are probably just trying to cash in on ignorant people.) You also see people talking about reformatting your SD card to add an ext-format partition to allow app storage there, which makes sense; the VFAT filesystem used by the SD cards by default doesn’t support some of the features needed for system files.
It took me a surprisingly long amount of time to find what seems to be the current best system: Super APP2SD by XDA Developers user TweakerL with assistance from several others. The basic approach is straightforward: in the early stages of system startup, a partition on the SD card is bind- mounted to a few magic app directories, redirecting their storage from the internal NAND memory to the SD. And that’s all you need to do!
As usual, the code written by the XDA people is a little dubious and scary, and the instructions are not great and also targeted at Windows users. So I’ve adapted their technique and documented what I did here. That being said, big thanks to TweakerL and friends for figuring this out and publishing the technique. The caveats:
-
You need a rooted phone.
-
Of course you run the risk of bricking your phone, killing all your apps, etc.
-
Apps become substantially slower to load and less responsive. The difference is noticeable and annoying. I still prefer having the freedom to actually install new apps, which I basically didn’t before, but this downside is significant.
-
The transfer is all-or-nothing, so you can’t keep a few apps on internal storage for faster loading.
-
The storage space reports on the phone become inaccurate.
-
None of your apps are available if your SD card is unavailable.
-
I’ve only been using this system for a little while, so there may be other issues that I haven’t yet appreciated.
Here’s how it’s done:
-
Do some preparation.
-
Root your phone, perhaps using my instructions. This has its own large set of caveats and hassles. For me, at least, the lack of app storage is an annoying enough issue that I’m happy that I went to the trouble of the rooting.
-
You’ll need the Android SDK and the
adbprogram. You just need the SDK, not the ADT bundle. My post on rooting has a bit more info on the installation. -
You also need to install Busybox on the phone to get a more powerful mount program for later. You install the Busybox app, then run it to actually install the needed files. It wanted to place all sorts of crazy programs (
httpd??) that I disabled, but they’re probably fine. I think the only truly necessary tools may bemountandmknod.
-
-
Back up everything, especially your apps (duh), their data, and your SD card.
-
Add an ext3 partition to your phone’s SD card.
-
You backed up your SD card, right? Because you’re about to wipe it.
-
Somewhat surprisingly, you can do this while your phone is running. Connect your phone to your computer via USB and turn on USB storage. Don’t mount the VFAT partition.
-
I added partitions using the very nice GNOME Disks program. I essentially shrank the first partition (by deleting and recreating it), changing it from 4 to 3 GB, and then I created a new ext3 partition of 1 GB. The volume labels aren’t important. The partitions should be primary/bootable. Android 2.3.6 can’t handle ext4, so use ext3. Make sure that the type of the VFAT partition is W95 FAT32; I had to change this manually after making the partition. You should be able to mount the VFAT and ext3 partitions on your computer after setting them up and verify their setup.
-
Restore your backup of the VFAT files.
-
If you disconnect the USB, your phone should reload the SD card and not notice any problems. If it does, reformat the card (which the phone will offer to do), then reconnect to your computer and figure out what you did wrong. For me, it was setting the partition type.
-
-
Get the ext3 partition mounted on your phone.
-
This part of the process involved some trial-and-error so I’m not sure what’s strictly necessary. I’m pretty sure that you need to reboot the phone to get the OS to notice the new SD partition.
-
Turn on USB Debugging on the phone. Connect the USB and open up a shell using the Android SDK’s
platform-tools/adb shellcommand. Usesuto become root. -
Many of the built-in shell utilities are surprisingly braindead, even given that we’re running Unix on a tiny piece of plastic and metal. When in doubt, prefix commands with
busyboxto use the Busybox versions, which are generally smarter. -
Run
busybox mount -o rw,remount /andbusybox mount -o rw,remount /systemto be able to monkey with the filesystem. -
You may also need to manually create device nodes to be able to mount the ext3 partition. The VFAT partition of the SD card is mounted from something like
/dev/block/vold/179:1, but the Busybox mount program seems to cut off the filename at the colon. There seems to be an equivalent device node called/dev/block/mmcblk0p1, so I created/dev/block/mmcblk0p2usingbusybox mknodand emulating the parameters of the VFAT partition. -
After the right magic has happened, I created a mount point at
/mnt/sd-extand was able to mount the partition withbusybox mount -o nosuid,nodev,noatime /dev/block/mmcblk0p2 /mnt/sd-ext. -
Also create a mount point at
/mnt/nand-datafor later.
-
-
Mirror the apps and data from the internal storage to the SD.
-
The relevant internal directories are
/data/appand/data/data. The XDA Developers approach also mirrors/data/media/Android, but I can’t find anything resembling this directory on my phone, so I suspect that it’s only present in newer Android versions. -
Create
/mnt/sd-ext/data/appand/mnt/sd-ext/data/dataand duplicate the contents of/data/appand/data/datausing your favorite technique. You may need to usebusybox cpand not justcpto get more useful options. Make sure to preserve permissions, ownership, etc. -
I touched
/data/data/this_is_oldand/mnt/sd-ext/data/data/this_is_newas sanity checks for later.
-
-
Install the code for futzing with the mounts at boot time.
-
The trick here is to intercept an invocation of
/system/bin/debuggerd, which is apparently called early in the boot process. -
Move
/system/bin/debuggerdto/system/bin/debuggerd.bin. -
Create
/system/bin/debuggerd.shimwith the following contents:#!/system/bin/sh /system/xbin/pkgw.earlymounts exec /system/bin/debuggerd.binI did this using
adb pushonto the VFAT SD card then moving the files. You can’t push directly into/system/binbecause of permissions. Give the file permissions and ownership mirroringdebuggerd.bin. -
cd /system/bin ; ln -s debuggerd.shim debuggerd -
Create
/system/xbin/pkgw.earlymountswith the following contents:#!/system/bin/sh export PATH=/sbin:/system/sbin:/system/xbin:/system/bin nanddata_dev=/dev/block/mtdblock5 nanddata_mount=/mnt/nand-data sdext_dev=/dev/block/mmcblk0p2 sdext_mount=/mnt/sd-ext busybox mount -o remount,rw / busybox mkdir -p $sdext_mount $nanddata_mount busybox mount $nanddata_dev $nanddata_mount busybox mount -o nosuid,nodev,noatime $sdext_dev $sdext_mount if test -f $sdext_mount/data/remount_is_safe ; then busybox mount -o bind $sdext_mount/data/data /data/data busybox mount -o bind $sdext_mount/data/app /data/app fi busybox mount -o remount,ro /It should be pretty apparent how it all works. It should also be apparent that the device paths and mount paths should be checked against the output of
mountto be sure that everything is pointing in the right place. Set ownership and permissions onpkgw.earlymountsas withdebuggerd.shim. (Themkdir -pabove might not be needed? I don’t know what persists across boots. I also discovered that the Android shell doesn’t have `` as an alias fortestby default.)
-
-
Reboot the phone to verify that the shim works. If you log in with
adb shell, the/datadirectory should be unchanged, but the/mnt/sd-extand/mnt/nand-datashould be mounted appropriately right from bootup. -
Activate the bind mounts.
-
Enable them by touching
/mnt/sd-ext/data/remount_is_safe. -
Reboot the phone.
-
Along with the new mounts in
/mnt, you should see that/data/dataand/data/appare mounted from/dev/block/mmcblk0p2now. Their contents should be identical and your phone should work. But /data/data should contain a file calledthis_is_new, notthis_is_old. Your apps are now all living on your SD card! -
Check out how much storage your phone thinks it has free in the internal app storage space. Try installing a new, large app. The amount of free space should remain unchanged. (If nothing else has happened. Firefox’s hungry cache ate up some of my space and made me think something had gone wrong.)
-
-
Clean up.
-
Delete files in
/mnt/nand-data/dataand/mnt/nand-data/appto free up space on the internal storage. Make sure you’re working in the right directory! Try deleting something noncritical, then confirming that it still runs on the phone. Reboot again if that’ll make you feel better. Don’t delete critical-sounding apps and data in case your SD card goes missing. After doing this, my internal storage has 74 MB free, which should be enough for all sorts of temporary stuff. -
In the app manager, move apps back “from” the SD “to” internal storage — even though internal storage is now also on the SD. We’re just relocating things from the VFAT partition to the ext3 partition. This just makes it so you can still use those apps when you’ve got the VFAT mounted over USB.
-
Go to the app store, go to My Apps, slide over to the All listing, and install all those old apps that you removed because of space restrictions.
-
As a side benefit, you can now mostly back up your apps and their data directly over USB, rather than by having to use a dedicated backup program.
-
Big thanks to TweakerL and the XDA Developers folks for blazing the trail!
Update: Having been using my phone this way for the past few days, I’m still happy I did this, but I might consider only moving the app data, and not the apps themselves, to the SD card. There would still be a lot of space left in the system storage for a reasonable number of apps, and there’s a possibility it would help with the responsiveness issues I’m seeing.