Когда в 2021 году Microsoft объявила, что Windows 11 сможет запускать Android-приложения как обычные окна на рабочем столе, реакция инженерного сообщества была сдержанно-любопытной: подобные попытки делались неоднократно и почти всегда упирались либо в производительность, либо в совместимость. Windows Subsystem for Android, сокращенно WSA, стала одной из самых технически амбициозных попыток решить обе проблемы сразу. Подсистема просуществовала с 2021 по 2024 год, после чего была объявлена к выводу из поддержки с окончательным сроком в марте 2025 года. Эта статья не некролог и не реклама: это технический разбор того, как WSA была устроена внутри, какие инженерные решения делали её возможной, почему архитектура определила и её сильные стороны, и её пределы, и какой урок она оставляет проектировщикам слоёв совместимости.

Виртуальная машина как фундамент и ядро AOSP внутри Utility VM

Ключевое архитектурное решение WSA состояло в отказе от эмуляции аппаратуры. Эмуляторы, к которым привыкли разработчики, строят виртуальное устройство целиком: виртуальный процессор, виртуальную память, виртуальные периферийные устройства, и поверх всего этого интерпретируют или транслируют гостевой код. Такой подход универсален, но дорог: каждая инструкция и каждое обращение к устройству облагаются накладными расходами. WSA пошла по пути WSL2: Android запускался внутри легковесной виртуальной машины на гипервизоре Hyper-V, той самой Utility VM, которую хостующая Windows не показывает пользователю как отдельную сущность, но которая является полноценным изолированным разделом со своим ядром.

Внутри этой машины работала настоящая система на базе Android Open Source Project с ядром Linux, собранным под архитектуру x86-64. Это важно подчеркнуть: гость не был "портом" Android и не был прослоечной реализацией API поверх Windows, как это делала например Wine для Win32-приложений или как был устроен первый WSL. Это была подлинная ОС с собственным init, собственным zygote, собственным ART, собственной моделью процессов и песочниц на базе UID. Windows видела снаружи только виртуальную машину целиком и набор каналов интеграции, через которые гость и хост обменивались окнами, звуком, вводом и данными.

Сравнение с WSL2 здесь не метафора, а буквальное описание родословной. Обе подсистемы используют общий инженерный паттерн Microsoft конца 2010-х: взять гипервизор, поднять в нём специализированную виртуальную машину, оптимизированную под быстрый старт и динамическое выделение памяти, и построить поверх неё мосты интеграции, чтобы гостевая среда ощущалась частью хоста. WSL2 доставляет ядро Linux тем же способом; WSA добавила к этому целый Android-стек. Разница принципиальна в масштабе: вместо консольных процессов гость производит полноценные GUI-приложения, и интеграция должна работать на уровне пикселей, окон и событий ввода, а не только stdout и файловой системы.

У Utility VM-подхода есть важное следствие для производительности: гостевой код на совместимой архитектуре исполняется процессором напрямую благодаря аппаратной виртуализации, без интерпретации. Android-приложение, собранное под x86, работало в WSA почти с нативной скоростью, потому что инструкции доходили до кремния практически без посредников. Накладные расходы оставались лишь в точках интеграции: отрисовка окон, ввод, звук, файловый мост.

Композитор окон и интеграция по образцу WSLg

Самая зрелищная часть WSA - механизм, благодаря которому Android-активность становилась обычным окном Windows с ручкой, заголовком, иконкой на панели задач и поддержкой Alt-Tab. Здесь Microsoft применила архитектуру, прямо унаследованную от WSLg, подсистемы графики для WSL2, представленной чуть раньше. Схема выглядит так: внутри гостя работает композитор, построенный на протоколе Wayland. Приложение рисует в буферы, композитор собирает из них кадр, но вместо вывода на гостевой виртуальный экран содержимое окон передаётся на хост, где специальный компонент интеграции создаёт соответствующие окна Win32 и отображает в них полученные поверхности.

Технически важны две вещи. Первая - шеринг буферов: кадры не кодируются в видеопоток и не пересылаются как картинки по сети. Используются разделяемые области памяти и GPU-ориентированные механизмы обмена поверхностями, поэтому кадр путешествует от гостевого приложения до окна хоста по существу передачей ссылки на буфер с минимальным числом копирований. Это тот же принцип, что и Wayland-подход "клиент владеет буфером", протянутый через границу виртуальной машины. Вторая - двустороннее отображение сущностей: каждое окно Android получает зеркальное окно Windows, а события ввода - позиции указателя, кнопки мыши, прокрутка, клавиатура, системные жесты - транслируются обратно в гостевую систему как события Android input pipeline, вплоть до мультитач-эмуляции для приложений, ожидающих сенсорный экран.

