- Русские Блоги
- Об использовании android: sharedUserId = «android.uid.system»
- Что такое UID
- Установите UID вашего собственного приложения на UID системного процесса
- Объявить UID
- Фирменная упаковка
- Уже есть apk
- Восстановить подпись
- Используйте файл mk для компиляции в исходной среде
- Как работает SystemUI в Android
- Данное приложение выполняет весьма важные функции:
- Запуск SystemUI
- Регулирование громкости
- RingtonePlayer
- PowerUI
- Задачи
- Главные функции:
- Экран блокировки
- Панель уведомлений
Русские Блоги
Об использовании android: sharedUserId = «android.uid.system»
Иногда нам нужно использовать некоторые системные разрешения в наших приложениях, такие как разрешения USB. Если процесс нашего собственного приложения и системный процесс имеют одинаковый UID, у нас будет это разрешение по умолчанию, и его не нужно предоставлять пользователю. Во многих случаях Так будет намного удобнее. Это разрешение используется в большинстве проектов, над которыми я недавно работал. Измените системное время, вызовите скрытый метод, выключите и перезапустите систему, установите, обновите и удалите приложения в автоматическом режиме и т. Д. Вначале добавьте разрешение напрямую и запустите его. Если сообщается об ошибке, независимо от симулятора или реальной машины, вы всегда будете получать сообщение «Невозможно открыть драйвер сигнализации: разрешение отклонено» в logcat. Для использования этой функции требуется разрешение root или она запускается в системном процессе.
После долгого поиска в Интернете я обнаружил, что есть два способа решить эту проблему:
Один из них — скомпилировать с помощью make в среде исходного кода системы Android:
1. Добавьте атрибут android: sharedUserId = «android.uid.system» в узел манифеста в AndroidManifest.xml приложения. .
2. Измените файл Android.mk и добавьте строку LOCAL_CERTIFICATE: = platform.
3. Используйте команду mm для компиляции, и сгенерированный apk будет иметь право изменять системное время.
Этот метод не может быть скомпилирован с .mk, поэтому я должен обратиться ко второму методу:
1. Добавьте атрибут android: sharedUserId = «android.uid.system». ,
2. Используйте eclipse для компиляции неподписанного файла apk, но этот файл apk использовать нельзя.
3. Используйте ключ платформы целевой системы, чтобы повторно подписать файл apk.
Этот шаг более сложен, сначала найдите файл ключа, расположение в моем каталоге исходного кода Android — «build / target / product / security»,
Следующие два файла — это platform.pk8 и platform.x509.pem. Затем используйте инструмент Signapk, предоставляемый Android, чтобы подписать,
Исходный код signapk находится в папке «build / tools / signapk», используется «signapk platform.x509.pem platform.pk8 input.apk output.apk»,
В имени файла лучше всего использовать абсолютный путь, чтобы предотвратить его обнаружение, или вы можете изменить исходный код и использовать его напрямую. Таким образом, финальный apk такой же, как и первый метод.
Наконец, чтобы объяснить принцип, сначала добавьте атрибут android: sharedUserId = «android.uid.system».
С помощью общего идентификатора пользователя можно настроить несколько APK-файлов с одним и тем же идентификатором пользователя для работы в одном процессе.
Затем сопоставьте UID программы с android.uid.system, то есть позвольте программе работать в системном процессе, чтобы у вас было право изменять системное время.
Недостаточно просто добавить UID. Если APK-файл установлен в это время, он не будет установлен, а подпись не будет совпадать.
Причина в том, что программа хочет запускаться в системном процессе, но также имеет ключ платформы целевой системы, которым являются два файла platform.pk8 и platform.x509.pem, упомянутые во втором методе выше.
После подписания этими двумя ключами apk фактически может быть помещен в системный процесс. Добавление LOCAL_CERTIFICATE: = platform к первому методу фактически использует эти два ключа для подписи.
Также существует проблема, то есть программа, сгенерированная таким образом, может использоваться только в исходной системе Android или системе, скомпилированной вами, потому что такая система может получить два файла platform.pk8 и platform.x509.pem.
Если Android, сделанный другой компанией, даже не может быть установлен. Попробуйте подписать ключ в исходном Android, программа работает на эмуляторе ОК, но при установке на G3 сразу же выдается запрос «Пакет . не имеет подписей, соответствующих подписям общего пользователя android.uid.system». Защитите безопасность системы.
Наконец, атрибут android: sharedUserId может не только помещать apk в системный процесс, но также настраивать несколько APK для работы в одном процессе.
Обмен данными должен быть полезным.
Что такое UID
Как мы все знаем, Pid — это идентификатор процесса, Uid — это идентификатор пользователя, но Android — это не то же самое, что компьютер. У каждого пользователя компьютера есть Uid, который запускает программу, Uid этой программы — это этот пользователь, и каждая программа в Android Существует Uid. По умолчанию Android назначает Uid с разным общим уровнем для каждой программы. Если вы звоните друг другу, только Uid может быть одинаковым. Это обеспечивает определенную степень безопасности общих данных. Данные не могут быть получены произвольно между программами.
Установите UID вашего собственного приложения на UID системного процесса
Существует три типа UID системного процесса:
- android:sharedUserId=»android.uid.system»
- android:sharedUserId=»android.uid.shared»
- android:sharedUserId=»android.media»
Давайте поэкспериментируем с первым. Две другие реализации будут такими же.
Объявить UID
Во-первых, нам нужно объявить UID приложения в манифесте:
Фирменная упаковка
Предварительным условием для упаковки подписи является наличие файла подписи системы, который обычно находится в каталоге build / target / product / security исходного кода, а пользовательские системы некоторых производителей размещаются в других каталогах. Например, Nanopc3, который я использую, находится в следующем каталоге, который может быть глобальным Найдите его. Сначала я также использовал каталог сборки, но его не удалось установить после упаковки. Позже я обнаружил, что в каталоге vendor также был / (ㄒ o ㄒ) /
загрузка… повторно загрузитьОтмена
загрузка… повторно загрузитьОтмена
Среди них android: sharedUserId = «android.uid.system» соответствует двум файлам platform.pk8 и platform.x509.pem.
Вот три распространенных способа импорта системных подписей:
- Повторно подписать сгенерированный apk
- Повторно подписать собственный файл подписи приложения
- Скомпилировать из mk файла
Уже есть apk
Созданный файл apk можно повторно подписать с помощью следующей команды через файл signapk.jar в каталоге исходного кода / out / host / linux-x86 / framework.
java -jar signapk.jar platform.x509.pem platform.pk8 my.apk new.apk
Обратите внимание, что четыре файла signapk.jar, platform.x509.pem, platform.pk8 и my.apk должны находиться по одному и тому же пути при использовании этой инструкции, в противном случае вам нужно изменить путь самостоятельно.
Восстановить подпись
После создания собственного файла ключа используйте инструмент keytool-importkeypair для повторного создания подписи с помощью следующей команды:
keytool-importkeypair -k demo.jks -p 123456 -pk8 platform.pk8 -cert platform.x509.pem -alias demo
- demo.jks: файл подписи
- 123456: пароль файла подписи
- platform.pk8, platform.x509.pem: файл подписи системы
- демо: псевдоним файла подписи
Инструмент keytool-importkeypair можно загрузить сСкачать здесь。
Используйте файл mk для компиляции в исходной среде
Я не тестировал этот метод, потому что плохо разбираюсь в файлах mk. В обычных условиях он не будет использоваться. В конце концов, он в основном разработан с использованием инструментов ide. Достаточно двух вышеуказанных методов. При необходимости добавим позже.
Источник
Как работает SystemUI в Android
В этой статье я разберу архитектуру и принцип работы основного приложения Android — SystemUI. Меня заинтересовала эта тема, потому что мне интересно, как устроена система, которой пользуется такое огромное количество пользователей и для которой ежедневно выкатываются тысячи приложений в Google Play или просто на просторы интернета. Помимо этого меня интересует вопрос информационной безопасности Android и создаваемых под него приложений.
В системе Android, SystemUI — это приложение, путь к исходному коду которого находится в platform_frameworks_base/packages/SystemUI/, на девайсе оно находится в system/priv-app/-SystemUI.
priv-app — это каталог, где хранятся привилегированные приложения. К слову, по пути system/app лежат предустановленные приложения, а обычные приложения, которые мы устанавливаем на свой девайс самостоятельно, хранятся в data/app.
Тут сразу возникает вопрос: почему нельзя засунуть все предустановленные и привилегированные приложения в один каталог, зачем нужно это разделение?
Дело в том, что некоторые приложения более системные, чем другие:) И это разделение необходимо для того чтобы уменьшить покрытие эксплойтами системных приложений, для получения доступа к защищенным операциям. Можно создавать приложение, которое будет иметь специальный ApplicationInfo.FLAG_SYSTEM и в системе получит больше прав, однако apk файл с таким разрешением будет помещен в раздел system.
Итак, SystemUI — это apk-файл, который по сути своей обычное приложение. Однако, если посмотреть на сложное устройство SystemUI, перестает казаться, что это всего лишь простое приложение, верно?
Данное приложение выполняет весьма важные функции:
Запуск SystemUI
Как я и говорила выше, SystemUI не похож на обычное приложение, так что его запуск не сопровождается запуском активности, как это происходит у большинства приложений. SystemUI — это глобальный пользовательский интерфейс, который запускается во время процесса загрузки системы и не может быть завершен.
Если мы залезем в SystemServer, который является одним из двух столпов в мире Android (второй — Zygote, но об этом я расскажу как-нибудь в другой раз), то мы можешь найти место, где стартует SystemUI при загрузке системы.
Тут мы видим как запускается сервис SystemUI с помощью непубличного API startServiceAsUser. Если бы вы захотели использовать это, то вам пришлось бы обратиться к рефлексии. Но если вы решите использовать reflection API в Android — подумайте несколько раз, стоит ли это того. Подумайте раз сто:)
Итак, тут создается отдельный процесс для приложения и по факту каждый раздел SystemUI является отдельным сервисом или независимым модулем.
Метод start() вызывается для запуска каждой службы, которые перечислены ниже.
Регулирование громкости
Мы регулярно пользуемся кнопками громкости на своих устройствах, но не задумываемся какие процессы должны произойти в системе для того чтобы мы могли прибавить или убавить звук. Операция кажется довольно простой на словах, но если заглянуть в VolumeUI, который находится в подпапке SystenUI/volume, в разных режимах интерфейс имеет свою вариацию.
Я уже говорила о том, что сервисы SystemUI запускаются методом start(). Если мы посмотрим на класс VolumeUI, то он тоже наследуется от SystemUI.
Тут мы видим что с помощью mEnabled мы определяем, следует ли нам показывать панель с настройкой звука. И судя по VolumeDialogComponent, VolumeUI отображает звуковую панель в виде диалога. Но все действия относительно нажатия на клавиши громкости обрабатываются в PhoneWindow.
Насколько мы видим, KEYCODE_VOLUME_UP (+) не обрабатывается и перейдет в обработку KEYCODE_VOLUME_DOWN (-). И в обоих событиях, как в onKeyDown, так и в onKeyUp вызывается метод dispatchVolumeButtonEventAsSystemService.
Итак, тут у нас вызывается метод adjustVolume, для того чтобы мы могли проверить наш direction, которому будет присвоен параметр события.
В итоге когда мы доберемся до AudioService, где будет вызван sendVolumeUpdate, где помимо вызова метода postVolumeChanged, будет установлен интерфейс HDMI.
RingtonePlayer
RingtonePlayer в Android выполняет роль проигрывателя. Он так же наследуется от SystemUI и в методе start() мы видим:
Здесь у нас устанавливается mCallback, который по сути является экземпляром IRingtonePlayer.
В итоге можно управлять RingtonePlayerService с помощью Binder для воспроизведения звуковых файлов.
PowerUI
PowerUI отвечает за управление питанием и уведомлениями. Аналогично наследуется от SystemUI и имеет метод start().
Как мы видим из приведенного выше кода, происодит подписка на изменения Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, а после — вызов mReceiver.init().
Тут регистрируется широковещательный приемник, с помощью которого происходит отслеживание изменений.
Задачи
Recents — это основная и часто используемая функция в мобильных устройствах на базе Android.
Главные функции:
- Отображение всех задач
- Переключение между задачами
- Удаление задач
Помимо этого Recents так же наследуется от SystemUI. В RecentsActivity происходит создание и обновление последних задач, чтобы мы могли увидеть их на нашем экране.
А в с помощью RecentTaskInfo мы можем получить информацию о конкретной задаче.
Вообще, запущенные задачи можно вынести в отдельную тему. Я изучила ее со всех сторон, так как хотела размывать экран приложения перед переходом приложения в background, чтобы в RecentsTask отображалась нечитаемая версия снапшота. Однако, проблема заключается в том, что снапшот приложения берется раньше, чем вызывается onPause(). Эту проблему можно решить несколькими способами. Либо выставлять флаг, чтобы система просто скрывала содержимое экрана с помощью
О чем я говорила в предыдущей статье, посвященной как раз снапшотам.
Можно вообще сделать так, чтобы конкретная activity приложения не отображалось в задачах, проставив в манифесте
Либо можно воспользоваться хитростью с помощью
Можно задать основной активности выше приведенный флаг excludeFromRecents = true, для того чтобы ее экран отсутствовал в запущенных задачах, но во время загрузки приложения запустить отдельную задачу, которая будет показывать либо размытый скриншот с основной активности, либо любое другое изображение. Более подробно, как это можно сделать описано в официальной документации на примере Google Drive.
Экран блокировки
Keyguard уже посложнее всех вышеприведенных модулей. Он представляет из себя сервис, который запускается в SystemUI, а управляется при помощи KeyguardViewMediator.
Однако на самом деле KeyguardService самостоятельно не работает с интерфейсом экрана блокировки, он лишь передает информацию в модуль StatusBar, где уже и производятся действия относительно визуального вида экрана и отображения информации.
Панель уведомлений
SystemBars имеет довольно сложное устройство и структуру. Его работа разделяется на два этапа:
- Инициализация SystemBars
- Отображение уведомлений
Если посмотреть на запуск SystemBars
То мы видим ссылку на ресурс из которого читается имя класса и создается его экземпляр.
Таким образом мы видим что тут вызывается StatusBar, который будет работать с выводом уведомлений и UI.
Я думаю никто и не сомневался в том, что Android устроен очень сложно и заключает в себе много хитростей, которые описаны в огромном количестве строчек кода. SystemUI является одной из самых важных частей этой системы и мне понравилось изучать ее. Из-за того что материала на эту тему очень мало, если вы заметите какие-либо ошибки, прошу исправить меня.
Источник