android:sharedUserId и android.uid.system: как работает система UID в Android

Строка android:sharedUserId="android.uid.system" в манифесте приложения — это прямое требование «выполнять мой процесс с правами системного пользователя Android», и подписать такой APK обычным ключом разработчика не получится: PackageManager откажется устанавливать пакет с ошибкой несовпадения сертификатов. Этот атрибут из манифеста AndroidManifest.xml связывает приложение с механизмом идентификаторов пользователей (UID), на котором построена вся модель изоляции процессов в Android.

В этой статье разберём, что такое UID и sharedUserId, чем системный UID отличается от обычного, почему Google объявила механизм устаревшим и как безопасно проверить назначенные идентификаторы на устройстве через ADB. Материал ориентирован на разработчиков и продвинутых пользователей, которые встретили этот атрибут в чужом манифесте или системном APK.

Что такое UID в Android и зачем он нужен

Каждое установленное приложение в Android получает собственный UID — числовой идентификатор пользователя на уровне ядра Linux. Это фундамент «песочницы»: процессы одного приложения не могут читать файлы другого, потому что ядро сравнивает UID владельца файла и UID процесса, который пытается получить доступ. Пользователь в привычном смысле (аккаунт Google) к этому механизму отношения не имеет.

Диапазоны идентификаторов зарезервированы. Системные службы работают под низкими UID вроде system (1000), radio, shell, а обычные приложения получают идентификаторы из диапазона app, начинающегося с 10000. Проверить, какой UID назначен конкретному пакету, можно командой:

adb shell dumpsys package com.example.app | grep userId

Вывод покажет строку вида userId=10123 — это и есть идентификатор, под которым ядро видит процессы приложения.

Атрибут android:sharedUserId — общий UID для нескольких приложений

Атрибут android:sharedUserId в теге <manifest> позволяет двум и более приложениям работать под одним UID. Последствия этого существенны: приложения получают доступ к приватным данным друг друга, могут исполняться в одном процессе и совместно использовать ресурсы без IPC.

Пример объявления в манифесте:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.example.app"

android:sharedUserId="com.example.shared">

Чтобы механизм сработал, должны совпасть три условия одновременно. Проверьте их до попытки установки связки приложений:

  • 🔑 Одинаковая подпись — все APK с общим UID подписаны одним сертификатом;
  • 📝 Идентичное строковое значение sharedUserId во всех манифестах;
  • 🚫 Отсутствие конфликта — на устройстве не установлен пакет с тем же именем, но другой подписью;
  • 📦 Совместимость версий, если приложения уже стояли по отдельности (миграция на общий UID установленного приложения системой не поддерживается).
⚠️ Внимание: изменить или удалить sharedUserId у уже опубликованного приложения нельзя без потери данных. Пользователю придётся удалить приложение и установить его заново — система откажется обновлять пакет с изменённым идентификатором.
📊 Для чего вам понадобился sharedUserId?
Анализ чужого системного APK
Разработка связки своих приложений
Ошибка INSTALL_FAILED при установке
Изучаю Android из интереса

android.uid.system — запуск приложения с правами системы

Значение android.uid.system — частный и самый известный случай sharedUserId. Приложение с таким атрибутом просит выполняться под UID 1000 (system), что даёт доступ к защищённым API, системным разрешениям уровня signature и файлам фреймворка. Обычное стороннее приложение получить такой UID не может.

Причина проста: подпись системного ключа. Пакет с android.uid.system установится только если он подписан тем же platform key, которым подписана сама прошивка устройства. Этот ключ есть у производителя устройства (OEM) или у Google для сборок AOSP. Если вы видите ошибку вида INSTALL_FAILED_SHARED_USER_INCOMPATIBLE при установке такого APK — вероятная причина именно в несовпадении сертификатов, а не в битом файле.

Типичные обладатели системного UID — компоненты самой ОС: SystemUI, Settings, службы телефонии. Их объединение под одним UID позволяет им обмениваться данными без накладных расходов на межпроцессное взаимодействие.

Сравнение основных UID в Android

Ниже — справочная таблица по ключевым идентификаторам. Она помогает быстро понять, к какому классу относится процесс, который вы видите в ps или dumpsys.

