Руководство по разработке модулей
ShizuSU предоставляет механизм модулей, позволяющий добиться эффекта модификации системного каталога при сохранении целостности системного раздела. Этот механизм принято называть "бессистемным".
Модульный механизм ShizuSU практически аналогичен механизму Magisk. Если вы знакомы с разработкой модулей Magisk, то разработка модулей ShizuSU очень похожа. Представление модулей ниже можно пропустить, достаточно прочитать [различия-с-magisk] (difference-with-magisk.md).
МЕТАМОДУЛЬ ТРЕБУЕТСЯ ТОЛЬКО ДЛЯ МОДИФИКАЦИИ СИСТЕМНЫХ ФАЙЛОВ
Модульная система ShizuSU основана на Magic Mount (из SukiSU-Ultra); для монтирования директории system не требуется устанавливать metamodule. Модули, изменяющие файлы /system, работают из коробки. См. Модульная система: Magic Mount.
Ядерные модули KPM
KernelPatch Module (KPM) позволяет загружать модули непосредственно на уровне ядра — идеально для продвинутых модификаций и улучшений ядра. ShizuSU полностью поддерживает KPM (портировано из Apatch). Для использования KPM включите CONFIG_KPM=y при сборке ядра.
WebUI
ShizuSU modules support displaying interfaces and interacting with users. See the WebUI documentation for additional details.
Конфигурация модулей
ShizuSU предоставляет встроенную систему конфигурации, которая позволяет модулям хранить постоянные или временные настройки в формате ключ-значение. Подробности смотрите в документации по конфигурации модулей.
Busybox
В комплект поставки ShizuSU входит полнофункциональный бинарный файл BusyBox (включая полную поддержку SELinux). Исполняемый файл находится по адресу /data/adb/ksu/bin/busybox. BusyBox от ShizuSU поддерживает переключаемый во время работы "ASH Standalone Shell Mode". Этот автономный режим означает, что при запуске в оболочке ash BusyBox каждая команда будет напрямую использовать апплет внутри BusyBox, независимо от того, что задано в качестве PATH. Например, такие команды, как ls, rm, chmod будут НЕ использовать то, что находится в PATH (в случае Android по умолчанию это будут /system/bin/ls, /system/bin/rm и /system/bin/chmod соответственно), а вместо этого будут напрямую вызывать внутренние апплеты BusyBox. Это гарантирует, что скрипты всегда будут выполняться в предсказуемом окружении и всегда будут иметь полный набор команд, независимо от того, на какой версии Android они выполняются. Чтобы заставить команду не использовать BusyBox, необходимо вызвать исполняемый файл с полными путями.
Каждый сценарий оболочки, запущенный в контексте ShizuSU, будет выполняться в оболочке BusyBox ash с включенным автономным режимом. Для сторонних разработчиков это касается всех загрузочных скриптов и скриптов установки модулей.
Для тех, кто хочет использовать эту возможность "Автономного режима" вне ShizuSU, есть два способа включить ее:
- Установите переменной окружения
ASH_STANDALONEзначение1
Пример:ASH_STANDALONE=1 /data/adb/ksu/bin/busybox sh <script> - Переключитесь с помощью параметров командной строки:
/data/adb/ksu/bin/busybox sh -o standalone <script>
Чтобы убедиться, что все последующие запуски оболочки sh также выполняются в автономном режиме, предпочтительным методом является вариант 1 (и это то, что ShizuSU и менеджер ShizuSU используют внутри), поскольку переменные окружения наследуются вплоть до дочерних процессов.
отличие от Magisk
BusyBox в ShizuSU теперь использует бинарный файл, скомпилированный непосредственно из проекта Magisk. **Поэтому вам не нужно беспокоиться о проблемах совместимости между скриптами BusyBox в Magisk и ShizuSU, поскольку они абсолютно одинаковы!
Модули ShizuSU
Модуль ShizuSU - это папка, размещенная в каталоге /data/adb/modules и имеющая следующую структуру:
/data/adb/modules
├── .
├── .
|
├── $MODID <--- Папка имеет имя с идентификатором модуля
│ │
│ │ *** Идентификация модуля ***
│ │
│ ├── module.prop <--- В этом файле хранятся метаданные модуля
│ │
│ │ *** Основное содержимое ***
│ │
│ ├── system <--- Эта папка будет смонтирована, если skip_mount не существует
│ │ ├── ...
│ │ ├── ...
│ │ └── ...
│ │
│ │ *** Флаги состояния ***
│ │
│ ├── skip_mount <--- Если он существует, то ShizuSU НЕ будет монтировать вашу системную папку
│ ├── disable <--- Если модуль существует, то он будет отключен
│ ├── remove <--- Если модуль существует, то при следующей перезагрузке он будет удален
│ │
│ │ *** Необязательные файлы ***
│ │
│ ├── post-fs-data.sh <--- Этот скрипт будет выполняться в post-fs-data
│ ├── service.sh <--- Этот скрипт будет выполняться в сервисе late_start
| ├── uninstall.sh <--- Этот скрипт будет выполнен, когда ShizuSU удалит ваш модуль
│ ├── system.prop <--- Свойства из этого файла будут загружены в качестве системных свойств программой resetprop
│ ├── sepolicy.rule <--- Дополнительные пользовательские правила sepolicy
│ ├── initrc/ <--- Файлы .rc в этом каталоге будут добавлены в init.rc при загрузке
│ │ ├── myservice.rc
│ │ └── ...
│ │
│ │ *** Автоматически генерируется, НЕЛЬЗЯ создавать или изменять вручную ***
│ │
│ ├── vendor <--- Символьная ссылка на $MODID/system/vendor
│ ├── product <--- Символьная ссылка на $MODID/system/product
│ ├── system_ext <--- Симлинк на $MODID/system/system_ext
│ │
│ │ *** Допускается использование любых дополнительных файлов/папок ***
│ │
│ ├── ...
│ └── ...
|
├── another_module
│ ├── .
│ └── .
├── .
├── .различия с Magisk
ShizuSU не имеет встроенной поддержки Zygisk, поэтому в модуле нет содержимого, связанного с Zygisk. Однако для поддержки модулей Zygisk можно использовать ZygiskNext. В этом случае содержимое модуля Zygisk идентично содержимому, поддерживаемому Magisk.
module.prop
module.prop - это конфигурационный файл модуля. В ShizuSU, если модуль не содержит этого файла, он не будет распознан как модуль. Формат этого файла следующий:
id=<string>
name=<string>
version=<string>
versionCode=<int>
author=<string>
description=<string>
updateJson=<url> (optional)
actionIcon=<path> (optional)
webuiIcon=<path> (optional)idдолжно соответствовать данному регулярному выражению:^[a-zA-Z][a-zA-Z0-9._-]+$
экс: ✓a_module, ✓a.module, ✓module-101, ✗a module, ✗1_module, ✗-a-module
Это уникальный идентификатор вашего модуля. Не следует изменять его после публикации.versionCodeдолжен быть целым. Это используется для сравнения версий.- Другими, не упомянутыми выше, могут быть любые однострочные строки.
- Обязательно используйте тип перевода строки
UNIX (LF), а неWindows (CR+LF)илиMacintosh (CR). actionIconиwebuiIcon— необязательные пути к изображениям, которые используются как значки по умолчанию для ярлыков действия и WebUI модуля в менеджере. Эти пути должны быть относительными к корневому каталогу модуля. Например,actionIcon=icon/icon.pngбудет интерпретирован как<MODDIR>/icon/icon.png.
ДИНАМИЧЕСКОЕ ОПИСАНИЕ
Поле description может быть динамически переопределено во время выполнения с помощью системы конфигурации модулей. Подробности см. в разделе Переопределение описания модуля.
Сценарии командной оболочки
Чтобы понять разницу между post-fs-data.sh и Service.sh, прочитайте раздел Boot Scripts. Для большинства разработчиков модулей service.sh должно быть достаточно, если вам нужно просто запустить загрузочный скрипт.
Во всех скриптах вашего модуля используйте MODDIR=${0%/*} для получения пути к базовому каталогу вашего модуля; НЕ кодируйте жестко путь к вашему модулю в скриптах.
различия с Magisk
С помощью переменной окружения KSU можно определить, выполняется ли сценарий в ShizuSU или в Magisk. Если скрипт выполняется в ShizuSU, то это значение будет равно true.
каталог system
После загрузки системы содержимое этого каталога будет наложено поверх раздела /system. Это означает, что:
ТРЕБОВАНИЕ МЕТАМОДУЛЯ
Модульная система ShizuSU основана на Magic Mount (из SukiSU-Ultra); каталог system монтируется напрямую без метамодуля. См. Модульная система: Magic Mount.
- Файлы с теми же именами, что и в соответствующем каталоге в системе, будут перезаписаны файлами в этом каталоге.
- Папки с теми же именами, что и в соответствующем каталоге в системе, будут объединены с папками в этом каталоге.
Если вы хотите удалить файл или папку в исходном каталоге системы, объявите в customize.sh переменную REMOVE, содержащую список каталогов. ShizuSU скроет эти файлы через Magic Mount (раздел /system при этом фактически не изменится).
REMOVE="
/system/app/YouTube
/system/app/Bloatware
"/system/app/YouTube и /system/app/Bloatware будут скрыты после вступления модуля в силу.
Если вы хотите заменить каталог в системе, объявите переменную REPLACE в customize.sh. ShizuSU выполнит bind mount пустого каталога поверх целевого пути, полностью заменив его (без изменения раздела /system).
REPLACE="
/system/app/YouTube
/system/app/Bloatware
"/system/app/YouTube и /system/app/Bloatware будут заменены на пустые каталоги после вступления модуля в силу.
различия с Magisk
Официальный KernelSU использует механизм OverlayFS (metamodule) для бессистемных модификаций, тогда как ShizuSU, основанный на SukiSU-Ultra, использует Magic Mount (bind mount), как и Magisk. Оба подхода достигают одной цели: модификация файлов /system без физического изменения раздела /system. ShizuSU использует только Magic Mount — двух модульных систем не существует. См. Модульная система: Magic Mount.
system.prop
Этот файл имеет тот же формат, что и build.prop. Каждая строка состоит из [key]=[value].
sepolicy.rule
Если для вашего модуля требуются дополнительные патчи sepolicy, добавьте эти правила в данный файл. Каждая строка в этом файле будет рассматриваться как утверждение политики.
Инъекция initrc
ShizuSU предоставляет механизм для внедрения кастомных директив Android Init RC в системный init.rc. Это позволяет модулям регистрировать кастомные службы Android, устанавливать триггеры свойств или выполнять другие действия на языке Init без изменения системного раздела.
Во время загрузки модуль ядра ShizuSU перехватывает системные вызовы read() и fstat(). Когда процесс init Android читает /system/etc/init/hw/init.rc, ShizuSU прозрачно добавляет кастомное содержимое RC в конец файла. Процесс init анализирует эти внедренные директивы точно так же, как исходное содержимое init.rc.
На стороне пользовательского пространства ksud объединяет все файлы .rc из включенных модулей в один файл modules.rc, хранящийся в разделе /metadata. Этот файл автоматически пересоздается всякий раз, когда изменяется состояние модуля (установка, включение, отключение, удаление и т.д.).
Файлы initrc модуля
Создайте подкаталог initrc/ в каталоге вашего модуля и поместите туда файлы .rc:
/data/adb/modules/<MODID>/
├── initrc/
│ ├── myservice.rc
│ └── another.rc
└── ...TIP
- Файлы должны иметь расширение
.rc. - Пока модуль включен, все файлы
.rcв каталогеinitrc/будут включены (разрешение на выполнение не требуется). - Файлы обрабатываются в алфавитном порядке имен файлов внутри каталога, а модули обрабатываются в алфавитном порядке ID модулей.
Общие файлы initrc
Помимо файлов RC на уровне модуля, вы можете поместить файлы .rc в глобальный каталог:
/data/adb/initrc.d/
├── myservice.rc
└── another.rcОбщим файлам initrc требуется разрешение на выполнение
В отличие от каталога модуля initrc/, файлы в /data/adb/initrc.d/ должны иметь права на выполнение, чтобы быть включенными. Неисполняемые файлы .rc будут пропущены без уведомления.
Общие файлы initrc.d/ обрабатываются до любых файлов RC модулей.
Пример
Вот пример файла .rc, который регистрирует кастомную службу Android:
service myservice /data/adb/modules/mymodule/bin/myservice
user root
group root
disabled
seclabel u:r:ksu:s0
on property:sys.boot_completed=1
start myserviceЕсли этот файл помещен в /data/adb/modules/mymodule/initrc/myservice.rc, он зарегистрирует службу с именем myservice при загрузке и запустит ее по достижении sys.boot_completed=1.
Обновление вручную
Вы можете вручную запустить пересоздание modules.rc с помощью следующей команды (изменения вступят в силу при следующей загрузке):
ksud initrc refreshTIP
- Инъекция initrc происходит очень рано в процессе загрузки (когда init читает init.rc), до выполнения post-fs-data и любых скриптов модуля.
- Внедренное содержимое RC рассматривается init как часть исходного init.rc, поддерживая весь синтаксис языка Android Init (определения служб, триггеры, настройки свойств и т.д.).
- Инъекция initrc недоступна в режиме late-load, поскольку хуки системных вызовов в этом режиме не устанавливаются.
- Инъекцию RC модулей можно отключить, передав параметр
--no-custom-rcпри патчинге образа с помощью ksud.
Установщик модулей
Инсталлятор модуля ShizuSU - это модуль ShizuSU, упакованный в zip-файл, который может быть прошит в APP-менеджере ShizuSU. Простейший установщик модуля ShizuSU - это просто модуль ShizuSU, упакованный в zip-файл.
module.zip
│
├── customize.sh <--- (Необязательно, более подробно позже)
│ Этот скрипт будет использоваться в update-binary
├── ...
├── ... /* Остальные файлы модуля */
│WARNING
Модуль ShizuSU НЕ поддерживается для установки в пользовательское Recovery!!!
Персонализация
Если вам необходимо настроить процесс установки модуля, то в качестве опции вы можете создать в программе установки скрипт с именем customize.sh. Этот скрипт будет источником (не исполняться!) сценария установщика модуля после извлечения всех файлов и применения стандартных разрешений и secontext. Это очень удобно, если ваш модуль требует дополнительной настройки в зависимости от ABI устройства, или вам необходимо установить специальные разрешения/секонтекст для некоторых файлов модуля.
Если вы хотите полностью контролировать и настраивать процесс установки, объявите SKIPUNZIP=1 в файле customize.sh, чтобы пропустить все шаги установки по умолчанию. При этом ваш customize.sh будет сам отвечать за установку.
Сценарий customize.sh запускается в оболочке BusyBox ash ShizuSU с включенным "Автономным режимом". Доступны следующие переменные и функции:
Переменные
KSU(bool): переменная, отмечающая, что скрипт выполняется в окружении ShizuSU, причем значение этой переменной всегда будет true. Ее можно использовать для различения ShizuSU и Magisk.KSU_VER(string): строка версии текущего установленного ShizuSU (например,v0.4.0)KSU_VER_CODE(int): код версии текущего установленного ShizuSU в пользовательском пространстве (например,10672)KSU_KERNEL_VER_CODE(int): код версии текущей установленной ShizuSU в пространстве ядра (например,10672)BOOTMODE(bool): в ShizuSU всегда должно бытьtrue.MODPATH(path): путь, по которому должны быть установлены файлы ваших модулейTMPDIR(path): место, где вы можете временно хранить файлыZIPFILE(path): установочный zip-архив вашего модуляARCH(string): архитектура процессора устройства. Значение:arm,arm64,x86илиx64.IS64BIT(bool):true, если$ARCHимеет значениеarm64илиx64.API(int): уровень API (версия Android) устройства (например,23для Android 6.0)KSU_UAPI_VER(int): версия UAPI пользовательского пространства ShizuSU (ksud) (например,2). Эта версия увеличивается при критических изменениях в драйвере ядра, и модули могут использовать её для проверки совместимости.KSU_RUNTIME_MODE(string): текущий режим работы ShizuSU. Возможные значения:built-in(режим GKI, встроен в ядро),lkm(загружен как модуль ядра при запуске) илиlate-load(загружен как модуль ядра после загрузки).KSU_LATE_LOAD(int?): если ShizuSU загружен с задержкой после загрузки системы, значение этой переменной равно1; в противном случае переменная не устанавливается.
WARNING
В ShizuSU MAGISK_VER_CODE всегда равен 25200, а MAGISK_VER всегда равен v25.2. Пожалуйста, не используйте эти две переменные для определения того, запущен ли он на ShizuSU или нет.
Функции
ui_print <msg>
вывести <msg> на консоль
Избегайте использования 'echo', так как он не будет отображаться в консоли пользовательского recovery
abort <msg>
вывести сообщение об ошибке <msg> на консоль и завершить установку
Избегайте использования команды 'exit', так как в этом случае будут пропущены шаги очистки завершения установки
set_perm <target> <owner> <group> <permission> [context]
если [context] не задан, то по умолчанию используется "u:object_r:system_file:s0".
Эта функция является сокращением для следующих команд:
chown owner.group target
chmod permission target
chcon context target
set_perm_recursive <directory> <owner> <group> <dirpermission> <filepermission> [context]
если [context] не задан, то по умолчанию используется "u:object_r:system_file:s0".
для всех файлов в <directory> будет вызвана команда:
set_perm file owner group filepermission context
для всех каталогов в <directory> (включая себя самого), он вызовет:
set_perm dir owner group dirpermission contextЗагрузочные сценарии
В ShizuSU скрипты делятся на два типа в зависимости от режима их работы: режим post-fs-data и режим late_start service:
- режим post-fs-data
- Эта стадия является БЛОКИРУЮЩЕЙ. Процесс загрузки приостанавливается до завершения выполнения или по истечении 10 секунд.
- Сценарии запускаются до того, как будут смонтированы какие-либо модули. Это позволяет разработчику модулей динамически настраивать свои модули до того, как они будут смонтированы.
- Этот этап происходит до запуска Zygote, что практически означает, что все в Android
- ПРЕДУПРЕЖДЕНИЕ: использование
setpropприведет к блокировке процесса загрузки! Вместо этого используйтеresetprop -n <prop_name> <prop_value>. - Запускайте скрипты в этом режиме только в случае необходимости.
- режим обслуживания late_start
- Эта стадия является НЕБЛОКИРУЮЩЕЙ. Ваш скрипт выполняется параллельно с остальным процессом загрузки.
- Это рекомендуемый этап для запуска большинства скриптов.
В ShizuSU скрипты запуска делятся на два типа по месту их хранения: общие скрипты и скрипты модулей:
- Общие скрипты
- Размещаются в файлах
/data/adb/post-fs-data.dили/data/adb/service.d. - Выполняется только в том случае, если скрипт установлен как исполняемый (
chmod +x script.sh) - Скрипты в
post-fs-data.dвыполняются в режиме post-fs-data, а скрипты вservice.d- в режиме late_start service. - Модули не должны НЕ добавлять общие скрипты при установке
- Размещаются в файлах
- Скрипты модуля
- Размещаются в отдельной папке модуля
- Выполняются только в том случае, если модуль включен
post-fs-data.shзапускается в режиме post-fs-data, аservice.sh- в режиме late_start service.
Все загрузочные скрипты будут выполняться в оболочке BusyBox ash от ShizuSU с включенным "Автономным режимом".
Режим late-load
Помимо стандартного процесса загрузки, описанного выше, ShizuSU поддерживает режим late-load для сценариев LKM (загружаемый модуль ядра). В этом режиме модуль ядра ShizuSU загружается после полной загрузки системы, а не во время процесса init.
Когда происходит late-load?
Late-load запускается командой ksud late-load. Эта команда:
- Определяет текущую версию KMI и загружает соответствующий
kernelsu.koиз встроенных ресурсов. - Выполняет инициализацию модуля (правила SELinux, список разрешений, функции и т.д.), которая обычно происходит во время загрузки.
Поскольку система уже полностью запущена, некоторые механизмы времени загрузки недоступны или не нужны.
Отличия от стандартной загрузки
| Поведение | Стандартная загрузка | Режим late-load |
|---|---|---|
| Модуль ядра загружен init (PID 1) | Да | Нет (загружен после загрузки) |
| Хуки kprobe ksud (execve/read/fstat/input) | Да | Пропущены |
| Обнаружение безопасного режима (клавиша громкости) | Да | Всегда отключено |
| Захват журнала загрузки (logcat/dmesg) | Да | Пропущен |
| Проверка сосуществования с Magisk | Да | Пропущена |
Событие post-fs-data отправлено ядру | Да | Пропущено |
Событие boot-completed отправлено ядру | Да | Установлено напрямую при инициализации |
Скрипты post-fs-data.sh / post-fs-data.d/ | Да | Заменены этапом late-load |
Загрузка system.prop | Да | Да |
| Монтирование модулей Magic Mount | Да | Да |
Скрипты post-mount.sh / post-mount.d/ | Да | Да |
Скрипты service.sh / service.d/ | Да | Да |
Скрипты boot-completed.sh / boot-completed.d/ | Да | Да |
Переменная окружения KSU_LATE_LOAD | Не установлена | Установлена в 1 |
Флаг info ядра 0x4 | Не установлен | Установлен |
Порядок выполнения скриптов
В режиме late-load порядок выполнения скриптов следующий:
ksud late-load:
1. Загрузить kernelsu.ko (если ещё не загружен)
2. Извлечь бинарные файлы, обработать обновления модулей, загрузить правила SELinux, инициализировать функции
3. Выполнить скрипты late-load.d/ и скрипты late-load модулей (блокирующе)
4. Загрузить system.prop (resetprop -n)
5. Выполнить монтирование модулей Magic Mount
6. Выполнить скрипты post-mount.d/ и post-mount.sh модулей (блокирующе)
7. Выполнить скрипты service.d/ и service.sh модулей (неблокирующе)
8. Выполнить скрипты boot-completed.d/ и boot-completed.sh модулей (неблокирующе)Скрипты, специфичные для late-load
Модули могут предоставить скрипт late-load.sh, который выполняется только в режиме late-load, как замена post-fs-data.sh. Этот скрипт выполняется до монтирования модулей, аналогично post-fs-data.sh в стандартном потоке.
Кроме того, общие скрипты можно размещать в /data/adb/late-load.d/ для выполнения на этом этапе.
Обнаружение режима late-load в скриптах
Модули могут определить режим late-load, проверив переменную окружения KSU_LATE_LOAD:
if [ "$KSU_LATE_LOAD" = "1" ]; then
# Работа в режиме late-load
echo "Late-load mode detected"
fiЭто позволяет модулям соответствующим образом корректировать своё поведение, например, пропуская операции, необходимые только при ранней загрузке.
Удобство управления модулями
ShizuSU предоставляет ряд удобств управления модулями:
- Резервное копирование и восстановление:Бэкап/восстановление установленных модулей и белого списка root в один тап.
- Пакетная установка:Установка нескольких zip-модулей за раз; сбой одного модуля не прерывает процесс, ошибки собираются и сообщаются в конце.
- Пакетное управление:Включение, отключение, отключение всех и удаление всех в один тап.
