Т-Банк — банк, который слушает твой акселерометр 416 раз в секунду1
Все, чт я опишу далее - касается только телефонов на базе android. Как оно там реализовано у них на яблоках - я понятия не имею.
TL;DR.
Приложение Т-Банка версии 8.1.0 (хотя, подозреваю, проблема была и сильно раньше) на моём Galaxy S23 Ultra сидело в фоне, никем не открытое, и читало акселерометр с частотой ~416 Гц и датчик гравитации с частотой 200 Гц. Круглосуточно. При этом данные оно даже не забирало — очередь событий стояла забитой под потолок. Результат: ~20% CPU в фоне, сенсорный сервис в топе потребления, телефон тормозит, батарея тает. Виноват не только банк, но и связка «T-Pay + NFC», которая не даёт Android усыпить процесс.
Преамбула
Стал я в последнее время все больше замечать, что телефон ведет себя не очень адекватно. Мелкие тормоза там и тут - открыть гуглоленту, потянуть за шторку, вызвать клавиатуру... Не сказать, что прям тормозит-тормозит. Так, слегка подтупливает. Однако, подтупливание я еще могу простить своему древнему Honor 20, который висит подключенный к колонкам в качестве медиаплеера на кухне. Но никак не Galaxy S23 Ultra. Рано ему еще. Я, конечно, бывает, забываю перезагружать телефон время от времени (как, впрочем, и в этот раз - подключившись по ADB внезапно обнаружил почти месяц аптайма. Упс.), однако, перезагрузка особо не спасала, лишь немного облегчая работу.
Фабула
Решил, значится, разбираться, подцепился по ADB:
`dumpsys cpuinfo` за пятиминутное окно, пока телефон лежал на столе с выключенным экраном:
22% system_server
13% android.hardware.sensors-service.multihal ← сенсорный HAL, 20 часов CPU за 26 дней
11% com.idamob.tinkoff.android ← Т-Банк, 5.1% user + 6.2% kernel
Второе место - сенсоры, третье - Тинькофф. Причём с очень странным профилем: больше половины времени — в **ядре**, плюс 11 000 major page faults за пять минут. Так выглядит процесс, который непрерывно получает данные через системные вызовы, а не «просто висит».
Дальше — `dumpsys sensorservice`, список активных подключений к датчикам:
Connection Number: 6
llb.a | uid 10404 | cache size 8051 | max cache size 10000
gravity Non-wakeup 0x0000005b | status: active
23:34:55 + 0x0000005b pid=31855 uid=10404 samplingPeriod=5000us (gravity, llb.a)
23:34:55 + 0x0000000b pid=31855 uid=10404 samplingPeriod=2404us (LSM6DSO Accelerometer, llb.a)
Расшифровка:
uid 10404 — это Т-Банк (`pm list packages -U | grep tinkoff`).
llb.a — имя класса после обфускации. Нам сейчас не важно.
samplingPeriod=2404us — период опроса акселерометра 2,4 миллисекунды. Это ~416 раз в секунду. Для сравнения: шагомер довольствуется 5 Гц, автоповорот экрана — 50 Гц, игры с управлением наклоном — 100 Гц. Тут — почти предел железа.
samplingPeriod=5000us — датчик гравитации, 200 Гц.
cache size 8051 / 10000 — в буфере лежит восемь тысяч непрочитанных событий. То есть приложение подписалось на поток данных с такой скоростью и… не читает его. Буфер просто упёрся в потолок и молча переполняется.
- Подписка появляется через секунды после старта процесса, без открытия приложения. Убиваем процесс — он перезапускается с новым pid и снова подписывается на те же датчики за ту же секунду.
Итого: банк в фоне 24/7 гонит два потока данных с датчиков движения на частоте почти в полкилогерца и даже не удосуживается их забирать.Сенсорный HAL при этом честно отрабатывает каждый тик — вот вам и 13% CPU у «сенсоров», и ядерное время у самого банка.
Почему Android это вообще позволяет
Тут самое интересное. Android начиная с 9-й версии запрещает фоновым приложениям читать датчики движения в непрерывном режиме. Подписался — данные перестанут приходить, как только приложение уйдёт в фон. Так почему Т-Банк не попал под это ограничение?
Потому что он никогда не был «в фоне» с точки зрения системы:
$ dumpsys activity services com.idamob.tinkoff.android
* ServiceRecord{... com.idamob.tinkoff.android
ru.nspk.mir.hce.sdk.internal.service.MirHcePaymentService}
Bindings:
* Client AppBindRecord{... ProcessRecord{... com.android.nfc/1027}}
$ dumpsys activity processes | grep tinkoff
Proc #76: vis ... com.idamob.tinkoff.android (service)
NFC-сервис. Я пользуюсь T-pay в качестве основного платежного сервиса NFC. (Поправка - теперь уже пользовался).
Системный сервис NFC держит этот сервис подключенным постоянно, а подключенный жк системному процессу сервис поднимает приоритет всего приложения до visible — то самое «vis» в выводе. Для Android это уровень «пользователь почти видит это приложение», и никакие фоновые ограничения — ни на датчики, ни на CPU, ни замораживание — к нему не применяются.
Результат восхитительный - приложение в активном режиме насилует датчики телефона, а NFC-сервис не дает приложению уснуть.
Зачем банку датчики 400 раз в секунду
Я не видел исходников, поэтому дальше — обоснованные предположения.
Зачем банку датчики вообще. Это почти наверняка поведенческая биометрия в составе антифрод-SDK. Идея красивая: у каждого человека уникальный «почерк» того, как он держит телефон, как дрожит рука, под каким углом лежит экран, как он тыкает в кнопки. По акселерометру и гравитации можно с приличной точностью отличить владельца от мошенника, который украл телефон вместе с разблокированной сессией. Ещё это ловит эмуляторы (у них датчики либо мёртвые, либо идеально ровные), автокликеры и удалённое управление (телефон лежит неподвижно, а по экрану кто-то бодро жмёт). Для банка это реальная защита от реальных схем, и я не против того, чтобы во время работы с приложением оно оценивало риск.
Зачем 416 Гц. Вот тут защитить их сложнее. Для поведенческой биометрии хватает 50–100 Гц: тремор руки — это единицы герц, походка — тоже. Есть три правдоподобных объяснения:
1. Лень.*В Android есть константа `SENSOR_DELAY_FASTEST` — «давай максимально быстро». Разработчик SDK написал её, потому что «данных мало не бывает», и пошёл дальше. На тестовом Pixel в лаборатории это стоит ничего, на боевом Samsung с 400-герцовым LSM6DSO — 10% процессора.
2. Наивная точность. Чем чаще опрос, тем «богаче» биометрический профиль. Возможно, модель у них обучена на сырых данных с максимальной частотой, и понизить её без переобучения нельзя.
3. Баг. Подписка вешается при инициализации приложения (в `ContentProvider` или `Application.onCreate`), а снять её никто не забыл потому, что предполагалось, что Android сам всё выключит, когда приложение уйдёт в фон. Что он и сделал бы — если бы не T-Pay. Восемь тысяч непрочитанных событий в буфере намекают именно на это: никто эти данные не обрабатывает. Поток идёт в никуда.
Моя ставка — комбинация первого и третьего. Антифрод-SDK написан «на максимум», а связка с NFC превратила «работает, пока открыт банк» в «работает всегда». Злого умысла я тут не вижу: следить за пользователем 416 раз в секунду и класть данные в переполненный буфер — это не слежка, это халтура.
Что НЕ помогает
- Ограничение работы в фоне (Настройки → Приложения → Т-Банк → Батарея → Ограничено). Ноль эффекта: процесс держит NFC, а не сам банк, и ограничение на него не распространяется. Проверено через `cmd appops set ... RUN_ANY_IN_BACKGROUND ignore` — процесс как был, так и остался, датчики как читались, так и читались.
- Force stop. Через несколько секунд NFC-сервис поднимает процесс обратно. И он снова подписывается.
- Отключение компонента через ADB. `pm disable-user com.idamob.tinkoff.android/...MirHcePaymentService` → `SecurityException: Shell cannot change component state`. Без рута системные шелл-команды не трогают компоненты сторонних приложений.
Что помогает
Смена приложения для бесконтактной оплаты. Тащем-та, единственный вариант, если вы не хотите сносить приложение банка.
Эффект мгновенный:
$ pidof com.idamob.tinkoff.android
(пусто — процесс не запущен)
$ dumpsys sensorservice | grep -E 'Accelerometer|gravity'
(пусто — ни одного активного подписчика)
Т-Банк стал обычным фоновым приложением: Android его замораживает, датчики ему не отдаёт, пуши приходят как раньше — приложение просыпается на секунду, показывает уведомление и засыпает.
Как проверить у себя
Нужен ADB (Android Platform Tools) и включённая отладка по USB или Wi-Fi.
```bash
# 1. Кто ест процессор в фоне (положите телефон и подождите пару минут)
adb shell dumpsys cpuinfo | head -15
# 2. UID вашего банка
adb shell pm list packages -U | grep tinkoff
# 3. Кто подписан на датчики и с какой частотой (подставьте свой uid)
adb shell dumpsys sensorservice | grep -B3 -A1 "uid 10404"
adb shell dumpsys sensorservice | grep "samplingPeriod" | grep 10404
# 4. Кто держит процесс банка живым
adb shell dumpsys activity services com.idamob.tinkoff.android | grep -E "ServiceRecord|Client"
adb shell dumpsys activity processes | grep tinkoff
# 5. Кто у вас платёжное приложение по умолчанию
adb shell settings get secure nfc_payment_default_component
```
Если в пункте 3 видите `samplingPeriod` в районе 2400–5000 микросекунд от процесса банка, который вы не открывали, — поздравляю, у вас тот же зверь. Если в пункте 4 клиентом сервиса указан `com.android.nfc` — вы знаете, что делать.
Оговорки
- Один телефон, одна версия приложения, один вечер с ADB. Это не исследование, это отчёт о находке.
- Не исключаю, что на других устройствах датчик отдаёт максимум 100–200 Гц, и там всё выглядит скромнее. LSM6DSO в Samsung умеет 416 Гц — вот и получил на полную.


