«Робота за призначенням»

Відомо, що функція доступності Android викликає затримку інтерфейсу користувача. Це помилка чи функція? Чому це відбувається? Ми в XDA досліджуємо першопричину.

Краса Android полягає в багатьох різних способах взаємодії програм сторонніх розробників із системою. Програми для керування паролями, наприклад LastPass надають можливість автоматично передавати відповідні дані імені користувача/паролю майже на будь-який екран входу. Текстовий помічник дозволяє значно скоротити час, який ви відправляєте друзям, завдяки створенню макросів для розширення тексту. Власний буфер обміну зменшує клопоти, пов’язані з частим перемиканням між програмами для копіювання великої кількості тексту, дозволяючи двічі торкнутися будь-якого поля введення, щоб відкрити буфер обміну. Хто може забути Озеленити, мабуть, програма №1, яку найчастіше рекомендують ентузіасти, яка тримає під контролем фальшиві програми у фоновому режимі та, таким чином, може подовжити час роботи акумулятора? Нарешті, хоч і менш знайомий більшості користувачів, є

Автовведення - плагін Tasker, призначений для автоматизації натискань на екран, введення тексту, жестів пальця та багато іншого. Усі ці програми мають дуже різні варіанти використання, але кожна з них покладається на дуже неправильно зрозумілу частину основних функцій Android: Доступність.

Пересічному користувачеві Android може здатися дивним, що багато з цих дивовижних функцій, які використовуються вашою улюбленою програмою, контролюються налаштуванням під доступність підменю. Створення програми доступний зазвичай має означати, що програмою для Android може користуватися людина з обмежені можливості. То чому ж у світі LastPass, Native Clipboard, Text Aide, Greenify або AutoInput мають доступність обслуговування? Крім того, чому здається, що ввімкнення служби доступності викликають таку велику затримку інтерфейсу користувача? Здається, неважливо, на якій версії Android ви користуєтесь Android 5.0 Lollipop або Android 7.0 Nougat - оскільки затримка, спричинена певними службами доступності, може вплинути на ваш досвід. Просте вирішення цієї проблеми полягає в тому, щоб просто вимкнути служби доступності, які ви могли ввімкнути, але при цьому ми втрачаємо багато корисних функцій. Іншим рішенням є звернення до Google із проханням «виправити» відставання доступності Android, але Google стверджує, що доступність Android працює за призначенням. Ми поспілкувалися з кількома розробниками, які добре знайомі зі службами доступності, і дослідили, як працюють ці функції, і ми тут, щоб перевірити це твердження: затримка доступності Android – це помилка чи це функція?


Розуміння спеціальних можливостей Android

Як ви можете собі уявити з назви, Accessibility здебільшого призначений для розробників, щоб забезпечити додаткові функції для будь-яких користувачів з обмеженими можливостями. Дійсно, короткий погляд на сторінки офіційної документації для спеціальних можливостей показує, що Google має досить вузьке уявлення про те, які види послуг мають надавати служби доступності.

Багато користувачів Android мають різні здібності, які вимагають від них взаємодії зі своїми пристроями Android різними способами. До них належать користувачі, які мають зорові, фізичні або вікові обмеження, які не дозволяють їм повноцінно бачити або використання сенсорного екрану, а також користувачів із втратою слуху, які можуть не сприймати звукову інформацію та сповіщення.

Android надає спеціальні можливості та служби, щоб допомогти цим користувачам краще орієнтуватися на своїх пристроях легко, включаючи перетворення тексту в мовлення, тактильний відгук, навігацію жестами, трекбол і панель керування навігація.

Google Відповісти, який попередньо встановлено на кожному телефоні Android, є чудовим прикладом того, якою має бути «типова» служба доступності. Голосовий доступ робить доступність на крок далі та дозволяє практично повністю контролювати ваш телефон, використовуючи лише ваш голос. Але той факт, що Google планував використовувати служби доступності таким чином, не заважає розробникам від реалізації їх будь-яким способом вони хочуть - і це саме те, що розробники мають зроблено. Саме завдяки тому, як працює доступність, ця функція створена неймовірно корисний для користувачів з обмеженими можливостями або без них.

