Аннотация
Проект показал, что визуальную идентичность старой Xperia можно вернуть на Android 13 без переноса несовместимого Sony SystemUI. Однако на платформе msm8974 внешний вид нельзя отделить от композиции кадров: прозрачность, затемнение и смена ориентации напрямую определяют нагрузку на HWC, MDP и GLES.
- Финальный образ
- LineageOS 20 v72 + runtime v1.3
- Экран
- 1080 × 1920, 60 Гц
- Композиция
- HWC2 / MDP + GLES
- Root
- Magisk 30.7
Современный framework на аппаратуре 2013 года
Главное ограничение проекта задавал не Android 13 сам по себе, а взаимодействие нового оконного стека со старым графическим драйвером Qualcomm.
Xperia Z Ultra C6833 построен на Snapdragon 800, оснащён 2 ГБ RAM и GPU Adreno 330. Физический дисплей работает в режиме MIPI-DSI video с разрешением 1080 × 1920 при 60 Гц. Следовательно, новый кадр должен быть подготовлен примерно за 16,67 мс.
LineageOS 20 переносит на аппарат современный SurfaceFlinger, WindowManager и SystemUI. Но vendor-часть остаётся наследием msm8974. Между ними работает совместимый HWC-слой, который решает, какие поверхности можно отдать аппаратным плоскостям MDP, а какие нужно предварительно собрать GPU в единый client target.
Проблема проявлялась не как одна ошибка. Пользователь видел тормоза при закрытии шторки, задержки в меню, нестабильный ползунок яркости, белую или чёрную область в правом нижнем углу, а также тяжёлые переходы при смене ориентации. Эти симптомы оказались разными выходами одной системы: политика композиции, синхронизация поверхностей и фоновая нагрузка на system_server.
| Узел | Конфигурация | Инженерное значение |
|---|---|---|
| Устройство | Sony Xperia Z Ultra C6833, togari | ARM32, 2 ГБ RAM, старый bootloader Sony |
| SoC | Qualcomm Snapdragon 800 / msm8974 | Ограниченный запас CPU и пропускной способности памяти |
| GPU | Adreno 330 | Чувствительность к полному GLES-композитингу 1080p |
| Панель | sharp renesas 1080p video new id | 1080 × 1920 при 60 Гц, MIPI-DSI video |
| Тач | MAX1187x, I2C 0x48 | Отдельная проверка геометрии жестов в портрете и landscape |
| Система | LineageOS 20 / Android 13 | Новый SystemUI поверх legacy vendor stack |
Реконструкция Sony UI вместо пересадки старого SystemUI
Старый системный APK Android 5.1 несовместим с framework Android 13. Поэтому перенос выполнен на уровне ресурсов, геометрии и новых компонентов.
Экран блокировки Sony 5.1 использовал старые private API, ODEX, signature-разрешения и механизм Runtime Skinning. Прямая установка такого SystemUI.apk на Android 13 привела бы к циклическому падению интерфейса. Вместо этого крупные двухъярусные часы Xperia были реализованы внутри современного Keyguard, сохранив актуальные механизмы PIN, уведомлений и системной безопасности.
Геометрия рассчитывалась не по физической диагонали, а по фактической плотности и доступной области экрана. В портрете часы занимают визуальный центр верхней половины. В landscape отдельная раскладка учитывает системную навигационную полосу: в финальной ветке центр замка задан по ширине content area 1824 px, то есть x = 912 px.
Xperia Home и меню приложений
Оригинальный Home 5.1 также нельзя было переносить побайтово. В основу взят более новый Xperia Home, совместимый с Android 13. В нём сохранена логика рабочего стола и локальная миграция настроек, отключены необязательные аналитические точки запуска, а визуальные ресурсы меню приложений заменены материалами C6833.
Стоковый набор использовал 56dp-иконки и 15sp-подписи для профиля sw360dp. Но итоговая сетка вычисляется современным launcher-кодом для текущей плотности. Это визуальная реконструкция, а не запуск бинарного Sony Home из прошивки 14.6.A.1.236.
Стоковый набор обоев и медиа
Из эталонной прошивки C6833 14.6.A.1.236 извлечены полноразмерные обои, миниатюры, UI-звуки и загрузочная анимация 1080 × 1920. Источником FTF было стороннее зеркало, поэтому корректная формулировка здесь важна: совпадают модель и номер сборки, но принадлежность ресурсов прежнему региональному пакету не доказана официальной подписью Sony.
Диагностика по слоям, кадрам и журналам
Субъективное ощущение лагов использовалось как триггер, но решение принималось только после сопоставления нескольких независимых измерений.
На 60-герцовом дисплее один период развёртки составляет 16,67 мс. Интервал свыше 33 мс уже означает пропуск как минимум одного периода. Но gfxinfo описывает работу приложения, а временная шкала SurfaceFlinger отражает вывод композиции на дисплей. Поэтому эти метрики нельзя механически складывать или подменять одной другой.
Каждая гипотеза проверялась повторяемым жестом, очисткой статистики перед серией, снимком HWC-состава во время проблемного состояния и кадрами, захваченными непосредственно в переходе. После теста отдельно проверялись ANR, crash и FATAL-события.
dumpsys gfxinfo
Кадры приложения
FrameStats, p50, p90, p95, p99 и доля modern jank.
dumpsys SurfaceFlinger
Фактическая композиция
DEVICE или CLIENT, client target, слои и интервалы вывода.
logcat + events
Системные события
ANR, перезапуски, FATAL, HWC-ошибки и блокировки WindowManager.
screencap
Пространственный контроль
Серия кадров во время жеста для поиска чёрного или белого угла.
Почему угол мигал чёрным, а затем белым
Артефакт возникал на границе режимов композиции, когда полупрозрачная поверхность меняла состав кадра быстрее, чем legacy HWC стабильно перестраивал плоскости.
Первые попытки лечить мигающий угол полным переводом сцены в GLES устраняли часть повреждённых кадров, но резко увеличивали время рендеринга. Обратная крайность, принудительный MDP для любой поверхности, ломала эффекты, которые аппаратные плоскости не могли корректно представить.
Рабочая политика появилась после разделения слоёв по назначению. Обычные непрозрачные окна, рабочий стол и закрывающаяся шторка оставались на MDP. Только эффектные и dim-слои получали GLES fallback. При смене ориентации HWC-кэш обновлялся, а формат поверхности SystemUI не менялся в терминальном кадре закрытия.
В v71 подложка шторки стала непрозрачной, но живой launcher под ней сохранился. Это убрало чёрный полноэкранный буфер при закрытии и не уничтожило параллакс обоев. В проверке v72 шесть последовательных кадров закрытия не содержали ни чёрного, ни белого промежуточного экрана.
Passenger Control: 483 мс превратились в 16,7 мс
Окно настроек автомобильного приложения стало стресс-тестом для всей графической архитектуры.
Passenger Control 1.40.0-beta13 открывает большое дополнительное окно с полупрозрачным системным затемнением позади. На msm8974 один HWC2 solid-color dim effect между двумя buffered windows переводил весь дисплей в legacy GLES client target. В v71 прокрутка настроек давала p50 около 300 мс и p95 около 483 мс. Одновременно появлялся белый или чёрный угол.
Глобальное отключение dim было бы неправильным: оно изменило бы поведение всех приложений. В v72 условие помещено в WindowState.applyDims() и ограничено пакетом ru.monjaro.passengercontrol.client. Для остальных окон Android логика затемнения не меняется.
final boolean suppressPassengerControlDim =
"ru.monjaro.passengercontrol.client".equals(mAttrs.packageName);
if (!suppressPassengerControlDim
&& ((mAttrs.flags & FLAG_DIM_BEHIND) != 0
|| shouldDrawBlurBehind())
&& isVisibleNow() && !mHidden) {
// Стандартный системный dim для остальных окон
}
Серия v72: 12 прокруток, 126 интервалов SurfaceFlinger, один интервал свыше 33 мс; gfxinfo зафиксировал 2 проблемных кадра из 441.
usesClientComposition=false.Исправление запоздалого ANR не должно само создавать лаги
Системная защита и Magisk-сценарий были переработаны как единый контур, потому что резервные копии скрипта неожиданно стали частью проблемы.
Исходный дефект заключался в гонке: приложение успевало восстановить обработку ввода, но уже подготовленное сообщение о показе ANR-диалога оставалось в очереди UI Handler. В framework введён токен конкретного ANR-события. Когда input dispatch возобновляется, токен, отложенное сообщение и видимый диалог очищаются атомарно. Устаревшее сообщение больше не может воскресить завершившийся ANR.
Дополнительный root-сценарий служит ограниченной страховкой. Он подписывается на am_anr, открывает 75-секундное окно частых проверок и выбирает только кнопку Wait по resource id aerr_wait. Принудительное закрытие, очистка данных и изменение пакета не выполняются.
После прошивки выяснилось, что Magisk исполнял не только основной файл, но и три резервные копии .bak-*, оставленные внутри /data/adb/service.d. В результате появилось 12 лишних процессов, а две старые копии вызывали дорогой dumpsys window каждую секунду. Binder-нагрузка system_server достигала примерно 31%.
- Исполняемые backup-файлы Magisk просматривает service.d и запускает все подходящие скрипты.
- Дублированные мониторы Главный файл и три копии создают 12 дополнительных процессов.
- WindowManager под опросом Два dumpsys window в секунду занимают binder-потоки system_server.
- Задержка UI Финальные фазы свайпа и возврата на рабочий стол теряют кадры.
Исправление
Резервные копии были обратимо перенесены в /data/adb/togari-script-backups/20260827-anr-autowait, завершены только процессы с точным совпадением командной строки, а основной скрипт получил singleton-lock через атомарное создание каталога. После этого доля CPU у system_server снизилась примерно до 3,1%.
Финальный стресс-тест включал 30 быстрых перелистываний Xperia Home. gfxinfo показал 701 кадр, 0 modern jank и 0 legacy jank; p50, p90, p95 и p99 составили 9, 9, 10 и 11 мс. SurfaceFlinger при этом зарегистрировал три интервала свыше 33 мс из 125, поэтому корректный вывод звучит как устранение регулярного launcher-лага, а не обещание математически идеального вывода.
Два системных дефекта выглядели как один общий тормоз
Падение Google Play было вызвано неполным набором привилегированных сервисов, а тяжёлый экран недавних приложений зависел от отдельного Quickstep и незавершённого анимационного handoff.
Google Play: восстановление системного контракта
В исходном состоянии Play Store завершался с ошибкой Failed to load configurations for FinskyApp. В журнале отсутствовал provider com.google.android.gsf.gservices. Это указывало не на сетевой сбой и не на повреждение пользовательских данных, а на отсутствие Google Services Framework и согласованного привилегированного окружения для Play Services и Phonesky.
Для частного устройства собран Magisk-модуль togari_minimal_gapps v1.3. Он монтирует Google Services Framework в system_ext/priv-app, GmsCore и Phonesky в product/priv-app, а также добавляет соответствующие privapp-permissions, default-permissions и sysconfig. После перезагрузки PackageManager распознал все три пакета как SYSTEM и PRIVILEGED; разрешения MANAGE_USERS, INTERACT_ACROSS_USERS и READ_DEVICE_CONFIG выданы. Контрольный запуск дошёл до AssetBrowserActivity, а в окне проверки не было FATAL, crash или ANR для Play Store.
- Sony Home Рабочий стол остаётся приложением по умолчанию и отвечает за Xperia UI.
- Кнопка Recents Системный жест передаётся не Sony Home, а отдельному Quickstep.
-
Launcher3 Quickstep
com.android.quickstep.RecentsActivityсобирает полноразмерные task snapshots. - Surface handoff Завершённая анимация освобождает recents surface и возвращает композицию Home.
Почему нулевая анимация оказалась медленнее
В проверяемой конфигурации Sony Home был default launcher, но экран недавних приложений обслуживал com.android.launcher3/com.android.quickstep.RecentsActivity. При значениях window_animation_scale=0 и transition_animation_scale=0 визуальная часть перехода исчезала, однако recents animation input consumer и связанные поверхности иногда оставались активными уже после возврата Home. В таком состоянии SurfaceFlinger продолжал занимать примерно 80-118% одного CPU, поэтому последующие переходы выглядели всё тяжелее.
Все три коэффициента анимации установлены в 0,5. Это не декоративная мера, а восстановление времени, необходимого WindowManager и Quickstep для штатного завершения протокола перехода. После закрытия Recents рабочий стол снова становится resumed activity, а нагрузка SurfaceFlinger через несколько секунд возвращается к 0%. Прямые прогретые запуски дали 91 и 83 мс; первый запуск уже поднятого сервиса занял 292 мс.
Фоновая нагрузка как независимый фактор
Отдельный эксперимент локализовал ещё один источник деградации. При активном Яндекс Диске его три процесса занимали около 300 МБ resident memory, основной процесс потреблял примерно 25-85% CPU, а доступная память снижалась примерно до 86 МБ. В журналах одновременно наблюдались запуск Activity за 5,239 с, pause timeout и обработка focus event продолжительностью 3096 мс. После обратимого force-stop SurfaceFlinger вернулся к 0% в покое, а свободная память выросла примерно до 195 МБ.
Автосинхронизация Яндекс Диска не отключалась и фоновые ограничения пакета не менялись. Поэтому повторное открытие приложения может снова создать нагрузку. Этот фактор нельзя смешивать с исправлением Quickstep: он подтверждает, что на устройстве с 2 ГБ RAM один тяжёлый клиент способен исчерпать запас памяти и пропускной способности всей графической системы.
Один блок ART потребовал корректной хирургии ext4
Изменение framework было мало написать и скомпилировать. Его нужно было поместить в Sony-совместимый sparse image без повреждения ext4.
Патч v72 изменил services.jar и соответствующие AOT-артефакты. Новый services.art оказался ровно на один блок 4096 байт больше прежнего extent. Обычная замена файла нарушила бы размещение следующих данных или метаданные файловой системы.
Скрипт v72-extend-services-art.py использовал debugfs fallocate, сопоставил логический блок 515 со свободным физическим блоком 408246, обновил ext4 metadata и добавил соответствующий RAW-chunk в sparse-поток. После упаковки проверены SELinux xattr, e2fsck -fn и точное совпадение sparse-to-raw round trip.
- Новый framework services.jar, art, odex и vdex собираются согласованным набором.
- Расширение extent Логический блок 515 получает свободный физический блок 408246.
- Sony sparse Новый RAW-chunk вставляется без повторного преобразования старым bootloader.
- Верификация xattr, e2fsck, SHA-256 и побайтовый raw round trip.
a9ecbbb13a4832e3ce2acf34ec9cf2670ed09fd2115be1952fcd1feab09a67dc
db1a92c6b1530d71252648dae9100a28e869fdf4d257bec5729e7d9005f42056
16ea8a4436b8719ed3b8069b4a763383968b51940006385c915055d96b5b286d
51978cfcbb44a2040117e996e3c8a97d00016e101429a6350a5d3e19e15cd514
600dd1ed1a3c8adc99c616b9037db8d222eb8b97b5db666b9adfc99d2d014175
83cc66666d146c64f255afe61ca98e69a3950b69f14a37ace0d8364ec81c2121
16835f476f1e87293f77993cf078b4d478071acd4224c7275f9e2b59dc7d00a4
Что подтверждено на физическом C6833
Таблица отделяет проверенные результаты от остаточных ограничений. Это важнее формулировки «всё быстро».
| Подсистема | Проверка | Результат | Статус |
|---|---|---|---|
| Загрузка | Фактическая прошивка system-v72.img | sys.boot_completed=1, стабильный запуск |
Подтверждено |
| Passenger Control | 12 прокруток окна настроек | p50/p95 16,7 мс; 2/441 jank, 0,45% | Подтверждено |
| Графический артефакт | 8 mid-scroll кадров Passenger Control | Чёрный или белый угол не обнаружен | Подтверждено |
| Страницы приложения | 5 разделов, без команд автомобилю | 15 переходов, 1/30 jank, 3,33% | Подтверждено |
| Xperia Home | 30 быстрых свайпов после service.d fix | 0/701 jank; p95 10 мс; параллакс работает | Подтверждено |
| Google Play | Привилегированный runtime v1.3 и контрольный запуск | GSF provider доступен; AssetBrowserActivity работает; новых FATAL нет | Подтверждено |
| Recents | Отдельный Quickstep, scale 0,5 и возврат на Home | Горячие запуски 91 и 83 мс; поверхность завершается штатно | Подтверждено |
| Холодный Recents | Первый запуск поднятого сервиса | 292 мс; snapshots сохраняют полное разрешение | Ограничение |
| Закрытие шторки | 6 последовательных переходных кадров | Чёрный или белый полноэкранный кадр не обнаружен | Подтверждено |
| SystemUI | 5 циклов шторки | 19/177 modern jank, 10,73% | Ограничение |
| Ориентация | Портрет и landscape | Геометрия исправлена, переход всё ещё может выглядеть тяжёлым | Ограничение |
| Root | Magisk su | uid=0, контекст u:r:magisk:s0 |
Подтверждено |
| Сеть | Wi-Fi после загрузки | Интерфейс включён и подключён | Подтверждено |
| Стабильность | Журналы после финального теста | Новых ANR, am_crash и FATAL нет | Подтверждено |
Современные безопасность, bouncer и lifecycle сохранены. Старые бинарные компоненты Sony не запускаются.
Adreno 330 и 2 ГБ RAM остаются физическим пределом. Редкие длинные интервалы SurfaceFlinger возможны.
Перестройка буферов 1080p и HWC-кэша заметнее обычных переходов, особенно под нагрузкой.
Яндекс Диск не ограничен постоянно. Его повторный запуск способен вернуть дефицит RAM и общесистемные задержки.
Реставрация интерфейса оказалась задачей системной инженерии
Xperia Z Ultra удалось вернуть визуальный язык Sony и одновременно сохранить Android 13. Ключ к результату был не в тотальном ускорении и не в глобальном отключении эффектов, а в локальных правилах: правильный слой отправляется в правильный композитор, конкретный ANR получает собственный токен, Google runtime восстанавливается согласованным набором, а Quickstep получает время для корректного завершения lifecycle.