UIDИмяКто используетУровень доступа
0rootЯдро, init, демоны с rootПолный доступ к системе
1000systemСистемные сервисы, SystemUIСистемные API, signature-разрешения
2000shellADB-сеанс разработчикаОтладочные команды, чтение логов
10000+app_XXXXXОбычные установленные приложенияИзолированная песочница

Обратите внимание: shell (UID 2000) — это не root. Через ADB можно сделать многое, например посмотреть разрешения пакета, но изменить системные разделы без разблокировки не получится.

Как проверить UID и sharedUserId приложения

Для диагностики достаточно ADB — root не требуется. Необходимо выполнить несколько безопасных команд, которые ничего не меняют в системе.

☑️ Проверка UID приложения через ADB

Выполнено: 0 / 5

Если dumpsys package показывает поле sharedUserId, значит пакет входит в группу с общим идентификатором. Рядом будет указан и фактический UID, назначенный группе. Для анализа APK без установки можно распаковать манифест через aapt:

aapt dump badging app.apk | head -5

В первых строках вывода видны имя пакета и, при наличии, значение sharedUserId. Это удобно при анализе системных приложений, извлечённых из прошивки.

Почему Google объявила sharedUserId устаревшим

Начиная с Android SDK 29 механизм помечен как deprecated. Общий UID усложняет аудит безопасности, мешает гранулярному управлению разрешениями и создаёт скрытые зависимости между приложениями. Вместо него рекомендуется использовать явные механизмы: контент-провайдеры, IPC через AIDL, общие разрешения уровня signature и android:process для управления процессами.

Типичные ошибки и ограничения

Чаще всего с sharedUserId сталкиваются в момент сбоя установки. Вот характерные сценарии:

  • INSTALL_FAILED_UPDATE_INCOMPATIBLE — попытка обновить приложение версией с другим sharedUserId или другой подписью;
  • INSTALL_FAILED_SHARED_USER_INCOMPATIBLE — конфликт с уже установленным пакетом, претендующим на тот же UID;
  • ❌ Тихий отказ при сборке системного образа — APK с android.uid.system не подписан platform key;
  • ❌ Потеря данных после удаления одного из приложений группы — файлы были общими.
⚠️ Внимание: не пытайтесь «добавить» android.uid.system в свой APK и установить его на обычный смартфон — установка будет отклонена, а на устройствах с проверкой целостности прошивки такие эксперименты могут привести к необходимости полной перепрошивки. Системный UID доступен только при сборке собственной прошивки (AOSP) или по соглашению с производителем устройства.

Если цель — просто обмен данными между двумя своими приложениями, общий UID избыточен. Используйте ContentProvider с защитой signature-разрешением: это современный, поддерживаемый и контролируемый путь.

FAQ: частые вопросы о sharedUserId и UID system

Может ли обычное приложение получить android.uid.system?

Нет. Пакет с таким sharedUserId установится только при совпадении подписи с ключом прошивки. На серийном устройстве без ключа производителя это невозможно — PackageManager отклонит установку.

Чем sharedUserId отличается от android:process?

Атрибут android:process управляет тем, в каком процессе работают компоненты одного приложения, но не снимает изоляцию между разными приложениями. sharedUserId объединяет идентификаторы разных пакетов, давая им доступ к данным друг друга на уровне ядра.

Безопасно ли удалять приложение, входящее в группу sharedUserId?

Данные приложения хранятся в каталоге, принадлежащем общему UID, поэтому удаление одного участника группы может затронуть файлы, которыми пользовались и другие приложения группы. Перед удалением системных пакетов с общим UID сверяйтесь с документацией конкретной прошивки.

Как узнать, какие приложения делят один UID?

Выполните adb shell dumpsys package | grep -A2 sharedUser и изучите секции с совпадающими идентификаторами. Альтернатива — поиск по значению userId в полном выводе dumpsys package.

sharedUserId deprecated — что использовать вместо него?

Для обмена данными — ContentProvider или явные Intent, для защиты — собственные signature-разрешения, для совместной работы компонентов — AIDL и bound-сервисы. Эти механизмы дают тот же результат без скрытой связки идентификаторов.

Подводя итог: атрибут android:sharedUserId и значение android.uid.system — это инструменты эпохи раннего Android, которые до сих пор встречаются в системных APK и старых проектах. Понимание того, как UID привязывается к подписи и как проверить назначенные идентификаторы через ADB, избавляет от часов отладки загадочных ошибок установки и помогает правильно оценить чужой манифест при анализе прошивки.