Руководство по разработке модулей APM 
APatch предоставляет модульный механизм (AndroidPatch Module) для модификации системного раздела с сохранением его целостности. Этот механизм часто называют бессистемным (systemless).
Реализация модулей APatch скопирована и модифицирована из KernelSU.
Модифицированный код находится здесь:
KernelSU: https://github.com/tiann/KernelSU/tree/main/userspace/ksud
 APatch: https://github.com/bmax121/APatch/tree/main/apd
Приведенная ниже документация скопирована и изменена из документации KernelSU, и большая часть ее содержания совпадает. Основные моменты, на которые следует обратить внимание, следующие:
- Расположение файлов
- Переменные окружения
- Поддержка SELinux, APatch напрямую использует magiskpolicy
Механизм работы модулей APatch почти такой же, как и Magisk. Если вы знакомы с разработкой модулей Magisk, то разработка модулей APatch очень похожа. Представление модулей ниже можно пропустить, достаточно прочитать в чем заключаются различия.
BusyBox 
APatch предоставляет полнофункциональный бинарный файл BusyBox (включая полную поддержку SELinux). Исполняемый файл находится по адресу /data/adb/ap/bin/busybox. BusyBox от APatch поддерживает переключаемый во время выполнения «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, вы должны вызвать исполняемый файл с полным путем.
Каждый сценарий оболочки, запущенный в контексте APatch, будет выполняться в оболочке BusyBox ash с включенным автономным режимом. Для сторонних разработчиков это касается всех загрузочных скриптов и скриптов установки модулей.
Для тех, кто хочет использовать эту функцию «автономного режима» вне APatch, есть два способа включить ее:
- Установите переменной окружения ASH_STANDALONEзначение1.
 Пример:ASH_STANDALONE=1 /data/adb/ap/bin/busybox sh <script>.
