мэри / мост и узлы

Управление телефоном без чужих приложений

Управление телефоном живёт внутри APK: служба доступности держит свой HTTP-мост, отдаёт дерево экрана и выполняет действия по узлам. Go-сервер разговаривает с этим мостом, а не с внешними приложениями, поэтому чтение экрана, нажатия, ввод, уведомления и буфер обмена работают на одном контракте — и одинаково доступны голосом и агенту.

действий моста
14
маршрутов управления
22
чтение
read · semantic · hit_test

Мост и узлы

Что делает мост

ControlBridgeService — служба доступности с собственным HTTP-мостом. Она не рисует и не решает, а читает состояние и исполняет действие.

Дерево экрана

Окно, узлы, роли, состояния, границы и позиции. Сервер получает слепок, а не картинку, и дальше работает с ним.

  • tree

Полный набор действий

14 действий: tap и long-press, свайп, ключи, click, tap, long-click и scroll-to по узлу, ввод текста, открытие приложения, URI и браузера, Intent, буфер обмена.

  • actions

Сервис, а не хак

Скриншот берётся через AccessibilityService, уведомления читаются и открываются, список приложений и буфер обмена доступны штатно; watchdog поднимает мост, если он отвалился.

  • service

Один контракт

22 маршрутов /api/control на стороне Go — то, чем пользуются голосовые навыки, UI-фолбэк и браузерный агент. Отдельного «второго пути» для каждого сценария нет.

  • api

Мост и узлы

Как читается экран

Модель и навыки видят не координаты, а узлы: так действие остаётся понятным и проверяемым.

Поиск по признаку

Узел находится по id, тексту, описанию или классу — точным совпадением или подстрокой.

  • find

Точка и ожидание

hit_test по координатам отвечает, что находится в точке, а wait дожидается появления узла — вместо слепой паузы «подожди секунду».

  • hit_test
  • wait

Плоское и семантическое чтение

control/read отдаёт список с ролями, состояниями и позициями, control/semantic — короткое семантическое представление. Сырые координаты и служебные атрибуты остаются серверу.

  • read

Подпись и журнал

Узел можно подписать словами, а журнал действий хранит, что нажали, когда и к чему это привело — история видна и человеку, и агенту.

  • history

Мост и узлы

Как выполняется действие

Путь один: найти узел, сделать, проверить.

По узлу, а не по пикселю

Действия идут по узлу с отступом от края и гравитацией (центр, слева, справа) — попадание не зависит от плотности экрана и темы приложения.

  • tap_node

Проверка результата

После действия экран снимается заново и сравнивается фингерпринт. Если он не изменился, Мэри говорит об этом, а не делает вид, что всё сработало.

  • fingerprint

Предохранители

Открытая шторка уведомлений, отсутствие кликабельных узлов и неизвестный жест возвращаются понятной причиной, а не тихим отказом.

  • safety

Эффект на экране

В момент действия сервер отправляет кадр по SSE, и оверлей рисует тап-кольцо или свайп «пальцем» — видно, что именно произошло.

  • fx

Мост и узлы

Номера и контракт экрана

Подсказка выбора и правила поведения приходят с сервера одним пакетом.

Номера поверх узлов

Кликабельные узлы получают номера, и оверлей рисует их поверх интерфейса. Список живёт 16 секунд под свежий слепок, APK опрашивает его раз в две секунды.

  • numbers

Выбор голосом

«Нажми 3» разрешается тем же списком узлов: сервер нажимает третий и отвечает, изменился ли экран.

  • pick

Контракт поведения

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

  • behavior

Экраны YouTube

Тип страницы (каталог, главная, поиск, плеер, Shorts, комментарии) определяется по слепку. В каталоге — номера и выбор голосом, в плеере и на Shorts — тихий режим, а следующий шортс подставляется по таймеру конца ролика.

  • youtube

проверяемое

Что здесь можно перепроверить

  • Действия идут по узлам доступности, а результат каждого проверяется повторным слепком экрана.
  • Номера узлов и правила поведения считает сервер: APK исполняет контракт, а не хранит сценарии у себя.
  • Мост — часть APK: внешние приложения и root-доступ для управления телефоном не нужны.