Щоб трохи спростити речі, ось короткий виклад того, як працює доступність Android. Розробник створює Служба доступності що підписується на різні Події доступності які надсилаються системою до Сервісу залежно від відповідності певним критеріям. Коли всі служби вимкнено в розділі «Налаштування» --> «Доступність», Android не збирає та не надсилає жодних подій доступності. Але коли користувач починає вмикати Accessibility Services, Android починає моніторинг і збір лише ті Події доступності, які запитує Служба доступності. Наприклад, служба доступності, яка підписується на подію доступності TYPE_WINDOW_CONTENT_CHANGED буде повідомлено системою кожен раз що відбувається зміна в поточному вікні. Ще одна подія доступності викликана TYPE_VIEW_CLICKED випалює кожен раз користувач натискає якусь кнопку.

Демонстрація доступності Android. У цьому відео я ввімкнув програму Tasker стежити за зміни в заголовку вікна. Для цього потрібно ввімкнути службу доступності Tasker. Ви можете відтворити це, створивши новий профіль у Tasker із контекстом «Подія», встановленим на «Набір змінних» і вибравши %WIN як змінну для моніторингу. Загалом це відео тривалістю приблизно 1 хвилину 107 змін у поточному вікні.

Такі події доступності відбуваються з великою частотою під час звичайної взаємодії користувача. Тож уявіть, що відбувається, коли користувач вмикає кілька служб доступності які вимагають запуску високочастотних подій доступності. Це вірно - відставання. Щоб пом’якшити це, розробники можуть більш вузько визначати, які види подій доступності вони мають Сервіс має реагувати на те й у якому контексті, наприклад можливість обмежити Сервіс лише реагуванням коли в певні програми або обмежити період голосування між подіями. Але, крім цього, обсяг накладних витрат, створених службою доступності, здебільшого залежить від які види заходів доступності він підписується. По суті, не кожна служба доступності спричиняє затримку. Одна служба доступності, яка потребує високочастотної події, може спричинити затримку, особливо якщо зазначена Послуга поєднується з іншою Послугою, для якої потрібна інша високочастотна Подія моніторинг.


Глибоке занурення в доступність із розбиранням APK

Як ви могли зрозуміти з опублікованого вище відео, служба доступності, яка відстежує зміни у вмісті вікна, може призводять до досить помітних змін у продуктивності інтерфейсу користувача через величезну кількість записаних подій доступності, створених система. Однак досить важко точно визначити, скільки накладних витрат спричиняє певна служба доступності. Моніторинг LogCat зазвичай ні до чого не приведе, оскільки події доступності друкуються в LogCat, лише якщо розробник служби доступності вирішить це зробити. На щастя, батько всіх служб доступності Android, Автовведення, робить саме це. А результат LogCat такий безладний, як ви могли собі уявити.

AutoInput не приховує від нас правду. Накладні витрати, спричинені програмою, можуть бути досить величезними залежно від того, які події ви відстежуєте. Але ці накладні витрати необхідні для роботи програми. Щоб AutoInput перехоплював кожне натискання клавіші, кожен жест на екрані, кожне оновлення інтерфейсу користувача та кожне натискання кнопки, потреби для моніторингу відповідних Подій доступності. Без цих подій AutoInput не може підключитися до системи та забезпечити майже необмежену автоматизацію інтерфейсу користувача, яку він зараз дозволяє. Таким чином, усі функції AutoInput мають ідеальний сенс у контексті доступності. Але для інших програм нам потрібно подивитися трохи глибше, щоб зрозуміти, як обробляються їхні служби доступності.

