blob: a5bbbbc85f63844961f1deed9da7c6a5da77d3da [file] [log] [blame]
<html devsite><head>
<title>非 A/B 系统更新</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>在老款的没有 A/B 分区的 Android 设备上,闪存空间通常包含以下分区:</p>
<dl>
<dt>引导</dt>
<dd>
包含 Linux 内核和最小的根文件系统(加载到 RAM 磁盘)。它装载了系统和其它分区,并启动位于系统分区上的运行时。
</dd>
<dt>系统</dt>
<dd>
包含在 Android 开源项目 (AOSP) 上提供源代码的系统应用和库。在正常操作期间,此分区被装载为只读分区;其内容仅在 OTA 更新期间更改。
</dd>
<dt>供应商</dt>
<dd>
包含在 Android 开源项目 (AOSP) 上<em></em>提供源代码的系统应用和库。在正常操作期间,此分区被装载为只读分区;其内容仅在 OTA 更新期间更改。
</dd>
<dt>用户数据</dt>
<dd>
存储由用户安装的应用所保存的数据等。OTA 更新过程通常不会触及该分区。
</dd>
<dt>缓存</dt>
<dd>
几个应用使用的临时保留区域(访问此分区需要使用特殊的应用权限),用于存储下载的 OTA 更新包。其他程序也可使用该空间,但是此类文件可能会随时消失。安装某些 OTA 更新包可能会导致此分区被完全擦除。缓存还包含 OTA 更新的更新日志。
</dd>
<dt>恢复</dt>
<dd>
包含第二个完整的 Linux 系统,其中包括一个内核和特殊的恢复二进制文件(该文件可读取一个软件包并使用其内容来更新其他分区)。
</dd>
<dt>其他</dt>
<dd>
执行恢复操作时使用的微小分区,可在应用 OTA 更新包并重新启动设备时,隐藏某些进程的信息。
</dd>
</dl>
<h2 id="life-ota-update">OTA 更新过程</h2>
<p>典型 OTA 更新包含以下步骤:</p>
<ol>
<li>
设备会与 OTA 服务器进行定期确认,并被告知是否有更新可用,包括更新软件包的 URL 和向用户显示的描述字符串。
</li>
<li>
将更新下载到缓存或数据分区,并根据 <code>/system/etc/security/otacerts.zip</code> 中的证书验证加密签名。系统提示用户安装更新。
</li>
<li>
设备重新启动进入恢复模式,引导恢复分区中的内核和系统启动,而非引导分区中的内核。
</li>
<li>
恢复分区的二进制文件由 init 启动。它会在 <code>/cache/recovery/command</code> 中寻找将其指向下载软件包的命令行参数。
</li>
<li>
恢复操作会根据 <code>/res/keys</code> (包含在恢复分区中的 RAM 磁盘的一部分)中的公钥来验证软件包的加密签名。
</li>
<li>
从软件包中提取数据,并根据需要使用该数据更新引导、系统和/或供应商分区。系统分区上其中一个新文件包含新恢复分区内容。
</li>
<li>设备正常重启。
<ol style="list-style-type:lower-alpha">
<li>
加载最新更新的引导分区,在最新更新的系统分区中装载并开始执行二进制文件。
</li>
<li>
作为正常启动的一部分,系统会根据所需内容(预先存储为 <code>/system</code> 中的一个文件)检查恢复分区的内容。二者内容不同,所以恢复分区会被所需内容重新刷写(在后续引导中,恢复分区已经包含新内容,因此无需重新刷写)。
</li>
</ol>
</li>
</ol>
<p>系统更新完成!更新日志可以在 <code>/cache/recovery/last_log.<var>#</var></code> 中找到。</p>
<h2 id="migrating">从更早版本迁移</h2>
<p>
当从 Android 2.3/3.0/4.0 版本进行迁移时,主要变化是将设备专属的功能从一组具有预定义名称的 C 函数转换为 C++ 对象。下表列出了用途大致相同的旧函数和新方法:
</p>
<table>
<tbody><tr>
<th>C 函数</th>
<th>C ++ 方法</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>
将旧函数转化为新方法应尽量简单直观。不要忘记添加新的 <code>make_device()</code> 函数来创建并返回新设备子类的实例。
</p>
</body></html>