Использовал ли Google A/B OTA на каких-либо устройствах?
Да. Маркетинговое название обновлений A/B — бесшовные обновления . Телефоны Pixel и Pixel XL с октября 2016 года поставляются с A/B, и все Chromebook используют одну и ту же реализацию update_engine
A/B. Необходимая реализация кода платформы общедоступна в Android 7.1 и выше.
Почему A/B OTA лучше?
A/B OTA обеспечивают лучший пользовательский опыт при получении обновлений. Измерения ежемесячных обновлений безопасности показывают, что эта функция уже доказала свою эффективность: по состоянию на май 2017 года 95% владельцев Pixel используют последнее обновление безопасности через месяц по сравнению с 87% пользователей Nexus, а пользователи Pixel обновляются раньше, чем пользователи Nexus. Сбои в обновлении блоков во время OTA больше не приводят к тому, что устройство не загружается; пока новый образ системы не будет успешно загружен, Android сохраняет возможность отката к предыдущему рабочему образу системы.
Что такое system_other?
Приложения хранятся в файлах .apk, которые на самом деле являются архивами ZIP. Каждый файл .apk содержит внутри себя один или несколько файлов .dex, содержащих переносимый байт-код Dalvik. Файл .odex (оптимизированный .dex) существует отдельно от файла .apk и может содержать машинный код, специфичный для устройства. Если файл .odex доступен, Android может запускать приложения на скорости предварительной компиляции, не дожидаясь компиляции кода каждый раз при запуске приложения. Файл .odex не является строго необходимым: Android фактически может запускать код .dex напрямую через интерпретацию или компиляцию Just-In-Time (JIT), но файл .odex обеспечивает наилучшее сочетание скорости запуска и скорости выполнения, если есть свободное место.
Пример: для файла installed-files.txt из Nexus 6P под управлением Android 7.1 с общим размером образа системы 2628 МБ (2755792836 байт) распределение файлов, вносящих наибольший вклад в общий размер образа системы, по типу выглядит следующим образом:
.odex | 1391770312 байт | 50,5% |
.apk | 846878259 байт | 30,7% |
.so (собственный код C/C++) | 202162479 байт | 7.3% |
Файлы .oat/изображения .art | 163892188 байт | 5.9% |
Шрифты | 38952361 байт | 1,4% |
данные локали icu | 27468687 байт | 0,9% |
Эти цифры схожи и для других устройств, так что на устройствах Nexus/Pixel файлы .odex занимают примерно половину системного раздела. Это означало, что мы могли продолжать использовать ext4, но записывать файлы .odex в раздел B на заводе, а затем копировать их в /data
при первой загрузке. Фактическое хранилище, используемое с ext4 A/B, идентично SquashFS A/B, потому что если бы мы использовали SquashFS, мы бы отправили предварительно настроенные файлы .odex на system_a вместо system_b.
Не означает ли копирование файлов .odex в /data, что сэкономленное в /system место будет потеряно в /data?
Не совсем так. На Pixel большая часть места, занимаемого файлами .odex, предназначена для приложений, которые обычно находятся в /data
. Эти приложения используют обновления Google Play, поэтому файлы .apk и .odex в образе системы не используются большую часть срока службы устройства. Такие файлы можно полностью исключить и заменить небольшими файлами .odex, управляемыми профилем, когда пользователь фактически использует каждое приложение (таким образом, не требуя места для приложений, которые пользователь не использует). Подробности см. в докладе Google I/O 2016 The Evolution of Art .
Сравнение затруднено по нескольким основным причинам:
- Приложения, обновляемые через Google Play, всегда помещают свои файлы .odex в папку
/data
сразу после получения первого обновления. - Приложениям, которые пользователь не запускает, файл .odex вообще не нужен.
- Компиляция на основе профилей создает файлы .odex меньшего размера, чем предварительная компиляция (поскольку первая оптимизирует только критически важный для производительности код).
Подробную информацию о возможностях настройки, доступных OEM-производителям, см. в разделе Настройка ART .
Разве в /data нет двух копий файлов .odex?
Это немного сложнее... После того, как новый образ системы записан, новая версия dex2oat запускается против новых файлов .dex для генерации новых файлов .odex. Это происходит, пока старая система все еще работает, поэтому старые и новые файлы .odex находятся в /data
одновременно.
Код в OtaDexoptService ( frameworks/base/+/android16-release/services/core/java/com/android/server/pm/OtaDexoptService.java
) вызывает getAvailableSpace
перед оптимизацией каждого пакета, чтобы избежать переполнения /data
. Обратите внимание, что available здесь по-прежнему консервативен: это объем оставшегося места до достижения обычного системного порога низкого пространства (измеряемого как в процентах, так и в байтах). Таким образом, если /data
заполнен, не будет двух копий каждого файла .odex. В этом же коде также есть BULK_DELETE_THRESHOLD: если устройство приближается к заполнению доступного пространства (как только что описано), файлы .odex, принадлежащие неиспользуемым приложениям, удаляются. Это еще один случай без двух копий каждого файла .odex.
В худшем случае, когда /data
полностью заполнен, обновление ждет, пока устройство перезагрузится в новую систему и больше не будет нуждаться в файлах .odex старой системы. PackageManager обрабатывает это: ( frameworks/base/+/android16-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215
). После успешной загрузки новой системы installd
( frameworks/native/+/android16-release/cmds/installd/dexopt.cpp#2422
) может удалить файлы .odex, которые использовались старой системой, вернув устройство в устойчивое состояние, в котором есть только одна копия.
Итак, хотя возможно, что /data
содержит две копии всех файлов .odex, (a) это временно и (b) происходит только если у вас в любом случае было много свободного места на /data
. За исключением времени обновления, есть только одна копия. И как часть общих функций надежности ART, он никогда не будет заполнять /data
файлами .odex в любом случае (потому что это было бы проблемой и в не-A/B системе).
Разве все эти записи/копирования не увеличивают износ вспышки?
Переписывается лишь небольшая часть флэш-памяти: полное обновление системы Pixel записывает около 2,3 ГБ. (Приложения также перекомпилируются, но это касается и не-A/B.) Традиционно блочные полные OTA-приложения записывали схожий объем данных, поэтому показатели износа флэш-памяти должны быть схожими.
Увеличивает ли время заводской прошивки перепрошивка двух системных разделов?
Нет. Пиксель не увеличил размер образа системы (он просто разделил пространство на два раздела).
Не замедляет ли сохранение файлов .odex на диске B перезагрузку после сброса настроек к заводским?
Да. Если вы действительно использовали устройство, сделали OTA и выполнили сброс настроек к заводским, первая перезагрузка будет медленнее, чем могла бы быть (1м40с против 40с на Pixel XL), потому что файлы .odex будут утеряны из B после первого OTA и поэтому не могут быть скопированы в /data
. Это компромисс.
Сброс заводских данных должен быть редкой операцией по сравнению с обычной загрузкой, поэтому затраченное время менее важно. (Это не влияет на пользователей или рецензентов, которые получают свои устройства с завода, потому что в этом случае раздел B доступен.) Использование JIT-компилятора означает, что нам не нужно перекомпилировать все , так что это не так плохо, как вы могли бы подумать. Также можно пометить приложения как требующие предварительной компиляции, используя coreApp="true"
в манифесте: ( frameworks/base/+/android16-release/packages/SystemUI/AndroidManifest.xml#23
). В настоящее время это используется system_server
, поскольку JIT не разрешен по соображениям безопасности.
Не замедляет ли хранение файлов .odex в /data, а не в /system, перезагрузку после OTA?
Нет. Как объяснялось выше, новый dex2oat запускается, пока старый образ системы все еще работает, чтобы сгенерировать файлы, которые понадобятся новой системе. Обновление не считается доступным, пока эта работа не будет выполнена.
Можем ли (нужно ли) мы поставлять устройство A/B на 32 ГиБ? 16 ГиБ? 8 ГиБ?
32 ГиБ работают хорошо, как было доказано на Pixel, а 320 МБ из 16 ГиБ означает сокращение на 2%. Аналогично, 320 МБ из 8 ГиБ означает сокращение на 4%. Очевидно, что A/B не будет рекомендуемым выбором для устройств с 4 ГиБ, поскольку накладные расходы в 320 МБ составляют почти 10% от общего доступного пространства.
Требуются ли для AVB2.0 A/B OTA?
Нет. Android Verified Boot всегда требовал обновлений на основе блоков, но не обязательно обновлений A/B.
Требуется ли для A/B OTA AVB2.0?
Нет.
Нарушают ли A/B OTA защиту от отката AVB2.0?
Нет. Здесь есть некоторая путаница, потому что если система A/B не может загрузить новый образ системы, она (после некоторого количества повторных попыток, определяемых вашим загрузчиком) автоматически вернется к «предыдущему» образу системы. Однако ключевым моментом здесь является то, что «предыдущий» в смысле A/B на самом деле все еще является «текущим» образом системы. Как только устройство успешно загружает новый образ, срабатывает защита от отката, которая гарантирует, что вы не сможете вернуться назад. Но пока вы фактически не загрузите новый образ успешно, защита от отката не считает его текущим образом системы.
Если вы устанавливаете обновление во время работы системы, разве это не медленно?
При обновлениях не-A/B цель состоит в том, чтобы установить обновление как можно быстрее, поскольку пользователь ждет и не может использовать свое устройство, пока применяется обновление. При обновлениях A/B все наоборот: поскольку пользователь все еще использует свое устройство, целью является как можно меньшее воздействие, поэтому обновление намеренно выполняется медленно. С помощью логики в клиенте обновления системы Java (который для Google является GmsCore, основным пакетом, предоставляемым GMS), Android также пытается выбрать время, когда пользователи вообще не используют свои устройства. Платформа поддерживает приостановку/возобновление обновления, и клиент может использовать это, чтобы приостановить обновление, если пользователь начинает использовать устройство, и возобновить его, когда устройство снова бездействует.
При выполнении OTA есть две фазы, которые четко показаны в пользовательском интерфейсе как Шаг 1 из 2 и Шаг 2 из 2 под полосой прогресса. Шаг 1 соответствует записи блоков данных, в то время как шаг 2 — это предварительная компиляция файлов .dex. Эти две фазы довольно сильно различаются с точки зрения влияния на производительность. Первая фаза — это простой ввод-вывод. Это требует немного ресурсов (ОЗУ, ЦП, ввод-вывод), потому что это просто медленное копирование блоков.
Вторая фаза запускает dex2oat для предварительной компиляции нового образа системы. Очевидно, что это имеет менее четкие границы требований, поскольку компилирует реальные приложения. И очевидно, что для компиляции большого и сложного приложения требуется гораздо больше работы, чем для небольшого и простого приложения; тогда как на фазе 1 нет блоков диска, которые больше или сложнее других.
Процесс похож на тот, когда Google Play устанавливает обновление приложения в фоновом режиме, прежде чем отобразить уведомление о пяти обновленных приложениях , как это делалось на протяжении многих лет.
А что, если пользователь на самом деле ждет обновления?
Текущая реализация в GmsCore не различает фоновые обновления и обновления, инициированные пользователем, но может сделать это в будущем. В случае, если пользователь явно запросил установку обновления или наблюдает за экраном хода обновления, мы отдадим приоритет работе по обновлению, предполагая, что он активно ждет его завершения.
Что произойдет, если не удастся применить обновление?
При не-A/B обновлениях, если обновление не применялось, пользователь обычно оставался с непригодным для использования устройством. Единственным исключением был случай, когда сбой происходил до запуска приложения (например, из-за того, что пакет не прошел проверку). При A/B обновлениях сбой в применении обновления не влияет на текущую работающую систему. Обновление можно просто повторить позже.