During the I/O 2016 Keynote presentation, and again at the October 4th Pixel announcement, Google made brief references to newly added support for seamless updates in Nougat. To make this work, many changes had to be made to the structure of Android and its assorted system partitions. As a result, there have also been some changes to the fastboot utility many of us use when new factory images become available. This post covers a few of the technical details and also demonstrates some of the ways to use the new features.

How it works

Seamless updates are accomplished by creating a second set of logical partitions in device storage. Android refers to these as "slots" in most places. At the start of the boot sequence, a bootloader flag instructs the device which slot is meant to be active. The one relevant exception to this is the /userdata partition, which contains your downloaded apps, any data they've stored, and your personal data and settings. There's only one version of that partition and each slot uses it freely.

When an OTA update is downloaded to your device, the OS quietly works in the background to write an updated versions of each partition into the inactive slot. Once it has finished, that bootloader flag is flipped to let the device boot up the freshly updated slot during the next restart.

In the event that a slot cannot boot, at least in the case of the Pixels, it will make a few attempts and ultimately reboot into the other slot.

Interesting side effects

If you are familiar with previous versions of Android, you'll find that there are some interesting changes to the partition table and factory images from Google. There are also a few limits with the new system and some reasons it's unlikely we'll see these features ported to older devices. If you don't care much about implementation details, feel free to skip the rest of this section and check out the guide to new fastboot commands.

Some partitions are going away:

  • On devices that support seamless updates, Android basically slipstreams OTAs as it writes the updated partitions, meaning that it can merge in changes without first creating copies. An advantage of this system is that it does away with the need for a dedicated /cache partition. It does not exist on the new Pixel phones and isn't likely to appear on future devices supporting seamless updates.
  • Likewise, the /recovery partition has become largely redundant. Historically, the stock recovery image was used to install OTA packages, perform factory resets, and wipe the /cache partition. Installing OTAs is now handled by the OS, and there's no need to wipe the /cache partition anymore, so the /recovery partition has been removed, as well. Since the ability to perform factory resets is still important and the Android team still wants to allow for sideloading OTAs, a functionally similar recovery feature has been integrated into the /boot image.

For much more background on these subjects, check out these three posts and follow-up comments: Elliott Hughes on May 19, Artem Russakovskii on May 24, and Chainfire on Oct 29.

Older devices aren't going to support seamless updates:

  • Multiple Googlers have confirmed that previously released Nexus devices weren't going to be updated to support seamless updates. Furthermore, it's unlikely any other device will gain this feature. The reason is fairly obvious – it requires significant repartitioning of storage. That process would be technically difficult to accomplish and very prone to errors, potentially resulting in significant data loss or even a bricked device.
  • It's not technically impossible for older devices to have seamless updates through the use of custom firmware, but the likelihood is low. This is because seamless updates rely on a bootloader that understands how to work with dual slots. Since bootloaders are rarely open source and custom modifications are difficult and community support would be limited, this type of project would be fairly impractical (but not impossible).

Potential future for modding:

  • Efforts to put a custom recovery on a Pixel are underway, but the various changes to the partition table (now that recovery is somewhat homeless), new boot procedures, and the switch to file based encryption from full-disk encryption have slowed progress.
  • The current nature of the seamless updates system is only intended to have a single usable slot at a time, then overwriting the inactive slot during an update. When no update is being written, the inactive slot can contain a fully bootable and usable version of Android. For developers, this makes it possible to flash and run older versions of the OS (although there may be complications with the shared /data partition), run a rooted version of Android in one slot while another remains stock, or even dual-boot with custom builds.

New fastboot commands

With the updates to Android 7.0 and 7.1, changes also had to be made to the fastboot utility so it could work with the new dual slot partition table and to set the active slot bootloader flag. The new parameters aren't difficult to understand or work with, but there are a few things to keep in mind. The main rule is that if you want some control over which slots are flashed, you'll want to add the appropriate parameters to your fastboot commands.

If you're flashing a phone or tablet without dual slots for seamless updates, you won't have to worry about making any changes to what you've already been doing. Likewise, if you simply don't care and you just want to install the latest factory image, feel free to use the same commands you've always used and things should turn out just fine. Of course, you could speed things up quite a bit with one extra parameter, but we'll get to that in a bit.