Служба доступності атрибути визначені в ан Файл ресурсів XML в APK. Тому ми можемо виконати an Розбір APK у програмі зі Службою доступності, щоб визначити атрибути Служби. Кожна програма функціонує по-різному, тому я спробую пояснити, як атрибути її служби пов’язані з конкретною функцією, яку вона виконує.

Власний буфер обміну

Нативний буфер обміну – це мій вибір, коли справа стосується менеджерів буфера обміну. Якщо ви шукаєте менеджер буфера обміну, який можна настроювати, Native Clipboard — чудова програма. Він навіть має компонент Xposed Module, який дозволяє довго натискати кнопку «Вставити», щоб відкрити диспетчер буфера обміну! На жаль, якщо у вас немає доступу до Xposed Framework (наприклад, у кожного користувача Nougat), вам доведеться погодитись для ввімкнення служби доступності, яка дозволить вам двічі торкнутися будь-якого введення тексту, щоб відкрити буфер обміну менеджер. Ось що це означає.


"@string/access_decs"
android: accessibilityEventTypes="typeViewClicked|typeViewFocused|typeViewLongClicked|typeWindowStateChanged"
android: accessibilityFeedbackType="feedbackGeneric"
android: notificationTimeout="100"
android: accessibilityFlags="flagReportViewIds|flagRetrieveInteractiveWindows"
android: canRetrieveWindowContent="true"
xmlns: andro />

Служба спеціальних можливостей Native Clipboard запитує запуск події доступності кожного разу, коли клацають подання, довго клацають, виділяють фокус або якщо відбувається зміна стану вікна. Не маючи доступу до вихідного коду, я не можу точно сказати, як працює Native Clipboard, але ймовірно, що Native Clipboard очікує, поки стан вікна вкаже, що програмна клавіатура наразі відкрита, а потім відстежує натискання на введення поле. Додаток має період опитування 100 мс, тож цього достатньо швидко, щоб практично негайно реагувати на зміни у видимості програмної клавіатури, а також на подвійні натискання. Це може призвести до певних витрат інтерфейсу користувача, коли користувач використовує програмну клавіатуру для введення будь-якого тексту, що потенційно може призвести до затримки.

Озеленити

На черзі — улюблений усіма режим економії заряду Greenify. Greenify використовує Accessibility Events для забезпечення своїх некореневих функцій.


"@string/accessibility_service_description"
android: settingsActivity="com.oasisfeng.greenify.accessibility.AccessibilitySettings"
android: accessibilityEventTypes="typeAnnouncement|typeNotificationStateChanged|typeWindowStateChanged"
android: accessibilityFeedbackType="feedbackGeneric" android: notificationTimeout="0"
android: accessibilityFlags="flagReportViewIds"
android: canRetrieveWindowContent="true"
xmlns: andro />

Він використовує зміни у стані вікна, щоб визначити, коли екран телефону вимкнуто, і вимагає, щоб ви відклали активацію екрана блокування, змінивши параметр у налаштуваннях безпеки. Greenify також отримуватиме події типу "Оголошення" або "Зміна стану сповіщень", останній непотрібний на пристроях Android 5.0+ завдяки функції доступу до сповіщень. Однак він все одно отримуватиме ці події незалежно від цього факту. Greenify сам по собі не повинен викликати великих витрат, але така можливість залишається.

Nova Launcher

Ймовірно, найпопулярніша програма запуску сторонніх розробників на ринку, Nova Launcher є чудовим прикладом програми, яка використовує службу доступності з мінімальними або повними витратами. Єдиною причиною існування Сервісу є допомога певним пристроям у виконанні жестів.


"@string/accessibility_service_description"
android: accessibilityEventTypes=""
android: packageNames="com.teslacoilsw.launcher"
android: accessibilityFeedbackType=""
android: notificationTimeout="10000"
android: canRetrieveWindowContent="false"
xmlns: andro />

