Dissecting the Android OTA Update System
One of the most important features of any modern software platform is its ability to update itself to the latest version. Not only does it satisfy the need of the customer to receive the latest and greatest features, it also allows the timely distribution of security patches to address exploits.
As the Lead Firmware Developer at TextNow, one of my responsibilities involves developing and maintaining the custom system software that gets flashed onto the phones we sell. Part of that software involves the Over the Air (OTA) updates system. In order to deliver updates to our customers more effectively, I’ve built a custom system application and back-end server that work together with the Android APIs and Recovery. Together, these components make OTA updates a reality for TextNow phones.
OTA updates involve downloading one or more files that contain the updates to be installed. Usually, they are accompanied by a script that tells the update system how the updates are to be installed.
The installation script is executed by the recovery image — essentially a slimmed down Linux system — which takes very little room in the phone’s memory, and also shows the user a simple menu to perform basic system recovery functions such as wiping the phone, or the cache partition. In this case, the recovery image will be performing the installation of the OTA update.
We will take a brief dive into each of these steps in hopes to make the overall process of OTA updates on the Android platform a little easier to understand.
Downloading the OTA Update
This step is handled by a system updates application that is pre-installed by the phone manufacturer and often the download is automated. Most manufacturers either don’t allow downloading while on a cellular data connection, or they have a setting for it.
Once the OTA update is downloaded, it is usually checked for integrity using a checksum. This is important so that we don’t waste the user’s time rebooting the phone and not being able to install the update (there are additional integrity checks later in the process).
Installing the OTA Update
This system update is then responsible for initiating the installation process, but generally this requires user consent (I’m looking at you Microsoft!), and so the OTA update availability is communicated to the user via an Android Notification.
Once the user says — “Yes, go ahead and install” — the system updates application will call into Android’s Recovery System API to initiate the installation process. The Recovery API does a few things:
1. Verifies the update file’s signature, to ensure it was signed with the same certificates that match /system/etc/security/otacerts.zip
2. Writes a command in /cache/recovery/command to instruct the recovery to install the OTA update. This command is usually:--update-package=<path_to_package.zip>
3. Reboots the phone with special arguments to ensure the phone will boot up into recovery mode.
Once the recovery has booted up, it will look for the command file, parse it, and realize that it needs to install an OTA update. It will unzip the archive, and verify its signature once again. This time, though, it will compare the signature against certificates stored right in the recovery image’s initial ramdisk (more on this in a future blog post), under /res/keys.
Next, the recovery will start running the OTA update’s installation script mentioned earlier. This script can technically be a shell script (used by some non-standard open source recovery projects), but the standard Android way is to use a language called Edify that was purpose-built for the Android Recovery System. There is also a reference to (most of) the commands that this language supports on the XDA Developers’ Wiki.
The update script typically does the following:
1. Verifies correct file versions and checksums on the system partition. This prevents installing the update on top of the incorrect OS version, thereby preventing a bricked phone and an angry user.
2. Copies new files, patches old ones, and deletes obsolete files.
3. Writes new recovery/bootloader/radio images. Since the recovery system is loaded into working memory at boot time, the flash partition where it was loaded from can be safely written to from the recovery itself.
4. Displays progress of the installation to the user.
5. Updates the version of the OS so that this OTA update can’t be installed again.
Finally, the recovery system will reboot the phone, but not before removing the recovery command file. This is important so we don’t get stuck in a recovery loop.
My Final Update
The Android recovery system is a complex beast, that addresses the complicated problem of OTA updates. There are many different components that need to be made to talk to each other. Debugging recovery problems can be tricky at the best of times, especially since it involves reboots and modifying system partitions, which can brick one’s phone and force them to start again from scratch. (Not that this ever happened to me, ever… ☺) However, once it works, it tends to work well, so you can find comfort in that.
If OTA updates and custom system software are your thing, check out some of our current job openings.