Commands

Here are the main updates and new commands:

Updated:

update <filename> – Reflash defice from update.zip. Sets the flashed slot as active.

The update command works just like it did before, but it now also automatically sets the flashed slot as active. Using commands or parameters described below, you can set which slot will be flashed.

Updated:

flashall – Flash boot, system, vendor, and – if found – recovery. If the device supports slots, the slot that has been flashed to is set as active. Secondary images may be flashed to an inactive slot.

Much like the update command, flashall has been updated to set the flashed slot to be active. The text also points out that secondary images may be flashed to an inactive slot. This depends on whether secondary images are part of an update package. If you want to keep your "old" slot intact and bootable, it's important to use the --skip-secondary parameter to prevent this behavior.

New:

set_active <slot> – Sets the active slot. If slots are not supported, this does nothing.

The set_active command can be used to specify which slot should be active. It simply changes the bootloader flag. Be advised that changing the active flag doesn't mean the new slot is actually active yet. You can be running the bootloader for the inactive slot. For example, launching recovery from the bootloader after changing the active slot will result in loading recovery from the inactive slot. Depending on the situation, it may be necessary to reboot after running this command.

Note: if you set one of the slots active and it cannot successfully boot, it will reboot a few times and eventually switch to the other slot so it can finish booting. This is a safety mechanism to save the day in case of a bad flash, allowing the device to return to an older working version and try again. You'll notice this happens if you don't use the --skip-secondary option with a factory image and switch to the secondary partition before rebooting.

Options

There are three new command line options that allow for properly specifying how commands are supposed to behave. Each works in different situations, so use best judgement to determine where they are appropriate.

New:

--slot <slot> – Specify slot name to be used if the device supports slots. All operations on partitions that support slots will be done on the slot specified. 'all' can be given to refer to all slots. 'other' can be given to refer to a non-current slot. If this flag is not used, slotted partitions will default to the current active slot.

The description for this one is pretty succinct and doesn't really need much clarification. This parameter is only relevant to commands that involve flashing data.

New:

-a, --set-active[=<slot>] – Sets the active slot. If no slot is provided, this will default to the value given by --slot. If slots are not supported, this sets the current slot to be active. This will run after all non-reboot commands.

This parameter probably won't get too much use since most of the commands automatically set the active slot when they flash some data (except for the flash command itself). This is a valid way to set the active slot without issuing an extra command and may also be useful in some scripts if it's used without specifying a slot.

New:

--skip-secondary – Will not flash secondary slots when performing a flashall or update. This will preserve data on other slots.

Finally, the --skip-secondary command is used to prevent non-primary slots from being modified if a flashall or update command would do so. This is the one parameter possibly worth using even for users that aren't concerned with maintaining the integrity of inactive slots. The reason it's useful is because it doesn't waste time writing data to inactive slots, so the update and flashall operations complete much faster than without it.

Examples

While most of these commands are pretty easy, it may help to see some samples for usage. Be aware that the Pixels use "_a" and "_b" to name the slots in commands, but they will be shown as just "a" and "b" in most outputs.

Setting the active partition:

fastboot set_active _b

–or–

fastboot --set-active=_b

With the set_active command or --set-active parameter, the active slot can be changed. Notice the shots below where the boot slot has changed from 'a' to 'b'.

Note: a reboot is required for the change to fully take effect.

Flashing to a specific slot (without affecting another slot):

fastboot flash --slot _b bootloader <bootloader.img>

fastboot update --slot _b --skip-secondary <update.zip>

In this scenario, the flash command strictly targets only one slot. If you're using update or flashall, they require the --skip-secondary option to avoid changing the data in the secondary slot. Again, even if you don't care about keeping the other partition intact, using the --skip-secondary option shaves about a minute off the flashing time since it doesn't have to write to the second system or vendor partitions. If the old slot is left intact, you can still switch back to it and boot from it like nothing has changed.

Thanks: Jeff Vander Stoep from the Android Security Team for the commands

Additional Information: Elliott Hughes