Як бачите, у файлі XML не визначено подію доступності. Все, що згадується, це назва пакета - Nova Launcher. Те, що відбувається тут, є обхідним шляхом для певних пристроїв, на яких жести Nova Launcher не працюють. Ця служба надасть Nova Launcher усі події доступності, з яких запускаються лише в Nova Launcher. Це звучить дивно, але, очевидно, це спосіб виправити жести на головному екрані Nova, якщо ваш пристрій не працює з ними. Оскільки це запитує події лише від самої Nova, Служба створює дуже невеликі витрати.

LastPass

Нарешті, мабуть, найсумніша служба доступності, яка викликає затримку (ймовірно, через її величезну популярність) - LastPass. Проблема затримки в LastPass є так помітно що на підприємстві є посадова особа Сторінка поширених запитань із описом проблеми. Як зазначено у поширених запитаннях, ви нічого не можете зробити із затримкою, окрім як вимкнути службу. Чому служба LastPass виглядає такою кричущою, коли йдеться про затримку? Давайте розглянемо атрибути Сервісу.


"@string/accessibility_service_description"
android: accessibilityEventTypes="typeViewFocused|typeWindowContentChanged"
android: accessibilityFeedbackType="feedbackGeneric"
android: notificationTimeout="200"
android: accessibilityFlags="flagReportViewIds"
android: canRetrieveWindowContent="true"
android: canRequestEnhancedWebAccessibility="true"
xmlns: andro />

Правда в тому, що в службі LastPass немає нічого незвичайного. Він запитує лише два типи подій для моніторингу - TYPE_VIEW_FOCUSED і TYPE_WINDOW_CONTENT_CHANGED. Це робиться тому, що йому потрібно знати, коли вміст програми/веб-сторінки змінюється/потрапляє у фокус, а потім отримує поточний вміст вікна, щоб знайти поля для введення пароля. Але оскільки служба постійно робить це на двох подіях доступності, які надзвичайно часто запускаються, це призводить до затримки. Це сумна правда.


Життя з відставанням

Коли ми вперше прочитали, що Google закриває звіти про помилки щодо затримки доступності, тому що ця функція «працювала належним чином», ми були так само здивовані та засмучені, як і багато хто з вас. Але замість того, щоб прийняти пояснення за чисту монету, ми вирішили розібратися в цьому питанні самі, щоб визначити правду. Тож коли працівник Google на сторінці звіту про помилку сказав таке:

Привіт, ця проблема є постійною у версіях Android. Також завжди буде додаткова затримка, коли ввімкнено службу доступності. Це тому, що пристрій, окрім стандартного інтерфейсу користувача, надає багато інформації службам доступності, щоб вони могли надати цим користувачам альтернативний досвід користувача.

Ми прийшли до розуміння чому це намічена поведінка. Програми, які використовують Служби доступності у спосіб, не передбачений Google, завжди спричинятимуть певні витрати на продуктивність; ця вартість просто необхідна для надання Сервісам великої кількості інформації, яку доступність Android запускає у фоновому режимі. Відставання Android із службами доступності є не помилка, а функція. Функція, з якою нам доведеться жити, якщо не буде перероблено всю систему, і я не можу уявити, як це можна зробити, щоб розмістити стільки різних наборів функцій із багатьох різних програм.

Принаймні, розробники LastPass не погодилися б на це. Їхні розробники співпрацювали з розробниками Chromium оптимізувати підтримку доступності, можливо, увімкнувши підтримку LastPass через використання API замість увімкнення служби доступності. Однією з можливостей є оптимізація накладних витрат, пов’язаних зі службами доступності, але, як прямо зазначили багато розробників на форумах Chromium, це просто пов’язка, яка не допоможе вирішити той факт, що ненавмисне використання служб доступності може призвести до відставання.


Особлива подяка розробнику AutoInput, joaomgcd, за відповідь на багато моїх запитань щодо доступності!