- Переключитесь с помощью параметров командной строки:/data/adb/ap/bin/busybox sh -o standalone <script>.
Чтобы гарантировать, что все последующие оболочки sh будут выполняться в автономном режиме, первый способ является предпочтительным (это также метод, используемый APatch и менеджером APatch), поскольку переменные окружения наследуются в дочерних процессах.
Различия с KernelSU
Расположение busybox было изменено с /data/adb/ksu/bin/busybox на /data/adb/ap/bin/busybox.
Различия с Magisk
BusyBox от APatch теперь представляет собой бинарник, скомпилированный непосредственно с помощью проекта Magisk, спасибо Magisk! Поэтому вам не нужно беспокоиться о совместимости скриптов BusyBox со скриптами Magisk и APatch, потому что они абсолютно одинаковы!
Модули APM 
Модуль APatch - это папка внутри /data/adb/modules со следующей структурой:
/data/adb/modules
├── .
├── .
|
├── $MODID                  <--- Имя папки модуля совпадает с его идентификатором
│   │
│   │      *** Идентификация модуля ***
│   │
│   ├── module.prop         <--- В этом файле хранятся метаданные модуля
│   │
│   │      *** Основное содержание ***
│   │
│   ├── system              <--- Эта папка будет смонтирована, если skip_mount не задан
│   │   ├── ...
│   │   ├── ...
│   │   └── ...
│   │
│   │      *** Флаги состояния ***
│   │
│   ├── skip_mount          <--- Если этот файл существует, то папка `/system` модуля не будет смонтирована
│   ├── disable             <--- Если этот файл существует, то модуль отключен
│   ├── remove              <--- Если этот файл существует, модуль будет удален при следующей перезагрузке
│   │
│   │      *** Дополнительные файлы ***
│   │
│   ├── post-fs-data.sh     <--- Этот скрипт будет выполняться в режиме post-fs-data
│   ├── post-mount.sh       <--- Этот скрипт будет запущен после монтирования файлов
│   ├── service.sh          <--- Этот скрипт будет запущен в режиме late_start сервиса
│   ├── boot-completed.sh   <--- Этот скрипт будет запущен после завершения загрузки Android
|   ├── uninstall.sh        <--- Этот скрипт будет запущен, когда модуль будет удален
│   ├── system.prop         <--- Свойства, указанные в этом файле, будут изменены во время загрузки с помощью resetprop
│   ├── sepolicy.rule       <--- Политика SELinux в этом файле будет загружаться во время загрузки
│   │
│   │      *** Автоматически генерируемые каталоги, не создавайте и не изменяйте их вручную! ***
│   │
│   ├── vendor              <--- Симлинк на $MODID/system/vendor
│   ├── product             <--- Симлинк на $MODID/system/product
│   ├── system_ext          <--- Симлинк на $MODID/system/system_ext
│   │
│   │      *** Любые дополнительные файлы / папки разрешены ***
│   │
│   ├── ...
│   └── ...
|
├── another_module
│   ├── .
│   └── .
├── .
├── .Различия с Magisk
APatch не имеет встроенной поддержки Zygisk, поэтому в модуле нет содержимого, связанного с Zygisk. Однако для поддержки модулей Zygisk можно использовать ZygiskNext или Zygisk_mod. В этом случае содержимое модуля Zygisk идентично содержимому, поддерживаемому Magisk.
module.prop 
module.prop - это конфигурационный файл модуля. Если модуль не содержит этого файла, он не будет распознан как модуль. Формат этого файла следующий:
id=<строка>
name=<строка>
version=<строка>
versionCode=<целое число>
author=<строка>
description=<строка>- 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).
Сценарии командной оболочки 
Различия между post-fs-data.sh, post-mount.sh, service.sh и boot-completed.sh описаны в разделе Загрузочные сценарии. Для большинства разработчиков модулей service.sh должно быть достаточно, если вам нужно запустить только загрузочный скрипт.
Во всех скриптах для вашего модуля используйте MODDIR=${0%/*} для получения пути к базовому каталогу вашего модуля. Не вводите путь к модулю в скриптах жестко!
Различия с Magisk, KernelSU
Вы можете определить, запущен ли скрипт в APatch, используя переменную окружения APATCH, если он запущен в APatch, это значение будет установлено в true.
Каталог system 
После загрузки системы содержимое этого каталога будет наложено поверх раздела /system с помощью OverlayFS. Это означает, что:
- Файлы с таким же именем в соответствующем каталоге в системе перезаписываются файлами в этом каталоге.
- Папки с таким же именем в соответствующем каталоге в системе объединяются с папками в этом каталоге.
Если вы хотите удалить файл или папку в исходном каталоге системы, необходимо создать файл с тем же именем, что и файл/папка, в каталоге модуля с помощью команды mknod filename c 0 0. Таким образом, система OverlayFS автоматически "забелит" этот файл, как если бы он был удален (раздел /system при этом фактически не изменится).
Вы также можете выполнить операцию удаления, объявив переменную REMOVE в customize.sh со списком директорий, и APatch автоматически выполнит за вас mknod <TARGET> c 0 0 в соответствующей директории модуля. Например:
REMOVE="
/system/app/YouTube
/system/app/Bloatware
"В приведенном выше примере будут выполнены команды mknod $MODPATH/system/app/YouTube c 0 0 и mknod $MODPATH/system/app/Bloatware c 0 0; при этом /system/app/YouTube и /system/app/Bloatware будут удалены после вступления модуля в силу.
Если вы хотите заменить каталог в системе, то необходимо создать каталог с тем же путем в каталоге модуля, а затем установить для этого каталога атрибут setfattr -n trusted.overlay.opaque -v y <TARGET>. Таким образом, система OverlayFS автоматически заменит соответствующий каталог в системе (без изменения раздела /system).
Вы можете объявить в файле customize.sh переменную с именем REPLACE, содержащую список заменяемых каталогов, и APatch автоматически выполнит соответствующие операции в каталоге вашего модуля. Например:
REPLACE="
/system/app/YouTube
/system/app/Bloatware
"В этом примере будут автоматически созданы каталоги $MODPATH/system/app/YouTube и $MODPATH/system/app/Bloatware, а затем выполнены команды setfattr -n trusted.overlay.opaque -v y $MODPATH/system/app/YouTube и setfattr -n trusted.overlay.opaque -v y $MODPATH/system/app/Bloatware. После вступления модуля в силу каталоги /system/app/YouTube и /system/app/Bloatware будут заменены на пустые.
Различия с Magisk
Бессистемный механизм APatch реализован через OverlayFS ядра, в то время как Magisk в настоящее время использует магическое монтирование (bind mount). Между этими двумя реализациями существует огромная разница, но конечная цель фактически одна и та же: модифицировать файл /system без изменения физического раздела /system.
Если вы заинтересованы в использовании OverlayFS, рекомендуется прочитать документацию по OverlayFS ядра Linux.
system.prop 
Формат этого файла точно такой же, как и у build.prop: каждая строка имеет вид [key]=[value].
sepolicy.rule 
Если ваш модуль требует дополнительных патчей политики SELinux, добавьте эти правила в этот файл. Каждая строка в этом файле будет считаться утверждением политики.
Установщик модулей 
Пакет установки модуля APatch представляет собой zip-файл, который можно прошить через APatch Manager, и формат этого zip-файла следующий:
module.zip
│
├── customize.sh                       <--- (Необязательно, подробнее позже)
│                                           Этот скрипт будет использоваться в update-binary
├── ...
├── ...  /* Остальные файлы модуля */
│WARNING
Модуль APatch не поддерживается для установки в Recovery!
Индивидуальный процесс установки 
Если вам необходимо настроить процесс установки модуля, то в качестве опции вы можете создать в программе установки скрипт с именем customize.sh. Этот скрипт будет источником (не исполняться) сценария установщика модуля после извлечения всех файлов и применения стандартных разрешений и secontext. Это очень удобно, если ваш модуль требует дополнительной настройки в зависимости от ABI устройства, или вам необходимо установить специальные разрешения/секонтекст для некоторых файлов модуля.
Если вы хотите полностью контролировать и настраивать процесс установки, объявите SKIPUNZIP=1 в файле customize.sh, чтобы пропустить все шаги установки по умолчанию. При этом ваш customize.sh будет сам отвечать за установку.
Сценарий customize.sh запускается в «автономном режиме» в оболочке BusyBox ash от APatch. Вы можете использовать следующие переменные и функции:
Переменные 
- KERNELPATCH(bool): Пометьте этот скрипт для запуска в среде APatch, и значение этой переменной всегда будет- true.
- KERNEL_VERSION(hex): Наследуется от KernelPatch, номер версии ядра (например,- 50a01означает- 5.10.1).
- KERNELPATCH_VERSION(hex): Наследуется от KernelPatch, номер версии KernelPatch (например,- a05означает- 0.10.5).
- SUPERKEY(string): Наследуется от KernelPatch, используется для вызова kpatch или supercall.
- APATCH(bool): Пометьте этот скрипт для запуска в среде APatch, и значение этой переменной всегда будет- true.
- APATCH_VER_CODE(int): Номер текущей версии APatch (например.- 10672).
- APATCH_VER(string): Имя текущей версии APatch (например.- 10672).
- BOOTMODE(bool): В APatch эта переменная всегда будет иметь значение- true.
- MODPATH(path): Каталог установки текущего модуля.
- TMPDIR(path): Каталог, в котором могут храниться временные файлы.
- ZIPFILE(path): Файл пакета установки для текущего модуля.
- ARCH(string): Архитектура процессора устройства, только- arm64.
- IS64BIT(bool): Является ли это устройство 64-битным.
- API(int): Текущая версия Android API устройства (например,- 23на Android 6.0).
WARNING
В APatch MAGISK_VER_CODE имеет значение 27000, а MAGISK_VER - 27.0.
Функции 
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».
    для всех файлов в <каталоге>, он вызовет:
       set_perm file owner group filepermission context
    для всех каталогов в <каталоге> (включая себя), он вызовет:
       set_perm dir owner group dirpermission contextЗагрузочные сценарии 
В APatch существует два типа скриптов в зависимости от режима их работы: режим post-fs-data и режим late_start service.
- Режим post-fs-data - Эта фаза является блокирующей. Процесс запуска приостанавливается до завершения выполнения или через 10 секунд.
- Скрипт запускается до установки любого модуля. Это позволяет разработчикам модулей динамически адаптировать свои модули до того, как они будут смонтированы.
- Эта фаза наступает перед началом развития зиготы.
- Использование setprop может привести к зависанию во время запуска! Вместо этого используйте resetprop -n <prop_name> <prop_value>.
- Запускайте скрипты в этом режиме только в случае необходимости.
 
- Режим late_start сервиса - Эта фаза является неблокирующей. Ваш скрипт будет выполняться параллельно с остальным процессом запуска.
- Большинство скриптов рекомендуется запускать в этом режиме.
 
В APatch есть еще два типа стартовых скриптов в зависимости от места их хранения: общие скрипты и скрипты модулей.
- Общие скрипты - Поместите его в /data/adb/post-fs-data.d,/data/adb/post-mount.d,/data/adb/service.dили/data/adb/boot-completed.d.
- Скрипты будут выполняться только в том случае, если они установлены как исполняемые (chmod +x script.sh).
- Скрипты в post-fs-data.dвыполняются в режиме post-fs-data, а скрипты вservice.d- в режиме late_start сервиса.
- Модули не должны добавлять общие скрипты во время установки.
 
- Поместите его в 
- Скрипты модуля - Поместите его в собственную папку модуля.
- Выполняется только при включенном модуле.
- post-fs-data.shзапускается в режиме post-fs-data,- post-mount.sh- в режиме post-mount, а- service.sh- в режиме late_start сервиса, а- boot-completed- в режиме сервиса после завершения загрузки Android.
 
Все сценарии запуска будут выполняться в оболочке BusyBox ash от APatch с включенным «автономным режимом».