На этом же канале интеграции ехали и остальные удобства: общий буфер обмена между хостом и гостем (текст и изображения копировались из Android-приложения прямо в Windows и обратно), звук, выводимый приложением через гостевой аудиостек и воспроизводимый через аудиоустройство хоста, уведомления, прокидываемые в центр уведомлений Windows. Изнутри Windows это выглядело родным: процессы гостя появлялись в диспетчере задач под общим сердцем подсистемы, а переключение между окнами работало единообразно. Инженерно это впечатляющий результат: две ОС с радикально разными оконными моделями - неявные полноэкранные активности против свободно размещаемых окон десктопа - были состыкованы без переписывания ни одной из сторон.

Файловый мост, сеть и поверхность интеграции

Гостевая система живёт в своей файловой системе, но пользователь ожидает, что приложение откроет его документ и сохранит файл туда, где ему удобно. WSA решала это файловым мостом: каталоги хоста пробрасывались в гостевое пространство как shared folders, доступные Android-приложениям через стандартные механизмы scoped storage. Планировка здесь та же, что у 9P-подобного обмена в WSL: протокол поверх канала виртуальной машины, транслирующий файловые операции гостя в вызовы хоста, с трансляцией прав и семантики. Различия файловых семантик двух миров - регистр имён, права, отсутствие POSIX-атрибутов у NTFS в нужном виде - разрешались внутри моста, что является классической нерешаемой-идеально задачей: мост достаточно хорош для документов и медиа, но не является прозрачной заменой родной файловой системы.

Сеть по умолчанию строилась как NAT за виртуальным коммутатором Hyper-V: гость получал приватный адрес, исходящий трафик транслировался через адрес хоста, входящих соединений не было. Для обычных приложений этого достаточно. Но для разработки и отладки, где нужно подключиться к устройству по ADB или обратиться к сервису в госте, Microsoft добавила режим advanced networking, в котором гостевой сетевой стек получал адрес в той же сети, что и хост, и ADB-подключение упрощалось. Разделение режимов отражает здравый инженерный компромисс: изоляция по умолчанию, проницаемость по требованию.

ADB заслуживает отдельного упоминания как инструментальная артерия всей подсистемы. Поскольку встроенный магазин приложений покрывал ограниченный каталог, а механизма установки произвольных пакетов в графическом интерфейсе не было, значительная часть пользователей и практически все разработчики устанавливали приложения через adb install по сетевому подключению к гостю. Подсистема, задуманная для потребительского сценария, в реальности работала во многом как удобная локальная среда исполнения APK с отличной интеграцией в десктоп - что, как будет видно дальше, было и силой, и симптомом проблемы.

Intel Bridge Technology и призрак Transmeta Crusoe

Главная техническая сложность WSA скрывалась ниже уровня виртуализации и касалась архитектуры набора команд. Подавляющее большинство Android-приложений несёт нативные библиотеки, собранные под ARM - именно ARM доминирует на рынке устройств, под которые собираются APK. Запуск таких приложений на x86-хосте через виртуализацию невозможен: гипервизор исполняет гостевой код напрямую только при совпадении архитектур. Чистая интерпретация ARM на x86 дала бы производительность на порядки ниже приемлемой. Решением стал Intel Bridge Technology - бинарный транслятор, встроенный в гостевую систему и работающий как пост-г бинарный рантайм: при загрузке ARM-библиотеки транслятор переводил её машинный код в x86-эквивалент, кэшировал результат и исполнял уже транслированный код почти с нативной скоростью.

Идейный дедушка этого подхода - процессор Transmeta Crusoe рубежа веков. Crusoe физически исполнял собственный VLIW-набор инструкций, а поддержку x86 обеспечивал слой Code Morphing Software, динамически транслировавший x86-код во внутренний формат с агрессивным кэшированием и оптимизацией горячих участков. Коммерчески проект Transmeta не выдержал конкуренции, но идея оказалась долгоживущей: динамическая бинарная трансляция как способ совместимости архитектур. Та же идея позже дала Apple Rosetta и Rosetta 2 при переходах на PowerPC-to-Intel и Intel-to-ARM, динамические трансляторы в консольной эмуляции, и наконец Intel Bridge Technology в WSA. Линия преемственности здесь почти прямая: рынок раз за разом подтверждает, что программная трансляция ISA, сделанная качественно и глубоко интегрированная в систему, жизнеспособна.

Практические свойства транслятора в WSA были типичными для класса: первый запуск приложения заметно медленнее из-за трансляции, повторные - быстрые за счёт кэша; приложения без нативного кода (чистый байт-код, исполняемый ART) работали идеально, поскольку ART в госте сам компилировал его под x86; приложения с ARM-only библиотеками работали через транслятор с непредсказуемыми оговорками. Оговорки важнее всего: транслятор покрывал основной набор инструкций, но библиотеки, активно использующие специфические расширения или самомодифицирующийся код, могли падать или вести себя нестабильно. Для системного инженера это знакомый силуэт: бинарная трансляция даёт 95% совместимости, а оставшиеся 5% концентрируются именно в тех приложениях, которые пользователь хотел запустить больше всего.

Пределы модели с сервисами, ARM-only библиотеками и мышью против тач-интерфейсов

