diff options
Diffstat (limited to 'en/devices')
-rw-r--r-- | en/devices/_toc-interfaces.yaml | 2 | ||||
-rw-r--r-- | en/devices/_toc-tech.yaml | 18 | ||||
-rw-r--r-- | en/devices/architecture/dto/partitions.html | 16 | ||||
-rw-r--r-- | en/devices/architecture/hidl/services.html | 14 | ||||
-rw-r--r-- | en/devices/architecture/images/android-diffs.png | bin | 0 -> 67212 bytes | |||
-rw-r--r-- | en/devices/architecture/images/kernel_branch_hierarchy_44.png | bin | 0 -> 83197 bytes | |||
-rw-r--r-- | en/devices/architecture/images/kernel_lts_diff.png | bin | 0 -> 20146 bytes | |||
-rw-r--r-- | en/devices/architecture/kernel/android-common.html | 170 | ||||
-rw-r--r-- | en/devices/tech/admin/enterprise-telephony.html | 15 | ||||
-rw-r--r-- | en/devices/tech/config/perms-whitelist.html | 14 | ||||
-rw-r--r-- | en/devices/tech/debug/index.html | 2 | ||||
-rw-r--r-- | en/devices/tech/ota/ab_updates.html | 1600 | ||||
-rw-r--r-- | en/devices/tech/ota/index.html | 162 | ||||
-rw-r--r-- | en/devices/tech/ota/nonab_updates.html | 195 |
14 files changed, 1324 insertions, 884 deletions
diff --git a/en/devices/_toc-interfaces.yaml b/en/devices/_toc-interfaces.yaml index 5a78a719..a7958fc3 100644 --- a/en/devices/_toc-interfaces.yaml +++ b/en/devices/_toc-interfaces.yaml @@ -17,6 +17,8 @@ toc: path: /devices/architecture/kernel/ - title: Stable Releases & Updates path: /devices/architecture/kernel/releases + - title: Android Common Kernels + path: /devices/architecture/kernel/android-common - title: Modular Kernel Requirements path: /devices/architecture/kernel/modular-kernels - title: Interface Requirements diff --git a/en/devices/_toc-tech.yaml b/en/devices/_toc-tech.yaml index 22d8fa9a..dd7e48a2 100644 --- a/en/devices/_toc-tech.yaml +++ b/en/devices/_toc-tech.yaml @@ -169,20 +169,22 @@ toc: path: /devices/tech/ota/ - title: OTA Tools path: /devices/tech/ota/tools - - title: Block-Based OTA - path: /devices/tech/ota/block - - title: Inside OTA Packages - path: /devices/tech/ota/inside_packages - - title: Device-Specific Code - path: /devices/tech/ota/device_code - - title: Reducing OTA Size - path: /devices/tech/ota/reduce_size - title: Signing Builds for Release path: /devices/tech/ota/sign_builds + - title: Reducing OTA Size + path: /devices/tech/ota/reduce_size - title: A/B System Updates path: /devices/tech/ota/ab_updates - title: Implementing A/B Updates path: /devices/tech/ota/ab_implement + - title: Non-A/B System Updates + path: /devices/tech/ota/nonab_updates + - title: Block-Based OTA + path: /devices/tech/ota/block + - title: Inside OTA Packages + path: /devices/tech/ota/inside_packages + - title: Device-Specific Code + path: /devices/tech/ota/device_code - title: Performance section: - title: Overview diff --git a/en/devices/architecture/dto/partitions.html b/en/devices/architecture/dto/partitions.html index bcbea204..d18cda84 100644 --- a/en/devices/architecture/dto/partitions.html +++ b/en/devices/architecture/dto/partitions.html @@ -150,8 +150,8 @@ several commands, including <code>create</code>, <code>cfg_create</code>, and <h3 id=create>create</h3> <p>Use the <code>create</code> command to create a <code>dtb</code>/<code>dtbo</code> image:</p> -<pre class="prettyprint"> -$mkdtimg create <image_filename> (<global-option>...) \ +<pre class="devsite-click-to-copy"> +<code class="devsite-terminal">mkdtimg create <image_filename> (<global-option>...) \</code> <ftb1_filename> (<entry1_option>...) \ <ftb2_filename> (<entry2_option>...) \ ... @@ -184,7 +184,7 @@ value of <code>page_size</code> in <code>dt_table_header</code> is 2048; use value.</p> <p>Example:</p> -<pre class="prettyprint"> +<pre class="devsite-click-to-copy"> [board1.dts] /dts-v1/; /plugin/; @@ -203,7 +203,7 @@ value.</p> }; -$mkdtimg create dtbo.img --id=/:board_id --custom0=0xabc \ +<code class="devsite-terminal">mkdtimg create dtbo.img --id=/:board_id --custom0=0xabc \</code> board1.dtbo \ board2.dtbo --id=0x6800 \ board3.dtbo --id=0x6801 --custom0=0x123 @@ -243,7 +243,7 @@ with one or more space characters (these options are the same as lines beginning with <code>#</code> are ignored.</p> <p>Example:</p> -<pre class="prettyprint"> +<pre class="devsite-click-to-copy"> [dtboimg.cfg] # global options id=/:board_id @@ -260,7 +260,7 @@ board2.dtbo custom0=0x123 # override the value of custom0 in global options -$mkdtimg cfg_create dtbo.img dtboimg.cfg +<code class="devsite-terminal">mkdtimg cfg_create dtbo.img dtboimg.cfg</code> </pre> <p><code>mkdtimg</code> does not handle alignment for @@ -278,8 +278,8 @@ useful when using different hardware with identical DTs.</p> <h3 id=dump>dump</h3> <p>For <code>dtb</code>/<code>dtbo</code> images, use the <code>dump</code> command to print the information in the image. Example:</p> -<pre class="prettyprint"> -$mkdtimg dump dtbo.img +<pre class="devsite-click-to-copy"> +<code class="devsite-terminal">mkdtimg dump dtbo.img</code> dt_table_header: magic = d7b7ab1e total_size = 1300 diff --git a/en/devices/architecture/hidl/services.html b/en/devices/architecture/hidl/services.html index 647555b7..75933ec9 100644 --- a/en/devices/architecture/hidl/services.html +++ b/en/devices/architecture/hidl/services.html @@ -51,8 +51,12 @@ into the server.</p> version, calling <code>getService</code> on the desired HAL class:</p> <pre class="prettyprint"> +// C++ sp<V1_1::IFooService> service = V1_1::IFooService::getService(); sp<V1_1::IFooService> alternateService = 1_1::IFooService::getService("another_foo_service"); +// Java +V1_1.IFooService; service = V1_1.IFooService.getService(true /* retry */); +V1_1.IFooService; alternateService = 1_1.IFooService.getService("another", true /* retry */); </pre> <p>Each version of a HIDL interface is treated as a separate interface. Thus, @@ -69,6 +73,16 @@ returned interface. For an interface <code>IFoo</code> in package <code>android.hardware.foo</code> in the device manifest if the entry exists; and if the transport method is not available, nullptr is returned.</p> +<p> In some cases, it may be necessary to continue immediately even without +getting the service. This can happen (for instance) when a client wants to +manage service notifications itself or in a diagnostic program (such as +<code>atrace</code>) which needs to get all hwservices and retrieve them. In +this case, additional APIs are provided such as <code>tryGetService</code> in C++ or +<code>getService("instance-name", false)</code> in Java. The legacy API +<code>getService</code> provided in Java also must be used with service +notifications. Using this API does not avoid the race condition where a server +registers itself after the client requests it with one of these no-retry APIs.</p> + <h2 id=death>Service death notifications</h2> <p>Clients who want to be notified when a service dies can receive death notifications delivered by the framework. To receive notifications, the client diff --git a/en/devices/architecture/images/android-diffs.png b/en/devices/architecture/images/android-diffs.png Binary files differnew file mode 100644 index 00000000..312718cb --- /dev/null +++ b/en/devices/architecture/images/android-diffs.png diff --git a/en/devices/architecture/images/kernel_branch_hierarchy_44.png b/en/devices/architecture/images/kernel_branch_hierarchy_44.png Binary files differnew file mode 100644 index 00000000..ab749e87 --- /dev/null +++ b/en/devices/architecture/images/kernel_branch_hierarchy_44.png diff --git a/en/devices/architecture/images/kernel_lts_diff.png b/en/devices/architecture/images/kernel_lts_diff.png Binary files differnew file mode 100644 index 00000000..cbd9fafa --- /dev/null +++ b/en/devices/architecture/images/kernel_lts_diff.png diff --git a/en/devices/architecture/kernel/android-common.html b/en/devices/architecture/kernel/android-common.html new file mode 100644 index 00000000..13175576 --- /dev/null +++ b/en/devices/architecture/kernel/android-common.html @@ -0,0 +1,170 @@ +<html devsite> + <head> + <title>Android Common Kernels</title> + <meta name="project_path" value="/_project.yaml" /> + <meta name="book_path" value="/_book.yaml" /> + </head> + <body> + <!-- + Copyright 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + + +<p>The +<a href="https://android.googlesource.com/kernel/common/" class="external">AOSP +common kernels</a> are downstream of Long Term Supported (LTS) kernels and +include patches of interest to the Android community that have not been merged +into LTS. These patches can include:</p> + +<ul> +<li>Features tailored for Android needs (e.g. interactive <code>cpufreq</code> +governor).</li> +<li>Features rejected by upstream due to implementation concerns (e.g. MTP/PTP, +paranoid networking).</li> +<li>Features ready for Android devices but still under development upstream +(e.g. Energy Aware Scheduling/EAS).</li> +<li>Vendor/OEM features that are useful for others (e.g. <code>sdcardfs</code>). +</li> +</ul> + +<h2 id="list-of-kernels">List of common kernels</h2> +<p>To view a list of Android common kernels, refer to +<a href="https://android.googlesource.com/kernel/common/" class=external>https://android.googlesource.com/kernel/common/</a> +(shown below).</p> +<p><img src="../images/android-diffs.png"></p> +<p class="img-caption"><strong>Figure 1.</strong> List of Android common +kernels.</p> + +<h3 id="differences-lts">Differences from LTS</h3> +<p>When compared to LTS (4.4.40), the Android common kernel has 679 changes, +56172 insertions, and 3340 deletions (as of February 2017).</p> + +<p><img src="../images/kernel_lts_diff.png"></p> +<p class="img-caption"><strong>Figure 2.</strong> Android-specific code over +time.</p> + +<p>The largest features include:</p> +<ul> +<li>13.8% SoC (arch/arm64, arch/x86)</li> +<li>9.2% USB (drivers/usb)</li> +<li>8.2% Energy Aware Scheduling (kernel/sched)</li> +<li>8.2% Atomic Display Framework (drivers/video/adf)</li> +<li>8.0% networking (net/netfilter)</li> +<li>6.2% sdcardfs (fs/sdcardfs)</li> +<li>5.0% Verity (drivers/md)</li> +<li>3.7% Input (drivers/input/misc)</li> +<li>3.3% FIQ Debugger (drivers/staging/android/fiq_debugger)</li> +<li>2.4% Cpufreq (drivers/cpufreq)</li> +<li>2.2% Goldfish Emulator (drivers/platform/goldfish)</li> +</ul> + +<h2 id="requirements">Requirements</h2> +<p>All AOSP common kernels must provide the following:</p> +<ul> +<li>Method for downstream partners to get timely updates that include all +LTS patches.</li> +<li>Mechanism to guarantee that new feature development does not interfere with +merging from AOSP common (even for previous Android releases).</li> +<li>Method for downstream partners to easily identify security patches that are +part of an <a href="/security/bulletin/">Android Security Bulletin (ASB)</a>. +This satisfies carriers who require a full requalification if OEMs attempt to +include patches beyond those listed in the bulletin.</li> +</ul> +<p>In addition, regular testing must be performed on AOSP common kernels and +branches must be tagged when passing.</p> + +<h3 id="lts-merges">LTS merges</h3> +<p>To ensure downstream partners can get timely updates that include all LTS +patches, android-<var>X</var>.<var>Y</var> gets regular merges from LTS and is +validated via automated VTS, CTS, and build/boot tests.</p> + +<h3 id="android-dessert-branches">Android-dessert branches</h3> +<p>To guarantee that new feature development does not interfere with merging +from the AOSP common kernel (even for previous Android releases), +android-<var>X</var>.<var>Y</var>-<var>androidRel</var> is cloned from +android-<var>X</var>.<var>Y</var> prior to the initial dessert release, gets regular +merges from LTS, and is tested against the associated Android release. For +example, the android-4.4-n branch gets merges from the LTS 4.4.y branch. </p> + +<h3 id="android-release-branches">Android-release branches</h3> +<p>To ensure downstream partners can easily identify security patches that are +part of an ASB, +android-<var>X</var>.<var>Y</var>-<var>androidRel</var>-<var>type</var> is +cloned from android-<var>X</var>.<var>Y</var>-<var>androidRel</var> at the time +of the Android release and gets only the patches listed in the bulletin.</p> + +<p>After the patches associated with a bulletin are confirmed to be merged +into a release branch, the branch is tagged with the ASB level. For example, the +tag <strong>ASB-2017-10-05</strong> indicates the release branch contains +patches from the Android Security Bulletin for October 5th, 2017. Parent +branches contain those security patches, so if the android-4.4-o-release branch +is tagged with <strong>ASB-2017-10-01</strong>, android-4.4-o and android-4.4 +are also up-to-date with that bulletin. Example:</p> +<ul> +<li>Before releasing Android N MR1, <strong>android-4.4-n-mr1</strong> is cloned +from <strong>android-4.4-n</strong>.</li> +<li>Only patches listed in ASBs are merged, allowing OEMs (who have strict +requirements from carriers to avoid full qualification on security updates) to +find the patches listed in the bulletin.</li> +<li><strong>android-4.4-n-mr2</strong> will be +<strong>android-4.4-n-mr1</strong> plus LTS patches that were merged between the +releases.</li> +<li>Each month when the ASB is released publicly, the release branches are +updated with any patches cited in the bulletin that are upstream +(device-specific patches cited in the bulletin are not applied to the common +kernels).</li> +</ul> + +<h3 id="regular-testing">Regular testing</h3> +<p>Regular testing is performed on all on AOSP common kernels and test results +are available to the public. Specifically:</p> +<ul> +<li>After LTS updates or other patches are merged, VTS and a subset of CTS +is run and results are made available at +<a href="https://qa-reports.linaro.org/lkft" class="external">https://qa-reports.linaro.org/lkft</a>. +</li> +<li>To continually test for build/boot breaks in a variety of architectures and +builds, <code>kernelci</code> is run and results are made available at +<a href="https://kernelci.org/job/android/" class="external">https://kernelci.org/job/android</a>. +</li> +</ul> + +<h3 id="branch-hierarchy">Branch hierarchy (android-4.4)</h3> +<p>The branch hierarchy for the android-4.4 kernel uses the following structure: +</p> + +<p><img src="../images/kernel_branch_hierarchy_44.png"></p> +<p class="img-caption"><strong>Figure 3.</strong> Branch hierarchy for the +android-4.4 kernel.</p> + +<h2 id="guidelines">Guidelines</h2> +<p>Android implementations should use the following kernel guidelines:</p> +<ul> +<li>Use the new AOSP common kernels as upstream merge sources.<ul> +<li>To get patches from LTS, merge from android-<var>X</var>.<var>Y</var>.<ul> +<li>Merge regularly during development phase.</li> +<li>When updating device to a new Android release, merge either from the +android-<var>X</var>.<var>Y</var> branch or the release branch for the target +release (e.g. for an update to Nougat MR2, merge from the android-4.4-n-mr2 +branch).</li> +</ul> +<li>When constrained by the carrier for a security release, merge from release +branches for security updates.</li> +</ul> +<li>Send fixes upstream to mainline, LTS, or AOSP common.</li> +</ul> + + </body> +</html> diff --git a/en/devices/tech/admin/enterprise-telephony.html b/en/devices/tech/admin/enterprise-telephony.html index 39a870c2..aee11f3a 100644 --- a/en/devices/tech/admin/enterprise-telephony.html +++ b/en/devices/tech/admin/enterprise-telephony.html @@ -75,19 +75,20 @@ for contacts in their Dialer Contacts and SMS/MMS Messaging apps.</p> <p> Cross profile contact search should be implemented using the Enterprise Contacts -API (<code>ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI</code> etc.) -see <a -href="http://developer.android.com/preview/features/afw.html#contacts">http://developer.android.com/preview/features/afw.html#contacts</a> +API (<code>ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI</code> etc.), which can be found +in the <a +href="http://developer.android.com/preview/features/afw.html#contacts">EMM developer's overview</a> +on the Android EMM Developers site. </p> <h3 id="work-profile-contact-badging">Work profile contact badging</h3> <p> Work profile contact badging can be implemented by checking -<code>ContactsContract.Directory.isEntepriseDirectoryId() </code>if available or -<a -href="http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html#isEnterpriseContactId(long)">http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html#isEnterpriseContactId(long)</a> -<code> </code> +<code>ContactsContract.Directory.isEntepriseDirectoryId()</code> if available or +<code><a +href="http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html#isEnterpriseContactId(long)">isEnterpriseContactId</a></code> +. </p> <h3 id="managed-profile-aware-connectionservice">Managed Profile Aware diff --git a/en/devices/tech/config/perms-whitelist.html b/en/devices/tech/config/perms-whitelist.html index 79f03263..0ec1f21c 100644 --- a/en/devices/tech/config/perms-whitelist.html +++ b/en/devices/tech/config/perms-whitelist.html @@ -76,8 +76,7 @@ </p> <pre - class="prettyprint">development/tools/privapp_permissions/privapp_permissions.py - </pre> + class="prettyprint">development/tools/privapp_permissions/privapp_permissions.py</pre> <p> To generate an initial version of device-specific @@ -86,15 +85,16 @@ </p> <ol> <li>Build a system image, as follows:<br> - <pre>$ . build/envsetup.sh -$ lunch product_name -$ make -j</pre> + <pre class="devsite-click-to-copy"> +<code class="devsite-terminal">. build/envsetup.sh</code> +<code class="devsite-terminal">lunch product_name</code> +<code class="devsite-terminal">make -j</code></pre> </li> <li>Run the following tool to generate a <code>privapp-permissions.xml </code>file that lists all signature|privileged permissions that are required to - be whitelisted.<br> - <pre>$ development/tools/privapp_permissions/privapp_permissions.py</pre><br> + be whitelisted.<br /> + <pre class="devsite-terminal devsite-click-to-copy">development/tools/privapp_permissions/privapp_permissions.py</pre> This tool prints XML content that can be used as a single file or split into multiple files in <code>/etc/permissions</code>.<br><br> diff --git a/en/devices/tech/debug/index.html b/en/devices/tech/debug/index.html index 67b2fee2..1c493637 100644 --- a/en/devices/tech/debug/index.html +++ b/en/devices/tech/debug/index.html @@ -159,7 +159,7 @@ directly without taking up anywhere near as much space as an unstripped version. <p>You can also <code>stack</code> an entire tombstone. Example:</p> <pre class="devsite-terminal devsite-click-to-copy"> -stack < FS/data/tombstones/tombstone_05</code> +stack < FS/data/tombstones/tombstone_05</code> </pre> <p>This is useful if you've just unzipped a bugreport in the current directory. For more information about diagnosing native crashes and tombstones, see diff --git a/en/devices/tech/ota/ab_updates.html b/en/devices/tech/ota/ab_updates.html index c63f6714..5dc04c2a 100644 --- a/en/devices/tech/ota/ab_updates.html +++ b/en/devices/tech/ota/ab_updates.html @@ -21,730 +21,882 @@ limitations under the License. --> -<p>A/B system updates, also known as seamless updates, ensure a workable booting -system remains on the disk during an -<a href="/devices/tech/ota/index.html">over-the-air (OTA) update</a>. This -approach reduces the likelihood of an inactive device after an update, which -means fewer device replacements and device reflashes at repair and warranty -centers. Other commercial-grade operating systems such as -<a href="https://www.chromium.org/chromium-os">ChromeOS</a> also use A/B updates -successfully.</p> - -<p>A/B system updates provide the following benefits:</p> - -<ul> -<li>OTA updates can occur while the system is running, without interrupting the -user (including app optimizations that occur after a reboot). This means users -can continue to use their devices during an OTA—the only downtime during -an update is when the device reboots into the updated disk partition.</li> -<li>If an OTA fails, the device boots into the pre-OTA disk partition and -remains usable. The download of the OTA can be attempted again.</li> -<li>Any errors (such as I/O errors) affect only the <strong>unused</strong> -partition set and can be retried. Such errors also become less likely because -the I/O load is deliberately low to avoid degrading the user experience.</li> -<li>Updates can be streamed to A/B devices, removing the need to download the -package before installing it. Streaming means it's not necessary for the -user to have enough free space to store the update package on <code>/data</code> -or <code>/cache</code>. -<li>The cache partition is no longer used to store OTA update packages, so there -is no need for sizing the cache partition.</li> -<li><a href="/security/verifiedboot/dm-verity.html">dm-verity</a> guarantees a -device will boot an uncorrupted image. If a device doesn't boot due to a bad OTA -or dm-verity issue, the device can reboot into an old image. (Android -<a href="/security/verifiedboot/">Verified Boot</a> does not require A/B -updates.)</li> -</ul> - -<h2 id=overview>About A/B system updates</h2> - -<p>A/B system updates affect the following:</p> - -<ul> -<li>Partition selection (slots), the <code>update_engine</code> daemon, and -bootloader interactions (described below)</li> -<li>Build process and OTA update package generation (described in -<a href="/devices/tech/ota/ab_implement.html">Implementing A/B Updates</a>)</li> -</ul> - -<aside class="note"><strong>Note:</strong> A/B system updates implemented through -OTA are recommended for new devices only.</aside> - -<h3 id=slots>Partition selection (slots)</h3> - -<p>A/B system updates use two sets of partitions referred to as <em>slots</em> -(normally slot A and slot B). The system runs from the <em>current</em> slot -while the partitions in the <em>unused</em> slot are not accessed by the running -system during normal operation. This approach makes updates fault resistant by -keeping the unused slot as a fallback: If an error occurs during or immediately -after an update, the system can rollback to the old slot and continue to have a -working system. To achieve this goal, no partition used by the <em>current</em> -slot should be updated as part of the OTA update (including partitions for which -there is only one copy).</p> - -<p>Each slot has a <em>bootable</em> attribute that states whether the slot -contains a correct system from which the device can boot. The current slot is -bootable when the system is running, but the other slot may have an old (still -correct) version of the system, a newer version, or invalid data. Regardless of -what the <em>current</em> slot is, there is one slot that is the <em>active</em> -slot (the one the bootloader will boot form on the next boot) or the -<em>preferred</em> slot.</p> - -Each slot also has a <em>successful</em> attribute set by the user space, which -is relevant only if the slot is also bootable. A successful slot should be able -to boot, run, and update itself. A bootable slot that was not marked as -successful (after several attempts were made to boot from it) should be marked -as unbootable by the bootloader, including changing the active slot to another -bootable slot (normally to the slot running immediately before the attempt to -boot into the new, active one). The specific details of the interface are -defined in -<code><a href="https://android.googlesource.com/platform/hardware/libhardware/+/master/include/hardware/boot_control.h" class="external-link">boot_control.h</a></code>. -</p> - -<h3 id="update-engine">Update engine daemon</h3> - -<p>A/B system updates use a background daemon called <code>update_engine</code> -to prepare the system to boot into a new, updated version. This daemon can -perform the following actions:</p> - -<ul> -<li>Read from the current slot A/B partitions and write any data to the unused -slot A/B partitions as instructed by the OTA package.</li> -<li>Call the <code>boot_control</code> interface in a pre-defined workflow.</li> -<li>Run a <em>post-install</em> program from the <em>new</em> partition after -writing all the unused slot partitions, as instructed by the OTA package. (For -details, see <a href="#post-installation">Post-installation</a>).</li> -</ul> - -<p>As the <code>update_engine</code> daemon is not involved in the boot process -itself, it is limited in what it can do during an update by the -<a href="/security/selinux/">SELinux</a> policies and features in the -<em>current</em> slot (such policies and features can't be updated until the -system boots into a new version). To maintain a robust system, the update -process <strong>should not</strong> modify the partition table, the contents of -partitions in the current slot, or the contents of non-A/B partitions that can't -be wiped with a factory reset.</p> - -<p>The <code>update_engine</code> source is located in -<code><a href="https://android.googlesource.com/platform/system/update_engine/" class="external">system/update_engine</a></code>. -The A/B OTA dexopt files are split between <code>installd</code> and a package -manager:</p> -<ul> -<li><code><a href="https://android.googlesource.com/platform/frameworks/native/+/master/cmds/installd/" class="external-link">frameworks/native/cmds/installd/</a></code>ota* -includes the postinstall script, the binary for chroot, the installd clone that -calls dex2oat, the post-OTA move-artifacts script, and the rc file for the move -script.</li> -<li><code><a href="https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/pm/OtaDexoptService.java" class="external-link">frameworks/base/services/core/java/com/android/server/pm/OtaDexoptService.java</a></code> -(plus <code><a href="https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java" class="external-link">OtaDexoptShellCommand</a></code>) -is the package manager that prepares dex2oat commands for applications.</li> -</ul> - -<p>For a working example, refer to -<code><a href="https://android.googlesource.com/device/google/marlin/+/nougat-dr1-release/device-common.mk" class="external-link">/device/google/marlin/device-common.mk</a></code>. -</p> - -<h3 id="bootloader-interactions">Bootloader interactions</h3> - -<p>The <code>boot_control</code> HAL is used by <code>update_engine</code> (and -possibly other daemons) to instruct the bootloader what to boot from. Common -example scenarios and their associated states include the following:</p> - -<ul> - <li> - <strong>Normal case</strong>: The system is running from its current slot, - either slot A or B. No updates have been applied so far. The system's - current slot is bootable, successful, and the active slot. - </li> - <li> - <strong>Update in progress</strong>: The system is running from slot B, so - slot B is the bootable, successful, and active slot. Slot A was marked as - unbootable since the contents of slot A are being updated but not yet - completed. A reboot in this state should continue booting from slot B. - </li> - <li> - <strong>Update applied, reboot pending</strong>: The system is running from - slot B, slot B is bootable and successful, but slot A was marked as active - (and therefore is marked as bootable). Slot A is not yet marked as - successful and some number of attempts to boot from slot A should be made by - the bootloader. - </li> - <li> - <strong>System rebooted into new update</strong>: The system is running from - slot A for the first time, slot B is still bootable and successful while - slot A is only bootable, and still active but not successful. A user space - daemon should mark slot A as successful after some checks are made. - </li> -</ul> - -<h3 id="streaming-updates">Streaming update support</h3> -<p>User devices don't always have enough space on <code>/data</code> to download -the update package. As neither OEMs nor users want to waste space on a -<code>/cache</code> partition, some users go without updates because the device -has nowhere to store the update package. To address this issue, Android 8.0 -added support for streaming A/B updates that write blocks directly to the B -partition as they are downloaded, without having to store the blocks on -<code>/data</code>. Streaming A/B updates need almost no temporary storage and -require just enough storage for roughly 100 KiB of metadata.</p> - -<p>To enable streaming updates in Android 7.1, cherrypick the following -patches:</p> -<ul> -<li> -<a href="https://android-review.googlesource.com/333624" class="external">Allow -to cancel a proxy resolution request</a></li> -<li> -<a href="https://android-review.googlesource.com/333625" class="external">Fix -terminating a transfer while resolving proxies</a></li> -<li> -<a href="https://android-review.googlesource.com/333626" class="external">Add -unittest for TerminateTransfer between ranges</a></li> -<li> -<a href="https://android-review.googlesource.com/333627" class="external">Cleanup -the RetryTimeoutCallback()</a></li> -</ul> - -<p>These patches are required to support streaming A/B updates in Android 7.1 -whether using <a href="https://www.android.com/gms/">Google Mobile Services -(GMS)</a> or any other update client.</p> - -<h2 id="life-of-an-a-b-update">Life of an A/B update</h2> - -<p>The update process starts when an OTA package (referred to in code as a -<em>payload</em>) is available for downloading. Policies in the device may defer -the payload download and application based on battery level, user activity, -charging status, or other policies. In addition, because the update runs in the -background, users might not know an update is in progress. All of this means the -update process might be interrupted at any point due to policies, unexpected -reboots, or user actions.</p> - -<p>Optionally, metadata in the OTA package itself indicates the update can be -streamed; the same package can also be used for non-streaming installation. The -server may use the metadata to tell the client it's streaming so the client will -hand off the OTA to <code>update_engine</code> correctly. Device manufacturers -with their own server and client can enable streaming updates by ensuring the -server identifies the update is streaming (or assumes all updates are streaming) -and the client makes the correct call to <code>update_engine</code> for -streaming. Manufacturers can use the fact that the package is of the streaming -variant to send a flag to the client to trigger hand off to the framework side -as streaming.</p> - -<p>After a payload is available, the update process is as follows:</p> - -<table> -<tr> -<th>Step</th> -<th>Activities</th> -</tr> -<tr> -<td>1</td> -<td>The current slot (or "source slot") is marked as successful (if not already -marked) with <code>markBootSuccessful()</code>.</td> -</tr> -<tr> -<td>2</td> -<td>The unused slot (or "target slot") is marked as unbootable by calling the -function <code>setSlotAsUnbootable()</code>. The current slot is always marked -as successful at the beginning of the update to prevent the bootloader from -falling back to the unused slot, which will soon have invalid data. If the -system has reached the point where it can start applying an update, the current -slot is marked as successful even if other major components are broken (such as -the UI in a crash loop) as it is possible to push new software to fix these -problems. -<br><br> -The update payload is an opaque blob with the instructions to update to the new -version. The update payload consists of the following: -<ul> -<li><em>Metadata</em>. A relatively small portion of the update payload, the -metadata contains a list of operations to produce and verify the new version on -the target slot. For example, an operation could decompress a certain blob and -write it to specific blocks in a target partition, or read from a source -partition, apply a binary patch, and write to certain blocks in a target -partition.</li> -<li><em>Extra data</em>. As the bulk of the update payload, the extra data -associated with the operations consists of the compressed blob or binary patch -in these examples.</li> -</ul> -</td> -</tr> -<tr> -<td>3</td> -<td>The payload metadata is downloaded.</td> -</tr> -<tr> -<td>4</td> -<td>For each operation defined in the metadata, in order, the associated data -(if any) is downloaded to memory, the operation is applied, and the associated -memory is discarded.</td> -</tr> -<tr> -<td>5</td> -<td>The whole partitions are re-read and verified against the expected hash. -</td> -</tr> -<tr> -<td>6</td> -<td>The post-install step (if any) is run. In the case of an error during the -execution of any step, the update fails and is re-attempted with possibly a -different payload. If all the steps so far have succeeded, the update succeeds -and the last step is executed.</td> -</tr> -<tr> -<td>7</td> -<td>The <em>unused slot</em> is marked as active by calling -<code>setActiveBootSlot()</code>. Marking the unused slot as active doesn't mean -it will finish booting. The bootloader (or system itself) can switch the active -slot back if it doesn't read a successful state.</td> -</tr> -<tr> -<td>8</td> -<td>Post-installation (described below) involves running a program from the -"new update" version while still running in the old version. If defined in the -OTA package, this step is <strong>mandatory</strong> and the program must return -with exit code <code>0</code>; otherwise, the update fails.</td> -</tr> -</table> - -<aside class="note"><strong>Note:</strong> Steps 3 and 4 take most of the update -time as they involve writing and downloading large amounts of data, and are -likely to be interrupted for reasons of policy or reboot.</aside> - -<h3 id="post-installation">Post-installation</h3> - -<p>For every partition where a post-install step is defined, -<code>update_engine</code> mounts the new partition into a specific location and -executes the program specified in the OTA relative to the mounted partition. For -example, if the post-install program is defined as -<code>usr/bin/postinstall</code> in the system partition, this partition from -the unused slot will be mounted in a fixed location (such as -<code>/postinstall_mount</code>) and the -<code>/postinstall_mount/usr/bin/postinstall</code> command is executed.</p> - -<p>For post-installation to succeed, the old kernel must be able to:</p> - -<ul> -<li><strong>Mount the new filesystem format</strong>. The filesystem type cannot -change unless there's support for it in the old kernel, including details such -as the compression algorithm used if using a compressed filesystem (i.e. -SquashFS).</li> -<li><strong>Understand the new partition's post-install program format</strong>. -If using an Executable and Linkable Format (ELF) binary, it should be compatible -with the old kernel (e.g. a 64-bit new program running on an old 32-bit kernel -if the architecture switched from 32- to 64-bit builds). Unless the loader -(<code>ld</code>) is instructed to use other paths or build a static binary, -libraries will be loaded from the old system image and not the new one.</li> -</ul> - -<p>For example, you could use a shell script as a post-install program -(interpreted by the old system's shell binary with a <code>#!</code> marker at -the top), then set up library paths from the new environment for executing a -more complex binary post-install program. Alternatively, you could run the -post-install step from a dedicated smaller partition to enable the filesystem -format in the main system partition to be updated without incurring backward -compatibility issues or stepping-stone updates; this would allow users to update -directly to the latest version from a factory image.</p> - -<p>The new post-install program is limited by the SELinux policies defined in -the old system. As such, the post-install step is suitable for performing tasks -required by design on a given device or other best-effort tasks (i.e. updating -the A/B-capable firmware or bootloader, preparing copies of databases for the -new version, etc.). The post-install step is <strong>not suitable</strong> for -one-off bug fixes before reboot that require unforeseen permissions.</p> - -<p>The selected post-install program runs in the <code>postinstall</code> -SELinux context. All the files in the new mounted partition will be tagged with -<code>postinstall_file</code>, regardless of what their attributes are after -rebooting into that new system. Changes to the SELinux attributes in the new -system won't impact the post-install step. If the post-install program needs -extra permissions, those must be added to the post-install context.</p> - -<h2 id=faq>Frequently asked questions</h2> - -<h3>Has Google used A/B OTAs on any devices?</h3> - -<p>Yes. The marketing name for A/B updates is <em>seamless updates</em>. Pixel -and Pixel XL phones from October 2016 shipped with A/B, and all Chromebooks use -the same <code>update_engine</code> implementation of A/B. The necessary -platform code implementation is public in Android 7.1 and higher.</p> - -<h3>Why are A/B OTAs better?</h3> - -<p>A/B OTAs provide a better user experience when taking updates. Measurements -from monthly security updates show this feature has already proven a success: As -of May 2017, 95% of Pixel owners are running the latest security update after a -month compared to 87% of Nexus users, and Pixel users update sooner than Nexus -users. Failures to update blocks during an OTA no longer result in a device that -won't boot; until the new system image has successfully booted, Android retains -the ability to fall back to the previous working system image.</p> - -<h3>How did A/B affect the 2016 Pixel partition sizes?</h3> - -<p>The following table contains details on the shipping A/B configuration versus -the internally-tested non-A/B configuration:</p> - -<table> - <tbody> - <tr> - <th>Pixel partition sizes</th> - <th width="33%">A/B</th> - <th width="33%">Non-A/B</th> - </tr> - <tr> - <td>Bootloader</td> - <td>50*2</td> - <td>50</td> - </tr> - <tr> - <td>Boot</td> - <td>32*2</td> - <td>32</td> - </tr> - <tr> - <td>Recovery</td> - <td>0</td> - <td>32</td> - </tr> - <tr> - <td>Cache</td> - <td>0</td> - <td>100</td> - </tr> - <tr> - <td>Radio</td> - <td>70*2</td> - <td>70</td> - </tr> - <tr> - <td>Vendor</td> - <td>300*2</td> - <td>300</td> - </tr> - <tr> - <td>System</td> - <td>2048*2</td> - <td>4096</td> - </tr> - <tr> - <td><strong>Total</strong></td> - <td><strong>5000</strong></td> - <td><strong>4680</strong></td> - </tr> - </tbody> -</table> - -<p>A/B updates require an increase of only 320 MiB in flash, with a savings of -32MiB from removing the recovery partition and another 100MiB preserved by -removing the cache partition. This balances the cost of the B partitions for -the bootloader, the boot partition, and the radio partition. The vendor -partition doubled in size (the vast majority of the size increase). Pixel's -A/B system image is half the size of the original non-A/B system image. -</p> - -<p>For the Pixel A/B and non-A/B variants tested internally (only A/B shipped), -the space used differed by only 320MiB. On a 32GiB device, this is just under -1%. For a 16GiB device this would be less than 2%, and for an 8GiB device almost -4% (assuming all three devices had the same system image).</p> - -<h3>Why didn't you use SquashFS?</h3> - -<p>We experimented with SquashFS but weren't able to achieve the performance -desired for a high-end device. We don't use or recommend SquashFS for handheld -devices.</p> - -<p>More specifically, SquashFS provided about 50% size savings on the system -partition, but the overwhelming majority of the files that compressed well were -the precompiled .odex files. Those files had very high compression ratios -(approaching 80%), but the compression ratio for the rest of the system -partition was much lower. In addition, SquashFS in Android 7.0 raised the -following performance concerns:</p> - -<ul> - <li>Pixel has very fast flash compared to earlier devices but not a huge - number of spare CPU cycles, so reading fewer bytes from flash but needing - more CPU for I/O was a potential bottleneck.</li> - <li>I/O changes that perform well on an artificial benchmark run on an - unloaded system sometimes don't work well on real-world use cases under - real-world load (such as crypto on Nexus 6).</li> - <li>Benchmarking showed 85% regressions in some places.</li> - </ul> - -<p>As SquashFS matures and adds features to reduce CPU impact (such as a -whitelist of commonly-accessed files that shouldn't be compressed), we will -continue to evaluate it and offer recommendations to device manufacturers.</p> - -<h3>How did you halve the size of the system partition without SquashFS?</h3> - -<p>Applications are stored in .apk files, which are actually ZIP archives. Each -.apk file has inside it one or more .dex files containing portable Dalvik -bytecode. An .odex file (optimized .dex) lives separately from the .apk file -and can contain machine code specific to the device. If an .odex file is -available, Android can run applications at ahead-of-time compiled speeds -without having to wait for the code to be compiled each time the application is -launched. An .odex file isn't strictly necessary: Android can actually run the -.dex code directly via interpretation or Just-In-Time (JIT) compilation, but an -.odex file provides the best combination of launch speed and run-time speed if -space is available.</p> - -<p>Example: For the installed-files.txt from a Nexus 6P running Android 7.1 with -a total system image size of 2628MiB (2755792836 bytes), the breakdown of the -largest contributors to overall system image size by file type is as follows: -</p> - -<table> -<tbody> -<tr> -<td>.odex</td> -<td>1391770312 bytes</td> -<td>50.5%</td> -</tr> -<tr> -<td>.apk</td> -<td>846878259 bytes</td> -<td>30.7%</td> -</tr> -<tr> -<td>.so (native C/C++ code)</td> -<td>202162479 bytes</td> -<td>7.3%</td> -</tr> -<tr> -<td>.oat files/.art images</td> -<td>163892188 bytes</td> -<td>5.9%</td> -</tr> -<tr> -<td>Fonts</td> -<td>38952361 bytes</td> -<td>1.4%</td> -</tr> -<tr> -<td>icu locale data</td> -<td>27468687 bytes</td> -<td>0.9%</td> -</tr> -</tbody> -</table> - -<p>These figures are similar for other devices too, so on Nexus/Pixel -devices, .odex files take up approximately half the system partition. This meant -we could continue to use ext4 but write the .odex files to the B partition -at the factory and then copy them to <code>/data</code> on first boot. The -actual storage used with ext4 A/B is identical to SquashFS A/B, because if we -had used SquashFS we would have shipped the preopted .odex files on system_a -instead of system_b.</p> - -<h3>Doesn't copying .odex files to /data mean the space saved on /system is -lost on /data?</h3> - -<p>Not exactly. On Pixel, most of the space taken by .odex files is for apps, -which typically exist on <code>/data</code>. These apps take Google Play -updates, so the .apk and .odex files on the system image are unused for most of -the life of the device. Such files can be excluded entirely and replaced by -small, profile-driven .odex files when the user actually uses each app (thus -requiring no space for apps the user doesn't use). For details, refer to the -Google I/O 2016 talk <a href="https://www.youtube.com/watch?v=fwMM6g7wpQ8">The -Evolution of Art</a>.</p> - -<p>The comparison is difficult for a few key reasons:</p> -<ul> -<li>Apps updated by Google Play have always had their .odex files on -<code>/data</code> as soon as they receive their first update.</li> -<li>Apps the user doesn't run don't need an .odex file at all.</li> -<li>Profile-driven compilation generates smaller .odex files than ahead-of-time -compilation (because the former optimizes only performance-critical code).</li> -</ul> - -<p>For details on the tuning options available to OEMs, see -<a href="/devices/tech/dalvik/configure.html">Configuring ART</a>.</p> - -<h3>Aren't there two copies of the .odex files on /data?</h3> - -<p>It's a little more complicated ... After the new system image has been -written, the new version of dex2oat is run against the new .dex files to -generate the new .odex files. This occurs while the old system is still running, -so the old and new .odex files are both on <code>/data</code> at the same time. -</p> - -<p>The code in OtaDexoptService -(<code><a href="https://android.googlesource.com/platform/frameworks/base/+/nougat-mr1-release/services/core/java/com/android/server/pm/OtaDexoptService.java#200" class="external">frameworks/base/+/nougat-mr1-release/services/core/java/com/android/server/pm/OtaDexoptService.java#200</a></code>) -calls <code>getAvailableSpace</code> before optimizing each package to avoid -over-filling <code>/data</code>. Note that <em>available</em> here is still -conservative: it's the amount of space left <em>before</em> hitting the usual -system low space threshold (measured as both a percentage and a byte count). So -if <code>/data</code> is full, there won't be two copies of every .odex file. -The same code also has a BULK_DELETE_THRESHOLD: If the device gets that close -to filling the available space (as just described), the .odex files belonging to -apps that aren't used are removed. That's another case without two copies of -every .odex file.</p> - -<p>In the worst case where <code>/data</code> is completely full, the update -waits until the device has rebooted into the new system and no longer needs the -old system's .odex files. The PackageManager handles this: -(<code><a href="https://android.googlesource.com/platform/frameworks/base/+/nougat-mr1-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215" class="external">frameworks/base/+/nougat-mr1-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215</a></code>). After the new system has -successfully booted, <code>installd</code> -(<code><a href="https://android.googlesource.com/platform/frameworks/native/+/nougat-mr1-release/cmds/installd/commands.cpp#2192" class="external">frameworks/native/+/nougat-mr1-release/cmds/installd/commands.cpp#2192</a></code>) -can remove the .odex files that were used by the old system, returning the -device back to the steady state where there's only one copy.</p> - -<p>So, while it is possible that <code>/data</code> contains two copies of all -the .odex files, (a) this is temporary and (b) only occurs if you had plenty of -free space on <code>/data</code> anyway. Except during an update, there's only -one copy. And as part of ART's general robustness features, it will never fill -<code>/data</code> with .odex files anyway (because that would be a problem on a -non-A/B system too).</p> - -<h3>Doesn't all this writing/copying increase flash wear?</h3> - -<p>Only a small portion of flash is rewritten: a full Pixel system update -writes about 2.3GiB. (Apps are also recompiled, but that's true of non-A/B -too.) Traditionally, block-based full OTAs wrote a similar amount of data, so -flash wear rates should be similar.</p> - -<h3>Does flashing two system partitions increase factory flashing time?</h3> - -<p>No. Pixel didn't increase in system image size (it merely divided the space -across two partitions).</p> - -<h3>Doesn't keeping .odex files on B make rebooting after factory data reset -slow?</h3> - -<p>Yes. If you've actually used a device, taken an OTA, and performed a factory -data reset, the first reboot will be slower than it would otherwise be (1m40s vs -40s on a Pixel XL) because the .odex files will have been lost from B after the -first OTA and so can't be copied to <code>/data</code>. That's the trade-off.</p> - -<p>Factory data reset should be a rare operation when compared to regular boot -so the time taken is less important. (This doesn't affect users or reviewers who -get their device from the factory, because in that case the B partition is -available.) Use of the JIT compiler means we don't need to recompile -<em>everything</em>, so it's not as bad as you might think. It's also possible -to mark apps as requiring ahead-of-time compilation using -<code>coreApp="true"</code> in the manifest: -(<code><a href="https://android.googlesource.com/platform/frameworks/base/+/nougat-mr1-release/packages/SystemUI/AndroidManifest.xml#23" class="external">frameworks/base/+/nougat-mr1-release/packages/SystemUI/AndroidManifest.xml#23</a></code>). -This is currently used by <code>system_server</code> because it's not allowed to -JIT for security reasons.</p> - -<h3>Doesn't keeping .odex files on /data rather than /system make rebooting -after an OTA slow?</h3> - -<p>No. As explained above, the new dex2oat is run while the old system image is -still running to generate the files that will be needed by the new system. The -update isn't considered available until that work has been done.</p> - -<h3>Can (should) we ship a 32GiB A/B device? 16GiB? 8GiB?</h3> - -<p>32GiB works well as it was proven on Pixel, and 320MiB out of 16GiB means a -reduction of 2%. Similarly, 320MiB out of 8GiB a reduction of 4%. Obviously -A/B would not be the recommended choice on devices with 4GiB, as the 320MiB -overhead is almost 10% of the total available space.</p> - -<h3>Does AVB2.0 require A/B OTAs?</h3> - -<p>No. Android <a href="/security/verifiedboot/">Verified Boot</a> has always -required block-based updates, but not necessarily A/B updates.</p> - -<h3>Do A/B OTAs require AVB2.0?</h3> - -<p>No.</p> - -<h3>Do A/B OTAs break AVB2.0's rollback protection?</h3> - -<p>No. There's some confusion here because if an A/B system fails to boot into -the new system image it will (after some number of retries determined by your -bootloader) automatically revert to the "previous" system image. The key point -here though is that "previous" in the A/B sense is actually still the "current" -system image. As soon as the device successfully boots a new image, rollback -protection kicks in and ensures that you can't go back. But until you've -actually successfully booted the new image, rollback protection doesn't -consider it to be the current system image.</p> - -<h3>If you're installing an update while the system is running, isn't that -slow?</h3> - -<p>With non-A/B updates, the aim is to install the update as quickly as -possible because the user is waiting and unable to use their device while the -update is applied. With A/B updates, the opposite is true; because the user is -still using their device, as little impact as possible is the goal, so the -update is deliberately slow. Via logic in the Java system update client (which -for Google is GmsCore, the core package provided by GMS), Android also attempts -to choose a time when the users aren't using their devices at all. The platform -supports pausing/resuming the update, and the client can use that to pause the -update if the user starts to use the device and resume it when the device is -idle again.</p> - -<p>There are two phases while taking an OTA, shown clearly in the UI as -<em>Step 1 of 2</em> and <em>Step 2 of 2</em> under the progress bar. Step 1 -corresponds with writing the data blocks, while step 2 is pre-compiling the -.dex files. These two phases are quite different in terms of performance -impact. The first phase is simple I/O. This requires little in the way of -resources (RAM, CPU, I/O) because it's just slowly copying blocks around.</p> - -<p>The second phase runs dex2oat to precompile the new system image. This -obviously has less clear bounds on its requirements because it compiles actual -apps. And there's obviously much more work involved in compiling a large and -complex app than a small and simple app; whereas in phase 1 there are no disk -blocks that are larger or more complex than others.</p> - -<p>The process is similar to when Google Play installs an app update in the -background before showing the <em>5 apps updated</em> notification, as has been -done for years.</p> - -<h3>What if a user is actually waiting for the update?</h3> - -<p>The current implementation in GmsCore doesn't distinguish between background -updates and user-initiated updates but may do so in the future. In the case -where the user explicitly asked for the update to be installed or is watching -the update progress screen, we'll prioritize the update work on the assumption -that they're actively waiting for it to finish.</p> - -<h3>What happens if there's a failure to apply an update?</h3> - -<p>With non-A/B updates, if an update failed to apply, the user was usually -left with an unusable device. The only exception was if the failure occurred -before an application had even started (because the package failed to verify, -say). With A/B updates, a failure to apply an update does not affect the -currently running system. The update can simply be retried later.</p> - -<h3>What does GmsCore do?</h3> - -<p>In Google's A/B implementation, the platform APIs and -<code>update_engine</code> provide the mechanism while GmsCore provides the -policy. That is, the platform knows <em>how</em> to apply an A/B update and all -that code is in AOSP (as mentioned above); but it's GmsCore that decides -<em>what</em> and <em>when</em> to apply.</p> - -<p>If you’re not using GmsCore, you can write your own replacement using the -same platform APIs. The platform Java API for controlling -<code>update_engine</code> is <code>android.os.UpdateEngine</code>: -<code><a href="https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/UpdateEngine.java" class="external-link">frameworks/base/core/java/android/os/UpdateEngine.java</a></code>. -Callers can provide an <code>UpdateEngineCallback</code> to be notified of status -updates: -<code><a href="https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/UpdateEngineCallback.java" class="external-link">frameworks/base/+/master/core/java/android/os/UpdateEngineCallback.java</a></code>. -Refer to the reference files for the core classes to use the interface.</p> - -<h3>Which systems on a chip (SoCs) support A/B?</h3> - -<p>As of 2017-03-15, we have the following information:</p> -<table class="style0"> -<tbody> -<tr> -<td></td> -<td><strong>Android 7.x Release</strong></td> -<td><strong>Android 8.x Release</strong></td> -</tr> -<tr> -<td><strong>Qualcomm</strong></td> -<td>Depending on OEM requests </td> -<td>All chipsets will get support</td> -</tr> -<tr> -<td><strong>Mediatek</strong></td> -<td>Depending on OEM requests</td> -<td>All chipsets will get support</td> -</tr> -</tbody> -</table> - -<p>For details on schedules, check with your SoC contacts. For SoCs not listed -above, reach out to your SoC directly.</p> + <p>A/B system updates, also known as seamless updates, ensure a workable + booting system remains on the disk during an <a href="/devices/tech/ota/index.html"> + over-the-air (OTA) update</a>. This approach reduces the likelihood of + an inactive device after an update, which means fewer device + replacements and device reflashes at repair and warranty centers. Other + commercial-grade operating systems such as + <a href="https://www.chromium.org/chromium-os">ChromeOS</a> also use A/B + updates successfully. + </p> + + <p>A/B system updates provide the following benefits:</p> + + <ul> + <li> + OTA updates can occur while the system is running, without + interrupting the user (including app optimizations that occur after a + reboot). This means users can continue to use their devices during an + OTA—the only downtime during an update is when the device + reboots into the updated disk partition. + </li> + <li> + If an OTA fails, the device boots into the pre-OTA disk partition and + remains usable. The download of the OTA can be attempted again. + </li> + <li> + Any errors (such as I/O errors) affect only the <strong>unused</strong> + partition set and can be retried. Such errors also become less likely + because the I/O load is deliberately low to avoid degrading the user + experience. + </li> + <li> + Updates can be streamed to A/B devices, removing the need to download + the package before installing it. Streaming means it's not necessary + for the user to have enough free space to store the update package on + <code>/data</code> or <code>/cache</code>. + </li> + <li> + The cache partition is no longer used to store OTA update packages, so + there is no need for sizing the cache partition. + </li> + <li> + <a href="/security/verifiedboot/dm-verity.html">dm-verity</a> + guarantees a device will boot an uncorrupted image. If a device + doesn't boot due to a bad OTA or dm-verity issue, the device can + reboot into an old image. (Android <a href="/security/verifiedboot/"> + Verified Boot</a> does not require A/B updates.) + </li> + </ul> + + <h2 id="overview">About A/B system updates</h2> + + <p>A/B system updates affect the following:</p> + + <ul> + <li> + Partition selection (slots), the <code>update_engine</code> daemon, + and bootloader interactions (described below) + </li> + <li> + Build process and OTA update package generation (described in + <a href="/devices/tech/ota/ab_implement.html">Implementing A/B + Updates</a>) + </li> + </ul> + + <aside class="note"> + <strong>Note:</strong> A/B system updates implemented through OTA are + recommended for new devices only. + </aside> + + <h3 id="slots">Partition selection (slots)</h3> + + <p> + A/B system updates use two sets of partitions referred to as + <em>slots</em> (normally slot A and slot B). The system runs from + the <em>current</em> slot while the partitions in the <em>unused</em> + slot are not accessed by the running system during normal operation. + This approach makes updates fault resistant by keeping the unused + slot as a fallback: If an error occurs during or immediately after + an update, the system can rollback to the old slot and continue to + have a working system. To achieve this goal, no partition used by + the <em>current</em> slot should be updated as part of the OTA + update (including partitions for which there is only one copy). + </p> + + <p> + Each slot has a <em>bootable</em> attribute that states whether the + slot contains a correct system from which the device can boot. The + current slot is bootable when the system is running, but the other + slot may have an old (still correct) version of the system, a newer + version, or invalid data. Regardless of what the <em>current</em> + slot is, there is one slot that is the <em>active</em> slot (the one + the bootloader will boot form on the next boot) or the + <em>preferred</em> slot. + </p> + + <p> + Each slot also has a <em>successful</em> attribute set by the user + space, which is relevant only if the slot is also bootable. A + successful slot should be able to boot, run, and update itself. A + bootable slot that was not marked as successful (after several + attempts were made to boot from it) should be marked as unbootable + by the bootloader, including changing the active slot to another + bootable slot (normally to the slot running immediately before the + attempt to boot into the new, active one). The specific details of + the interface are defined in + <code><a href="https://android.googlesource.com/platform/hardware/libhardware/+/master/include/hardware/boot_control.h" class="external-link"> + boot_control.h</a></code>. + </p> + + <h3 id="update-engine">Update engine daemon</h3> + + <p> + A/B system updates use a background daemon called + <code>update_engine</code> to prepare the system to boot into a new, + updated version. This daemon can perform the following actions: + </p> + + <ul> + <li> + Read from the current slot A/B partitions and write any data to + the unused slot A/B partitions as instructed by the OTA package. + </li> + <li> + Call the <code>boot_control</code> interface in a pre-defined + workflow. + </li> + <li> + Run a <em>post-install</em> program from the <em>new</em> + partition after writing all the unused slot partitions, as + instructed by the OTA package. (For details, see + <a href="#post-installation">Post-installation</a>). + </li> + </ul> + + <p> + As the <code>update_engine</code> daemon is not involved in the boot + process itself, it is limited in what it can do during an update by + the <a href="/security/selinux/">SELinux</a> policies and features + in the <em>current</em> slot (such policies and features can't be + updated until the system boots into a new version). To maintain a + robust system, the update process <strong>should not</strong> modify + the partition table, the contents of partitions in the current slot, + or the contents of non-A/B partitions that can't be wiped with a + factory reset. + </p> + + <p> + The <code>update_engine</code> source is located in + <code><a href="https://android.googlesource.com/platform/system/update_engine/" class="external">system/update_engine</a></code>. + The A/B OTA dexopt files are split between <code>installd</code> and + a package manager: + </p> + + <ul> + <li> + <code><a href="https://android.googlesource.com/platform/frameworks/native/+/master/cmds/installd/" class="external-link">frameworks/native/cmds/installd/</a></code>ota* + includes the postinstall script, the binary for chroot, the + installd clone that calls dex2oat, the post-OTA move-artifacts + script, and the rc file for the move script. + </li> + <li> + <code><a href="https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/pm/OtaDexoptService.java" class="external-link">frameworks/base/services/core/java/com/android/server/pm/OtaDexoptService.java</a></code> + (plus <code><a href="https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java" class="external-link">OtaDexoptShellCommand</a></code>) + is the package manager that prepares dex2oat commands for + applications. + </li> + </ul> + + <p> + For a working example, refer to <code><a href="https://android.googlesource.com/device/google/marlin/+/nougat-dr1-release/device-common.mk" class="external-link">/device/google/marlin/device-common.mk</a></code>. + </p> + + <h3 id="bootloader-interactions">Bootloader interactions</h3> + + <p> + The <code>boot_control</code> HAL is used by + <code>update_engine</code> (and possibly other daemons) to instruct + the bootloader what to boot from. Common example scenarios and their + associated states include the following: + </p> + + <ul> + <li> + <strong>Normal case</strong>: The system is running from its + current slot, either slot A or B. No updates have been applied so + far. The system's current slot is bootable, successful, and the + active slot. + </li> + <li> + <strong>Update in progress</strong>: The system is running from + slot B, so slot B is the bootable, successful, and active slot. + Slot A was marked as unbootable since the contents of slot A are + being updated but not yet completed. A reboot in this state should + continue booting from slot B. + </li> + <li> + <strong>Update applied, reboot pending</strong>: The system is + running from slot B, slot B is bootable and successful, but slot A + was marked as active (and therefore is marked as bootable). Slot A + is not yet marked as successful and some number of attempts to + boot from slot A should be made by the bootloader. + </li> + <li> + <strong>System rebooted into new update</strong>: The system is + running from slot A for the first time, slot B is still bootable + and successful while slot A is only bootable, and still active but + not successful. A user space daemon, <code>update_verifier</code>, + should mark slot A as successful after some checks are made. + </li> + </ul> + + <h3 id="streaming-updates">Streaming update support</h3> + + <p> + User devices don't always have enough space on <code>/data</code> to + download the update package. As neither OEMs nor users want to waste + space on a <code>/cache</code> partition, some users go without + updates because the device has nowhere to store the update package. + To address this issue, Android 8.0 added support for streaming A/B + updates that write blocks directly to the B partition as they are + downloaded, without having to store the blocks on <code>/data</code>. + Streaming A/B updates need almost no temporary storage and require + just enough storage for roughly 100 KiB of metadata. + </p> + + <p>To enable streaming updates in Android 7.1, cherrypick the following + patches:</p> + + <ul> + <li> + <a href="https://android-review.googlesource.com/333624" class="external"> + Allow to cancel a proxy resolution request</a> + </li> + <li> + <a href="https://android-review.googlesource.com/333625" class="external"> + Fix terminating a transfer while resolving proxies</a> + </li> + <li> + <a href="https://android-review.googlesource.com/333626" class="external"> + Add unit test for TerminateTransfer between ranges</a> + </li> + <li> + <a href="https://android-review.googlesource.com/333627" class="external"> + Cleanup the RetryTimeoutCallback()</a> + </li> + </ul> + + <p> + These patches are required to support streaming A/B updates in + Android 7.1 and later whether using + <a href="https://www.android.com/gms/">Google Mobile Services + (GMS)</a> or any other update client. + </p> + + <h2 id="life-of-an-a-b-update">Life of an A/B update</h2> + + <p> + The update process starts when an OTA package (referred to in code as a + <em>payload</em>) is available for downloading. Policies in the device + may defer the payload download and application based on battery level, + user activity, charging status, or other policies. In addition, + because the update runs in the background, users might not know an + update is in progress. All of this means the update process might be + interrupted at any point due to policies, unexpected reboots, or user + actions. + </p> + + <p> + Optionally, metadata in the OTA package itself indicates the update + can be streamed; the same package can also be used for non-streaming + installation. The server may use the metadata to tell the client it's + streaming so the client will hand off the OTA to + <code>update_engine</code> correctly. Device manufacturers with their + own server and client can enable streaming updates by ensuring the + server identifies the update is streaming (or assumes all updates are + streaming) and the client makes the correct call to + <code>update_engine</code> for streaming. Manufacturers can use the + fact that the package is of the streaming variant to send a flag to + the client to trigger hand off to the framework side as streaming. + </p> + + <p>After a payload is available, the update process is as follows:</p> + + <table> + <tr> + <th>Step</th> + <th>Activities</th> + </tr> + <tr> + <td>1</td> + <td>The current slot (or "source slot") is marked as successful (if + not already marked) with <code>markBootSuccessful()</code>.</td> + </tr> + <tr> + <td>2</td> + <td> + The unused slot (or "target slot") is marked as unbootable by + calling the function <code>setSlotAsUnbootable()</code>. The + current slot is always marked as successful at the beginning of + the update to prevent the bootloader from falling back to the + unused slot, which will soon have invalid data. If the system has + reached the point where it can start applying an update, the + current slot is marked as successful even if other major + components are broken (such as the UI in a crash loop) as it is + possible to push new software to fix these problems. + <br /><br /> + The update payload is an opaque blob with the instructions to + update to the new version. The update payload consists of the + following: + <ul> + <li> + <em>Metadata</em>. A relatively small portion of the update + payload, the metadata contains a list of operations to produce + and verify the new version on the target slot. For example, an + operation could decompress a certain blob and write it to + specific blocks in a target partition, or read from a source + partition, apply a binary patch, and write to certain blocks + in a target partition. + </li> + <li> + <em>Extra data</em>. As the bulk of the update payload, the + extra data associated with the operations consists of the + compressed blob or binary patch in these examples. + </li> + </ul> + </td> + </tr> + <tr> + <td>3</td> + <td>The payload metadata is downloaded.</td> + </tr> + <tr> + <td>4</td> + <td> + For each operation defined in the metadata, in order, the + associated data (if any) is downloaded to memory, the operation is + applied, and the associated memory is discarded. + </td> + </tr> + <tr> + <td>5</td> + <td> + The whole partitions are re-read and verified against the expected + hash. + </td> + </tr> + <tr> + <td>6</td> + <td> + The post-install step (if any) is run. In the case of an error + during the execution of any step, the update fails and is + re-attempted with possibly a different payload. If all the steps + so far have succeeded, the update succeeds and the last step is + executed. + </td> + </tr> + <tr> + <td>7</td> + <td> + The <em>unused slot</em> is marked as active by calling + <code>setActiveBootSlot()</code>. Marking the unused slot as + active doesn't mean it will finish booting. The bootloader (or + system itself) can switch the active slot back if it doesn't read + a successful state. + </td> + </tr> + <tr> + <td>8</td> + <td> + Post-installation (described below) involves running a program + from the "new update" version while still running in the old + version. If defined in the OTA package, this step is + <strong>mandatory</strong> and the program must return with exit + code <code>0</code>; otherwise, the update fails. + </td> + </tr> + <td>9</td> + <td> + After the system successfully boots far enough into the new slot + and finishes the post-reboot checks, the now current slot + (formerly the "target slot") is marked as successful by calling + <code>markBootSuccessful()</code>. + </td> + <tr> + </table> + + <aside class="note"> + <strong>Note:</strong> Steps 3 and 4 take most of the update time as + they involve writing and downloading large amounts of data, and are + likely to be interrupted for reasons of policy or reboot. + </aside> + + <h3 id="post-installation">Post-installation</h3> + + <p> + For every partition where a post-install step is defined, + <code>update_engine</code> mounts the new partition into a specific + location and executes the program specified in the OTA relative to + the mounted partition. For example, if the post-install program is + defined as <code>usr/bin/postinstall</code> in the system partition, + this partition from the unused slot will be mounted in a fixed + location (such as <code>/postinstall_mount</code>) and the + <code>/postinstall_mount/usr/bin/postinstall</code> command is + executed. + </p> + + <p> + For post-installation to succeed, the old kernel must be able to: + </p> + + <ul> + <li> + <strong>Mount the new filesystem format</strong>. The filesystem + type cannot change unless there's support for it in the old + kernel, including details such as the compression algorithm used + if using a compressed filesystem (i.e. SquashFS). + </li> + <li> + <strong>Understand the new partition's post-install program format</strong>. + If using an Executable and Linkable Format (ELF) binary, it should + be compatible with the old kernel (e.g. a 64-bit new program + running on an old 32-bit kernel if the architecture switched from + 32- to 64-bit builds). Unless the loader (<code>ld</code>) is + instructed to use other paths or build a static binary, libraries + will be loaded from the old system image and not the new one. + </li> + </ul> + + <p> + For example, you could use a shell script as a post-install program + interpreted by the old system's shell binary with a <code>#!</code> + marker at the top), then set up library paths from the new + environment for executing a more complex binary post-install + program. Alternatively, you could run the post-install step from a + dedicated smaller partition to enable the filesystem format in the + main system partition to be updated without incurring backward + compatibility issues or stepping-stone updates; this would allow + users to update directly to the latest version from a factory image. + </p> + + <p> + The new post-install program is limited by the SELinux policies + defined in the old system. As such, the post-install step is + suitable for performing tasks required by design on a given device + or other best-effort tasks (i.e. updating the A/B-capable firmware + or bootloader, preparing copies of databases for the new version, + etc.). The post-install step is <strong>not suitable</strong> for + one-off bug fixes before reboot that require unforeseen permissions. + </p> + + <p> + The selected post-install program runs in the + <code>postinstall</code> SELinux context. All the files in the new + mounted partition will be tagged with <code>postinstall_file</code>, + regardless of what their attributes are after rebooting into that + new system. Changes to the SELinux attributes in the new system + won't impact the post-install step. If the post-install program + needs extra permissions, those must be added to the post-install + context. + </p> + + <h3 id="after_reboot">After reboot</h3> + + <p> + After rebooting, <code>update_verifier</code> triggers the integrity + check using dm-verity. This check starts before zygote to avoid Java + services making any irreversible changes that would prevent a safe + rollback. During this process, bootloader and kernel may also + trigger a reboot if verified boot or dm-verity detect any + corruption. After the check completes, <code>update_verifier</code> + marks the boot successful. + </p> + + <p> + <code>update_verifier</code> will read only the blocks listed in + <code>/data/ota_package/care_map.txt</code>, which is included in an + A/B OTA package when using the AOSP code. The Java system update + client, such as GmsCore, extracts <code>care_map.txt</code>, sets up + the access permission before rebooting the device, and deletes the + extracted file after the system successfully boots into the new + version. + </p> + + <h2 id="faq">Frequently asked questions</h2> + + <h3>Has Google used A/B OTAs on any devices?</h3> + + <p> + Yes. The marketing name for A/B updates is <em>seamless updates</em>. + Pixel and Pixel XL phones from October 2016 shipped with A/B, and + all Chromebooks use the same <code>update_engine</code> + implementation of A/B. The necessary platform code implementation is + public in Android 7.1 and higher. + </p> + + <h3>Why are A/B OTAs better?</h3> + + <p>A/B OTAs provide a better user experience when taking updates. Measurements + from monthly security updates show this feature has already proven a success: As + of May 2017, 95% of Pixel owners are running the latest security update after a + month compared to 87% of Nexus users, and Pixel users update sooner than Nexus + users. Failures to update blocks during an OTA no longer result in a device that + won't boot; until the new system image has successfully booted, Android retains + the ability to fall back to the previous working system image.</p> + + <h3>How did A/B affect the 2016 Pixel partition sizes?</h3> + + <p>The following table contains details on the shipping A/B configuration versus + the internally-tested non-A/B configuration:</p> + + <table> + <tbody> + <tr> + <th>Pixel partition sizes</th> + <th width="33%">A/B</th> + <th width="33%">Non-A/B</th> + </tr> + <tr> + <td>Bootloader</td> + <td>50*2</td> + <td>50</td> + </tr> + <tr> + <td>Boot</td> + <td>32*2</td> + <td>32</td> + </tr> + <tr> + <td>Recovery</td> + <td>0</td> + <td>32</td> + </tr> + <tr> + <td>Cache</td> + <td>0</td> + <td>100</td> + </tr> + <tr> + <td>Radio</td> + <td>70*2</td> + <td>70</td> + </tr> + <tr> + <td>Vendor</td> + <td>300*2</td> + <td>300</td> + </tr> + <tr> + <td>System</td> + <td>2048*2</td> + <td>4096</td> + </tr> + <tr> + <td><strong>Total</strong></td> + <td><strong>5000</strong></td> + <td><strong>4680</strong></td> + </tr> + </tbody> + </table> + + <p>A/B updates require an increase of only 320 MiB in flash, with a savings of + 32MiB from removing the recovery partition and another 100MiB preserved by + removing the cache partition. This balances the cost of the B partitions for + the bootloader, the boot partition, and the radio partition. The vendor + partition doubled in size (the vast majority of the size increase). Pixel's + A/B system image is half the size of the original non-A/B system image. + </p> + + <p>For the Pixel A/B and non-A/B variants tested internally (only A/B shipped), + the space used differed by only 320MiB. On a 32GiB device, this is just under + 1%. For a 16GiB device this would be less than 2%, and for an 8GiB device almost + 4% (assuming all three devices had the same system image).</p> + + <h3>Why didn't you use SquashFS?</h3> + + <p>We experimented with SquashFS but weren't able to achieve the performance + desired for a high-end device. We don't use or recommend SquashFS for handheld + devices.</p> + + <p>More specifically, SquashFS provided about 50% size savings on the system + partition, but the overwhelming majority of the files that compressed well were + the precompiled .odex files. Those files had very high compression ratios + (approaching 80%), but the compression ratio for the rest of the system + partition was much lower. In addition, SquashFS in Android 7.0 raised the + following performance concerns:</p> + + <ul> + <li>Pixel has very fast flash compared to earlier devices but not a huge + number of spare CPU cycles, so reading fewer bytes from flash but needing + more CPU for I/O was a potential bottleneck.</li> + <li>I/O changes that perform well on an artificial benchmark run on an + unloaded system sometimes don't work well on real-world use cases under + real-world load (such as crypto on Nexus 6).</li> + <li>Benchmarking showed 85% regressions in some places.</li> + </ul> + + <p>As SquashFS matures and adds features to reduce CPU impact (such as a + whitelist of commonly-accessed files that shouldn't be compressed), we will + continue to evaluate it and offer recommendations to device manufacturers.</p> + + <h3>How did you halve the size of the system partition without SquashFS?</h3> + + <p>Applications are stored in .apk files, which are actually ZIP archives. Each + .apk file has inside it one or more .dex files containing portable Dalvik + bytecode. An .odex file (optimized .dex) lives separately from the .apk file + and can contain machine code specific to the device. If an .odex file is + available, Android can run applications at ahead-of-time compiled speeds + without having to wait for the code to be compiled each time the application is + launched. An .odex file isn't strictly necessary: Android can actually run the + .dex code directly via interpretation or Just-In-Time (JIT) compilation, but an + .odex file provides the best combination of launch speed and run-time speed if + space is available.</p> + + <p>Example: For the installed-files.txt from a Nexus 6P running Android 7.1 with + a total system image size of 2628MiB (2755792836 bytes), the breakdown of the + largest contributors to overall system image size by file type is as follows: + </p> + + <table> + <tbody> + <tr> + <td>.odex</td> + <td>1391770312 bytes</td> + <td>50.5%</td> + </tr> + <tr> + <td>.apk</td> + <td>846878259 bytes</td> + <td>30.7%</td> + </tr> + <tr> + <td>.so (native C/C++ code)</td> + <td>202162479 bytes</td> + <td>7.3%</td> + </tr> + <tr> + <td>.oat files/.art images</td> + <td>163892188 bytes</td> + <td>5.9%</td> + </tr> + <tr> + <td>Fonts</td> + <td>38952361 bytes</td> + <td>1.4%</td> + </tr> + <tr> + <td>icu locale data</td> + <td>27468687 bytes</td> + <td>0.9%</td> + </tr> + </tbody> + </table> + + <p>These figures are similar for other devices too, so on Nexus/Pixel + devices, .odex files take up approximately half the system partition. This meant + we could continue to use ext4 but write the .odex files to the B partition + at the factory and then copy them to <code>/data</code> on first boot. The + actual storage used with ext4 A/B is identical to SquashFS A/B, because if we + had used SquashFS we would have shipped the preopted .odex files on system_a + instead of system_b.</p> + + <h3>Doesn't copying .odex files to /data mean the space saved on /system is + lost on /data?</h3> + + <p>Not exactly. On Pixel, most of the space taken by .odex files is for apps, + which typically exist on <code>/data</code>. These apps take Google Play + updates, so the .apk and .odex files on the system image are unused for most of + the life of the device. Such files can be excluded entirely and replaced by + small, profile-driven .odex files when the user actually uses each app (thus + requiring no space for apps the user doesn't use). For details, refer to the + Google I/O 2016 talk <a href="https://www.youtube.com/watch?v=fwMM6g7wpQ8">The + Evolution of Art</a>.</p> + + <p>The comparison is difficult for a few key reasons:</p> + <ul> + <li>Apps updated by Google Play have always had their .odex files on + <code>/data</code> as soon as they receive their first update.</li> + <li>Apps the user doesn't run don't need an .odex file at all.</li> + <li>Profile-driven compilation generates smaller .odex files than ahead-of-time + compilation (because the former optimizes only performance-critical code).</li> + </ul> + + <p>For details on the tuning options available to OEMs, see + <a href="/devices/tech/dalvik/configure.html">Configuring ART</a>.</p> + + <h3>Aren't there two copies of the .odex files on /data?</h3> + + <p>It's a little more complicated ... After the new system image has been + written, the new version of dex2oat is run against the new .dex files to + generate the new .odex files. This occurs while the old system is still running, + so the old and new .odex files are both on <code>/data</code> at the same time. + </p> + + <p>The code in OtaDexoptService + (<code><a href="https://android.googlesource.com/platform/frameworks/base/+/nougat-mr1-release/services/core/java/com/android/server/pm/OtaDexoptService.java#200" class="external">frameworks/base/+/nougat-mr1-release/services/core/java/com/android/server/pm/OtaDexoptService.java#200</a></code>) + calls <code>getAvailableSpace</code> before optimizing each package to avoid + over-filling <code>/data</code>. Note that <em>available</em> here is still + conservative: it's the amount of space left <em>before</em> hitting the usual + system low space threshold (measured as both a percentage and a byte count). So + if <code>/data</code> is full, there won't be two copies of every .odex file. + The same code also has a BULK_DELETE_THRESHOLD: If the device gets that close + to filling the available space (as just described), the .odex files belonging to + apps that aren't used are removed. That's another case without two copies of + every .odex file.</p> + + <p>In the worst case where <code>/data</code> is completely full, the update + waits until the device has rebooted into the new system and no longer needs the + old system's .odex files. The PackageManager handles this: + (<code><a href="https://android.googlesource.com/platform/frameworks/base/+/nougat-mr1-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215" class="external">frameworks/base/+/nougat-mr1-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215</a></code>). After the new system has + successfully booted, <code>installd</code> + (<code><a href="https://android.googlesource.com/platform/frameworks/native/+/nougat-mr1-release/cmds/installd/commands.cpp#2192" class="external">frameworks/native/+/nougat-mr1-release/cmds/installd/commands.cpp#2192</a></code>) + can remove the .odex files that were used by the old system, returning the + device back to the steady state where there's only one copy.</p> + + <p>So, while it is possible that <code>/data</code> contains two copies of all + the .odex files, (a) this is temporary and (b) only occurs if you had plenty of + free space on <code>/data</code> anyway. Except during an update, there's only + one copy. And as part of ART's general robustness features, it will never fill + <code>/data</code> with .odex files anyway (because that would be a problem on a + non-A/B system too).</p> + + <h3>Doesn't all this writing/copying increase flash wear?</h3> + + <p>Only a small portion of flash is rewritten: a full Pixel system update + writes about 2.3GiB. (Apps are also recompiled, but that's true of non-A/B + too.) Traditionally, block-based full OTAs wrote a similar amount of data, so + flash wear rates should be similar.</p> + + <h3>Does flashing two system partitions increase factory flashing time?</h3> + + <p>No. Pixel didn't increase in system image size (it merely divided the space + across two partitions).</p> + + <h3>Doesn't keeping .odex files on B make rebooting after factory data reset + slow?</h3> + + <p>Yes. If you've actually used a device, taken an OTA, and performed a factory + data reset, the first reboot will be slower than it would otherwise be (1m40s vs + 40s on a Pixel XL) because the .odex files will have been lost from B after the + first OTA and so can't be copied to <code>/data</code>. That's the trade-off.</p> + + <p>Factory data reset should be a rare operation when compared to regular boot + so the time taken is less important. (This doesn't affect users or reviewers who + get their device from the factory, because in that case the B partition is + available.) Use of the JIT compiler means we don't need to recompile + <em>everything</em>, so it's not as bad as you might think. It's also possible + to mark apps as requiring ahead-of-time compilation using + <code>coreApp="true"</code> in the manifest: + (<code><a href="https://android.googlesource.com/platform/frameworks/base/+/nougat-mr1-release/packages/SystemUI/AndroidManifest.xml#23" class="external">frameworks/base/+/nougat-mr1-release/packages/SystemUI/AndroidManifest.xml#23</a></code>). + This is currently used by <code>system_server</code> because it's not allowed to + JIT for security reasons.</p> + + <h3>Doesn't keeping .odex files on /data rather than /system make rebooting + after an OTA slow?</h3> + + <p>No. As explained above, the new dex2oat is run while the old system image is + still running to generate the files that will be needed by the new system. The + update isn't considered available until that work has been done.</p> + + <h3>Can (should) we ship a 32GiB A/B device? 16GiB? 8GiB?</h3> + + <p>32GiB works well as it was proven on Pixel, and 320MiB out of 16GiB means a + reduction of 2%. Similarly, 320MiB out of 8GiB a reduction of 4%. Obviously + A/B would not be the recommended choice on devices with 4GiB, as the 320MiB + overhead is almost 10% of the total available space.</p> + + <h3>Does AVB2.0 require A/B OTAs?</h3> + + <p>No. Android <a href="/security/verifiedboot/">Verified Boot</a> has always + required block-based updates, but not necessarily A/B updates.</p> + + <h3>Do A/B OTAs require AVB2.0?</h3> + + <p>No.</p> + + <h3>Do A/B OTAs break AVB2.0's rollback protection?</h3> + + <p>No. There's some confusion here because if an A/B system fails to boot into + the new system image it will (after some number of retries determined by your + bootloader) automatically revert to the "previous" system image. The key point + here though is that "previous" in the A/B sense is actually still the "current" + system image. As soon as the device successfully boots a new image, rollback + protection kicks in and ensures that you can't go back. But until you've + actually successfully booted the new image, rollback protection doesn't + consider it to be the current system image.</p> + + <h3>If you're installing an update while the system is running, isn't that + slow?</h3> + + <p>With non-A/B updates, the aim is to install the update as quickly as + possible because the user is waiting and unable to use their device while the + update is applied. With A/B updates, the opposite is true; because the user is + still using their device, as little impact as possible is the goal, so the + update is deliberately slow. Via logic in the Java system update client (which + for Google is GmsCore, the core package provided by GMS), Android also attempts + to choose a time when the users aren't using their devices at all. The platform + supports pausing/resuming the update, and the client can use that to pause the + update if the user starts to use the device and resume it when the device is + idle again.</p> + + <p>There are two phases while taking an OTA, shown clearly in the UI as + <em>Step 1 of 2</em> and <em>Step 2 of 2</em> under the progress bar. Step 1 + corresponds with writing the data blocks, while step 2 is pre-compiling the + .dex files. These two phases are quite different in terms of performance + impact. The first phase is simple I/O. This requires little in the way of + resources (RAM, CPU, I/O) because it's just slowly copying blocks around.</p> + + <p>The second phase runs dex2oat to precompile the new system image. This + obviously has less clear bounds on its requirements because it compiles actual + apps. And there's obviously much more work involved in compiling a large and + complex app than a small and simple app; whereas in phase 1 there are no disk + blocks that are larger or more complex than others.</p> + + <p>The process is similar to when Google Play installs an app update in the + background before showing the <em>5 apps updated</em> notification, as has been + done for years.</p> + + <h3>What if a user is actually waiting for the update?</h3> + + <p>The current implementation in GmsCore doesn't distinguish between background + updates and user-initiated updates but may do so in the future. In the case + where the user explicitly asked for the update to be installed or is watching + the update progress screen, we'll prioritize the update work on the assumption + that they're actively waiting for it to finish.</p> + + <h3>What happens if there's a failure to apply an update?</h3> + + <p>With non-A/B updates, if an update failed to apply, the user was usually + left with an unusable device. The only exception was if the failure occurred + before an application had even started (because the package failed to verify, + say). With A/B updates, a failure to apply an update does not affect the + currently running system. The update can simply be retried later.</p> + + <h3>What does GmsCore do?</h3> + + <p>In Google's A/B implementation, the platform APIs and + <code>update_engine</code> provide the mechanism while GmsCore provides the + policy. That is, the platform knows <em>how</em> to apply an A/B update and all + that code is in AOSP (as mentioned above); but it's GmsCore that decides + <em>what</em> and <em>when</em> to apply.</p> + + <p>If you’re not using GmsCore, you can write your own replacement using the + same platform APIs. The platform Java API for controlling + <code>update_engine</code> is <code>android.os.UpdateEngine</code>: + <code><a href="https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/UpdateEngine.java" class="external-link">frameworks/base/core/java/android/os/UpdateEngine.java</a></code>. + Callers can provide an <code>UpdateEngineCallback</code> to be notified of status + updates: + <code><a href="https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/UpdateEngineCallback.java" class="external-link">frameworks/base/+/master/core/java/android/os/UpdateEngineCallback.java</a></code>. + Refer to the reference files for the core classes to use the interface.</p> + + <h3>Which systems on a chip (SoCs) support A/B?</h3> + + <p>As of 2017-03-15, we have the following information:</p> + <table class="style0"> + <tbody> + <tr> + <td></td> + <td><strong>Android 7.x Release</strong></td> + <td><strong>Android 8.x Release</strong></td> + </tr> + <tr> + <td><strong>Qualcomm</strong></td> + <td>Depending on OEM requests </td> + <td>All chipsets will get support</td> + </tr> + <tr> + <td><strong>Mediatek</strong></td> + <td>Depending on OEM requests</td> + <td>All chipsets will get support</td> + </tr> + </tbody> + </table> + + <p>For details on schedules, check with your SoC contacts. For SoCs not listed + above, reach out to your SoC directly.</p> </body> </html> diff --git a/en/devices/tech/ota/index.html b/en/devices/tech/ota/index.html index 234ff2de..58737b5c 100644 --- a/en/devices/tech/ota/index.html +++ b/en/devices/tech/ota/index.html @@ -23,138 +23,42 @@ -<p>Android devices in the field can receive and install over-the-air (OTA) -updates to the system and application software. Devices have a special -recovery partition with the software needed to unpack a downloaded update -package and apply it to the rest of the system.</p> -<p>This section describes the structure of these packages and the tools -provided to build them. It is intended for developers who want to -make the OTA update system work on new Android devices and those who are -building update packages for use with released devices. OTA updates are -designed to upgrade the underlying operating system and the read-only apps -installed on the system partition; these updates do <i>not</i> affect -applications installed by the user from Google Play. -</p> -<p>This section describes the OTA system as of the Android 5.x release. For -help porting OTA-related code from older releases, see <a href="#migrating"> -Migrating from previous releases</a>. -</p> + <p> + Android devices in the field can receive and install over-the-air (OTA) + updates to the system and application software. This section describes + the structure of the update packages and the tools provided to build + them. It is intended for developers who want to make the OTA update + system work on new Android devices and those who are building update + packages for use with released devices. OTA updates are designed to + upgrade the underlying operating system and the read-only apps installed + on the system partition; these updates do <em>not</em> affect + applications installed by the user from Google Play. + </p> -<h2 id="android-device-layout">Android device layout</h2> -<p>The flash space on an Android device typically contains the following -partitions.</p> + <h2 id="ab_updates">A/B updates</h2> -<dl> -<dt>boot</dt> -<dd>Contains the Linux kernel and a minimal root filesystem (loaded into a RAM -disk). It mounts system and other partitions and starts the runtime located on -the system partition.</dd> -<dt>system</dt> -<dd>Contains system applications and libraries that have source code available -on Android Open Source Project (AOSP). During normal operation, this partition -is mounted read-only; its contents change only during an OTA update.</dd> -<dt>vendor</dt> -<dd>Contains system applications and libraries that do <em>not</em> have -source code available on Android Open Source Project (AOSP). During normal -operation, this partition is mounted read-only; its contents change only -during an OTA update.</dd> -<dt>userdata</dt> -<dd>Stores the data saved by applications installed by the user, etc. This -partition is not normally touched by the OTA update process.</dd> -<dt>cache</dt> -<dd>Temporary holding area used by a few applications (accessing this -partition requires special app permissions) and for storage of downloaded OTA -update packages. Other programs use this space with the expectation that files -can disappear at any time. Some OTA package installations may result in this -partition being wiped completely.</dd> -<dt>recovery</dt> -<dd>Contains a second complete Linux system, including a kernel and the -special recovery binary that reads a package and uses its contents to update -the other partitions.</dd> -<dt>misc</dt> -<dd>Tiny partition used by recovery to stash some information away about what -it's doing in case the device is restarted while the OTA package is being -applied.</dd></dl> + <p> + Modern A/B devices have two copies of each partition, A and B. Devices + apply the update to the currently unused partition while the system is + running but idle. A/B devices do not need space to download the update + package because they can apply the update as they read it from the + network. This is called <em>streaming A/B</em>. A/B updates are also + know as <em>seamless updates</em>. For more information about OTA + updates for A/B devices, see + <a href="/devices/tech/ota/ab_updates.html">A/B (Seamless) System + Update + </a>. + </p> -<h2 id="life-ota-update">Life of an OTA update</h2> -<p>A typical OTA update contains the following steps:</p> -<ol> -<li>Device performs regular check in with OTA servers and is notified of the -availability of an update, including the URL of the update package and a -description string to show the user.</li> -<li>Update downloads to a cache or data partition, and its cryptographic -signature is verified against the certificates in -<code>/system/etc/security/otacerts.zip</code>. User is prompted to install the -update.</li> -<li>Device reboots into recovery mode, in which the kernel and system in the -recovery partition are booted instead of the kernel in the boot partition.</li> -<li>Recovery binary is started by init. It finds command-line arguments in -<code>/cache/recovery/command</code> that point it to the downloaded package. -</li> -<li>Recovery verifies the cryptographic signature of the package against the -public keys in <code>/res/keys</code> (part of the RAM disk contained in the -recovery partition).</li> -<li>Data is pulled from the package and used to update the boot, system, -and/or vendor partitions as necessary. One of the new files left on the system -partition contains the contents of the new recovery partition.</li> -<li>Device reboots normally. <ol style="list-style-type:lower-alpha"> -<li>The newly updated boot partition is loaded, and it mounts and starts -executing binaries in the newly updated system partition.</li> -<li>As part of normal startup, the system checks the contents of the recovery -partition against the desired contents (which were previously stored as a file -in <code>/system</code>). They are different, so the recovery partition is -reflashed with the desired contents. (On subsequent boots, the recovery -partition already contains the new contents, so no reflash is necessary.)</li> -</ol></li> -</ol> -<p>The system update is complete!</p> + <h2 id="nonab_updates">Non-A/B updates</h2> -<h2 id="migrating">Migrating from previous releases</h2> - -<p>When migrating from Android 2.3/3.0/4.0 release, the major change is the -conversion of all the device-specific functionality from a set of C functions -with predefined names to C++ objects. The following table lists the old -functions and the new methods that serve a roughly equivalent purpose:</p> - -<table> -<tbody> -<tr> -<th>C function</th> -<th>C++ method</th> -</tr> -<tr> -<td>device_recovery_start()</td> -<td>Device::RecoveryStart()</td> -</tr> -<tr> -<td>device_toggle_display()<br> -device_reboot_now()<br> -</td> -<td>RecoveryUI::CheckKey()<br> -(also RecoveryUI::IsKeyPressed())<br> -</td> -</tr> -<tr> -<td>device_handle_key()</td> -<td>Device::HandleMenuKey()</td> -</tr> -<tr> -<td>device_perform_action()</td> -<td>Device::InvokeMenuItem()</td> -</tr> -<tr> -<td>device_wipe_data()</td> -<td>Device::WipeData()</td> -</tr> -<tr> -<td>device_ui_init()</td> -<td>ScreenRecoveryUI::Init()</td> -</tr> -</tbody> -</table> - -<p>Conversion of old functions to new methods should be reasonably -straightforward. Don't forget to add the new <code>make_device()</code> -function to create and return an instance of your new Device subclass.</p> + <p> + Older devices have a special recovery partition containing the software + needed to unpack a downloaded update package and apply the update to + the other partitions. For more information, see + <a href="/devices/tech/ota/nonab_updates.html">Non-A/B System Updates + </a>. + </p> + </body> </html> diff --git a/en/devices/tech/ota/nonab_updates.html b/en/devices/tech/ota/nonab_updates.html new file mode 100644 index 00000000..627fa263 --- /dev/null +++ b/en/devices/tech/ota/nonab_updates.html @@ -0,0 +1,195 @@ +<html devsite> + <head> + <title>Non-A/B System Updates</title> + <meta name="project_path" value="/_project.yaml" /> + <meta name="book_path" value="/_book.yaml" /> + </head> + <body> + <!-- + Copyright 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + + <p>On older Android devices without A/B partitions, the flash space + typically contains the following partitions: + </p> + + <dl> + <dt>boot</dt> + <dd> + Contains the Linux kernel and a minimal root filesystem (loaded into + a RAM disk). It mounts system and other partitions and starts the + runtime located on the system partition. + </dd> + + <dt>system</dt> + <dd> + Contains system applications and libraries that have source code + available on Android Open Source Project (AOSP). During normal + operation, this partition is mounted read-only; its contents change + only during an OTA update. + </dd> + + <dt>vendor</dt> + <dd> + Contains system applications and libraries that do <em>not</em> have + source code available on Android Open Source Project (AOSP). During + normal operation, this partition is mounted read-only; its contents + change only during an OTA update. + </dd> + + <dt>userdata</dt> + <dd> + Stores the data saved by applications installed by the user, etc. This + partition is not normally touched by the OTA update process. + </dd> + + <dt>cache</dt> + <dd> + Temporary holding area used by a few applications (accessing this + partition requires special app permissions) and for storage of + downloaded OTA update packages. Other programs use this space with the + expectation that files can disappear at any time. Some OTA package + installations may result in this partition being wiped completely. + </dd> + + <dt>recovery</dt> + <dd> + Contains a second complete Linux system, including a kernel and the + special recovery binary that reads a package and uses its contents to + update the other partitions. + </dd> + + <dt>misc</dt> + <dd> + Tiny partition used by recovery to stash some information away about + what it is doing in case the device is restarted while the OTA package + is being applied. + </dd> + </dl> + + <h2 id="life-ota-update">Life of an OTA update</h2> + + <p>A typical OTA update contains the following steps:</p> + + <ol> + <li> + Device performs regular check in with OTA servers and is notified of + the availability of an update, including the URL of the update + package and a description string to show the user. + </li> + <li> + Update downloads to a cache or data partition, and its cryptographic + signature is verified against the certificates in + <code>/system/etc/security/otacerts.zip</code>. User is prompted to + install the update. + </li> + <li> + Device reboots into recovery mode, in which the kernel and system in + the recovery partition are booted instead of the kernel in the boot + partition. + </li> + <li> + Recovery binary is started by init. It finds command-line arguments + in <code>/cache/recovery/command</code> that point it to the + downloaded package. + </li> + <li> + Recovery verifies the cryptographic signature of the package against + the public keys in <code>/res/keys</code> (part of the RAM disk + contained in the recovery partition). + </li> + <li> + Data is pulled from the package and used to update the boot, system, + and/or vendor partitions as necessary. One of the new files left on + the system partition contains the contents of the new recovery partition. + </li> + <li>Device reboots normally. + <ol style="list-style-type:lower-alpha"> + <li> + The newly updated boot partition is loaded, and it mounts and + starts executing binaries in the newly updated system partition. + </li> + <li> + As part of normal startup, the system checks the contents of the + recovery partition against the desired contents (which were + previously stored as a file in <code>/system</code>). They are + different, so the recovery partition is reflashed with the + desired contents. (On subsequent boots, the recovery partition + already contains the new contents, so no reflash is necessary.) + </li> + </ol> + </li> + </ol> + + <p>The system update is complete!</p> + + <h2 id="migrating">Migrating from previous releases</h2> + + <p> + When migrating from Android 2.3/3.0/4.0 release, the major change is + the conversion of all the device-specific functionality from a set of + C functions with predefined names to C++ objects. The following table + lists the old functions and the new methods that serve a roughly equivalent purpose: + </p> + + <table> + <tr> + <th>C function</th> + <th>C++ method</th> + </tr> + + <tr> + <td>device_recovery_start()</td> + <td>Device::RecoveryStart()</td> + </tr> + + <tr> + <td>device_toggle_display()<br /> + device_reboot_now()<br /> + </td> + <td>RecoveryUI::CheckKey()<br /> + (also RecoveryUI::IsKeyPressed())<br /> + </td> + </tr> + + <tr> + <td>device_handle_key()</td> + <td>Device::HandleMenuKey()</td> + </tr> + + <tr> + <td>device_perform_action()</td> + <td>Device::InvokeMenuItem()</td> + </tr> + + <tr> + <td>device_wipe_data()</td> + <td>Device::WipeData()</td> + </tr> + + <tr> + <td>device_ui_init()</td> + <td>ScreenRecoveryUI::Init()</td> + </tr> + </table> + + <p> + Conversion of old functions to new methods should be reasonably + straightforward. Don't forget to add the new <code>make_device()</code> + function to create and return an instance of your new Device subclass. + </p> + + </body> +</html>
\ No newline at end of file |