Ограничения WSA не были случайными недоработками - они вырастали прямо из архитектурных выборов. Первое и главное: гость базировался на AOSP, а AOSP не включает проприетарный слой сервисов Google Mobile Services. Значительная часть экосистемы Android - карты, push-уведомления, геолокация, оплата, проверка целостности устройства - написана поверх GMS API, которого в подсистеме не существовало. Приложения, жёстко зависящие от GMS, либо не запускались, либо деградировали. Встроенный канал распространения шёл через Amazon Appstore, чей каталог был на порядок меньше привычного пользователям полного каталога Google Play. Архитектурно закрыть эту дыру было невозможно без лицензии на поставку сервисов, а это уже не инженерный, а коммерческий вопрос.

Второе: ARM-only библиотеки. Транслятор решал задачу хорошо, но не идеально, а любое падение внутри транслированного кода диагностировать сложнее, чем в нативной среде. Третье: ввод. Android-приложения проектируются под тач: жесты, свайпы, масштабные анимации, крупные цели нажатия. Мышь и клавиатура отображались на этот мир функционально - клик как тап, прокрутка как свайп - но не идиоматически. Приложения оставались чужеродными по ощущению, и никакой мост интеграции не мог переписать их UI-логику. Плюс издержки самой модели: резервирование памяти под виртуальную машину, необходимость виртуализации в системе, конфликты с иным софтом, зависящим от гипервизора.

Совокупность этих пределов определяла потолок подсистемы независимо от качества её исполнения. WSA была инженерно сильной, но рынок измеряет не элегантность транслятора, а число приложений, которые пользователь может просто установить и которыми может просто пользоваться.

Сворачивание проекта и судьба экосистемы

В марте 2024 года Microsoft объявила о выводе WSA из поддержки: новые установки прекращались сразу, а поддержка существующих пользователей - 5 марта 2025 года. Параллельно закрывался и связанный канал распространения Android-приложений на Windows. Формальных технических причин в объявлении не называлось, но наблюдаемая логика прозрачна: подсистема не достигла массового принятия, каталог оставался узким, поддержка связки "гипервизор плюс гостевая ОС плюс транслятор плюс мост интеграции" требовала постоянных инженерных затрат на каждое обновление Windows и каждое обновление Android-стека. Стоимость владения оказалась несоразмерной аудитории.

Интересно проследить, что стало с экосистемой после. Ниша "Android на десктопе" не исчезла - она вернулась к своим историческим носителям. Полномасштабные эмуляторы для разработчиков, прежде всего штатный эмулятор из Android SDK, продолжают развиваться и к настоящему времени сами широко используют аппаратную виртуализацию хоста, заимствуя фактически те же приёмы ускорения, что доказывала WSA. Игровые проигрыватели приложений заняли потребительскую нишу. Направление, которое можно назвать наиболее символичным, - сближение платформ со стороны Google: работы по объединению ChromeOS и Android-стека и появление официального для разработчиков способа запуска Android-приложений на ПК показывают, что спрос на скрещивание миров существует, но реализовать его намерен тот, кто владеет обеими половинами, включая сервисный слой. WSA демонстрирует обратный случай: Microsoft владела только половиной хоста, а сервисная половина гостя оставалась недоступной по неинженерным причинам.

Инженерный урок виртуализации плюс бинарная трансляция

Завершая разбор, полезно сформулировать урок в общем виде. Слой совместимости между ОС и чужими приложениями стоит на нескольких независимых опорах: совместимость набора команд, совместимость системного API, совместимость сервисной экосистемы, совместимость модели взаимодействия с пользователем. WSA подняла две тяжелейшие вершины сразу: виртуализация дала честное гостевое ядро и почти нативную производительность x86-кода, а бинарная трансляция закрыла разрыв ARM-x86. Это выдающееся достижение, и обе технологии по отдельности доказали жизнеспособность - Utility VM живёт в WSL2, бинарная трансляция живёт в Rosetta-подобных системах. Но удержание двух вершин одновременно не освобождает от остальных опор: без сервисного слоя приложения деградируют, без идиоматичного ввода они остаются чужими, а каждая из вершин продолжает требовать содержания - кэши транслятора, совместимость ядер, мосты интеграции, которые ломает любое обновление любой из сторон.

Из этого следует практический принцип: выбирая архитектуру совместимости, инженер должен считать не стоимость запуска, а стоимость удержания. Эмулятор проще и дешевле в поддержке, поэтому выжил как инструмент разработчика. Виртуализация оправдана там, где гость и хост принадлежат одному владельцу и эволюционируют совместно - именно поэтому WSL2 процветает, а WSA свёрнута. Бинарная трансляция оправдана там, где контролируется гостевая платформа целиком и можно гарантировать объём нетранслируемых исключений, как это делает Apple на собственном железе. WSA пыталась держать архитектуру, для честности которой требовалось контролировать слишком много чужих движущихся частей. Технически она работала замечательно. Стратегически она была обречена границами собственной же схемы - и в этом её главная ценность как предмета изучения для любого, кто проектирует следующий слой совместимости.