# A-Team Android ROM Builder — Technical Guide ## 1. Architecture at a Glance A-Team Android ROM Builder is a Python/GTK application wrapped around a script-driven Android ROM workflow. The central design is: ```text GTK interface | v Project state | +--> device configuration | +--> ROM configuration | +--> host configuration | +--> profile configuration | v Environment generation | v Bash scripts | +--> sync +--> device setup +--> GApps +--> build +--> clean +--> updater ``` The GUI should be treated as the control plane. The scripts remain the execution plane. That distinction is important when extending the application: a new ROM-specific operation normally belongs in the script/configuration layer rather than becoming a large block of shell logic inside a GTK callback. --- ## 2. Source Tree The important top-level areas are: ```text builder/ Python backend and application helpers configs/ Device, ROM, host, setup, build-command, and upload configuration profiles/ Saved project profiles scripts/ Build and synchronization operations gui.py GTK application and tab construction ``` The project also contains application assets and supporting files used by the GUI. --- ## 3. `gui.py` `gui.py` is the main GTK application. It is responsible for: - Creating the main window - Creating the application tabs - Creating controls - Reading user selections - Building the current project state - Starting backend actions - Starting scripts - Displaying terminal output - Displaying updater state - Handling application-side UI tools The application uses GTK 3 and VTE for the embedded terminal. ### UI constants UI dimensions are intentionally centralized. Current spacing controls include: ```text BUILD_COMMANDS_TOP_BOTTOM_SPACING BUILD_SETUP_TOP_SPACING PROJECT_PROFILES_TOP_SPACING SYNC_SETUP_TOP_SPACING SPLASH_TOP_BOTTOM_SPACING ``` Current button-width controls include: ```text SYNC_SETUP_BUTTON_WIDTH SYNC_GAPPS_BUTTON_WIDTH BUILD_ROM_BUTTON_WIDTH LAUNCHER_BUTTON_WIDTH CLEAN_BUTTON_WIDTH ``` Keep these constants centralized when modifying layout. Do not scatter repeated pixel values through widget construction unless there is a specific reason. --- ## 4. Configuration Parsing The configuration system uses simple key/value files. Example: ```text DEVICE_CODENAME="milanf" DEVICE_SOC="sm6375" DEVICE_MANUFACTURER="Motorola" ``` Conceptually this becomes: ```python { "DEVICE_CODENAME": "milanf", "DEVICE_SOC": "sm6375", "DEVICE_MANUFACTURER": "Motorola" } ``` Configuration parsing supports the project’s simple `KEY=VALUE` format and ignores comments and blank lines. This intentionally avoids making device and ROM configuration dependent on Python code. --- ## 5. Device Discovery Device discovery is configuration-driven. The builder searches: ```text configs/devices/ ``` for device configuration files. A new device therefore normally does not require a Python edit. ### Minimum device integration Create: ```text configs/devices/example.conf ``` Then provide the values required by the device scripts. For example: ```text DEVICE_CODENAME="example" DEVICE_DISPLAY_CODENAME="Example" DEVICE_DISPLAY_NAME="Example Android Device" DEVICE_MANUFACTURER="Motorola" DEVICE_MODEL_NUMBER="XT0000" DEVICE_SYNC_SCRIPT="example-sync.sh" ``` The GUI can then discover the device from the configuration directory. --- ## 6. Device Sync Scripts Device-specific scripts live under: ```text scripts/devices_sync/ ``` A device configuration points to its script: ```text DEVICE_SYNC_SCRIPT="example-sync.sh" ``` The common synchronization workflow can then load the selected device configuration and execute the selected device-specific script. ### Recommended device addition procedure 1. Create the device `.conf`. 2. Add the device identity variables. 3. Add only device-specific variables that scripts actually require. 4. Create the device sync script. 5. Set `DEVICE_SYNC_SCRIPT`. 6. Test the script independently. 7. Start the GUI and confirm the device appears. 8. Run Sync & Setup Device Source. Testing the shell script independently is useful because it separates Android source/setup failures from GTK failures. --- ## 7. ROM Configuration ROM configuration can come from either: ```text configs/rom.conf ``` or: ```text /rom.conf ``` The ROM-local configuration is the preferred location when a ROM needs its own settings. ### Why two locations exist The builder-wide file provides defaults. The ROM-local file allows a ROM source tree to carry its own configuration. For example: ```text configs/rom.conf ``` could provide generic defaults while: ```text /home/pizzag/Android/Roms/Lineage/23.2/rom.conf ``` contains values specific to that ROM tree. ### Case sensitivity On Linux: ```text rom.conf Rom.conf ROM.conf ``` are three different names. The loader's expected filename is: ```text rom.conf ``` --- ## 8. ROM Configuration Variables ROM configuration can contain build metadata and script variables. Examples: ```text ROM_BUILD_NAME="lineage" ROM_TARGET_RELEASE="bp4a" DEFAULT_ROM_BUILD_COMMAND="brunch $DEVICE_CODENAME" ROM_DISPLAY_NAME="LineageOS" ROM_VENDOR_NAME="lineage" ROM_MANIFEST="https://github.com/LineageOS/android.git" ROM_BRANCH_PREFIX="lineage-" ROM_MAJOR_VERSION="23" ROM_MINOR_VERSION="2" ``` The important principle is that the ROM configuration should contain values that describe the ROM rather than values that uniquely identify a single physical device. Device-specific values belong in the device configuration. --- ## 9. Project State The project state is the bridge between GUI selections and scripts. Typical values include: ```text DEVICE_NAME ROM_NAME ROM_BRANCH ROM_PATH ANDROID_VERSION BUILD_VARIANT BUILD_COMMAND GAPPS_VARIANT CLEAN_VARIANT INSTALLER_VARIANT BUILD_JOBS USE_CCACHE APN_VARIANT ``` Additional variables are merged from configuration sources. The result is converted into an environment that can be consumed by Bash. --- ## 10. Environment Construction The project environment combines GUI selections with configuration values. A simplified model is: ```text GUI/project values | v device variables | v ROM variables | v A-Team setup variables | v upload variables | v variable expansion ``` This is what allows a configuration value such as: ```text DEFAULT_ROM_BUILD_COMMAND="brunch $DEVICE_CODENAME" ``` to use the currently selected device without duplicating the device name in the ROM configuration. When adding a new variable, decide whether it belongs to: - project state - device configuration - ROM configuration - A-Team setup - upload configuration before adding Python-specific handling. --- ## 11. ROM Path Interpretation The selected ROM directory is used to derive ROM identity. For example: ```text /home/pizzag/Android/Roms/Lineage/23.2 ``` can represent: ```text ROM_NAME = Lineage ROM_BRANCH = 23.2 ROM_PATH = /home/pizzag/Android/Roms/Lineage/23.2 ``` The project then exports these values to the scripts. This is why the expected ROM directory structure matters to the GUI. --- ## 12. Build Command System The Build tab reads: ```text configs/rom_build_commands.conf ``` Example: ```text Default --> rom.conf Lineage Derpfest ``` Normal entries become selectable build commands. The command implementation is deliberately separate from the GUI: ```text scripts/build_options/rom_build_commands.sh ``` This allows the command selector to remain simple while the actual command-specific environment is handled in Bash. --- ## 13. `rom_build_commands()` The build-command implementation is a Bash function: ```bash rom_build_commands() { ... } ``` It currently handles three paths. ### Lineage ```bash if [[ $BUILD_COMMAND == "lineage" ]]; then LUNCH_COMMAND="${ROM_BUILD_NAME}_${DEVICE_NAME}-${ROM_TARGET_RELEASE}-${BUILD_VARIANT}" ROM_BUILD_COMMAND="brunch $DEVICE_CODENAME" ``` ### Derpfest ```bash elif [[ $BUILD_COMMAND == "derpfest" ]]; then LUNCH_COMMAND="${ROM_BUILD_NAME}_${DEVICE_NAME}-${ROM_TARGET_RELEASE}-${BUILD_VARIANT}" ROM_BUILD_COMMAND="m derp" ``` ### Default ```bash else LUNCH_COMMAND="${ROM_BUILD_NAME}_${DEVICE_NAME}-${ROM_TARGET_RELEASE}-${BUILD_VARIANT}" ROM_BUILD_COMMAND="$DEFAULT_ROM_BUILD_COMMAND" ``` Each branch exports: ```text LUNCH_COMMAND ROM_BUILD_COMMAND ``` ### Why the function is sourced `build.sh` uses: ```bash source "$BUILD_OPTIONS_DIR/rom_build_commands.sh" rom_build_commands ``` It is important that the file is sourced rather than executed with a separate `bash` process. If the function ran in a child shell, exported variables would not remain available to the parent build script. --- ## 14. Build Execution The build entry point is: ```text scripts/build.sh ``` The script receives the project environment and performs the build preparation. The command-selection flow is: ```text GUI selection | v BUILD_COMMAND | v rom_build_commands() | +--> LUNCH_COMMAND | +--> ROM_BUILD_COMMAND | v build execution ``` The current implementation uses the resulting command strings for the ROM build. When a command is stored as a string containing shell syntax or multiple arguments, the build script must execute it in a way consistent with how the command is defined. --- ## 15. Build Options The GUI exposes project-level build options. ### Android version The selected Android version is exported as: ```text ANDROID_VERSION ``` ### Build variant The project supports the Android build variants exposed by the current GUI. The selected value becomes: ```text BUILD_VARIANT ``` ### GApps The selected GApps mode becomes: ```text GAPPS_VARIANT ``` ### Clean The clean selection becomes: ```text CLEAN_VARIANT ``` ### Installer The installer selection becomes: ```text INSTALLER_VARIANT ``` ### Build jobs The selected job count becomes: ```text BUILD_JOBS ``` ### Ccache The checkbox controls: ```text USE_CCACHE ``` ### Custom APN The Custom APN option controls the APN-related project value consumed by the build scripts. --- ## 16. Sync Workflow The common synchronization entry point is: ```text scripts/sync.sh ``` Its role is to coordinate common setup and then dispatch to the selected device workflow. The architecture is: ```text sync.sh | +--> load configuration | +--> establish A-Team setup | +--> select device script | +--> execute device sync ``` Device-specific behavior remains in: ```text scripts/devices_sync/ ``` This prevents the common sync script from becoming a large device-specific conditional tree. --- ## 17. A-Team Setup Marker The project uses a setup marker under the ROM tree to identify whether the A-Team setup process has already been performed. The marker is: ```text device/A-Team/A-Team-Setup.check ``` The purpose is to prevent the common setup work from being repeated unnecessarily. If the setup requirements change, the marker/versioning logic should be reviewed so existing ROM trees can be migrated safely. --- ## 18. MindTheGapps Synchronization GApps synchronization is handled by: ```text scripts/gapps_sync.sh ``` The script uses the Android version to determine the appropriate MindTheGapps source. The source is synchronized into the ROM tree at the location expected by the current build system. This operation is separate from the core ROM build so it can be repeated without rebuilding the entire ROM. --- ## 19. Project Profiles Profiles are stored under: ```text profiles/ ``` A profile represents a reusable set of project selections. Examples of profile-level information include: ```text device ROM path Android version build variant build command GApps variant clean variant installer variant build jobs ccache APN selection host ``` Profiles should not be used as a replacement for device or ROM configuration files. A profile says: > "Build this project this way." A device configuration says: > "This is how this device is defined." A ROM configuration says: > "This is how this ROM is defined." Keeping those responsibilities separate makes the project easier to maintain. --- ## 20. Build Hosts Host configuration is stored in: ```text configs/hosts.conf ``` The builder supports local and SSH-based hosts. A remote host needs: - SSH access - Android build dependencies - ROM source - required device/vendor/kernel source - Git and other source-management tools - any ROM-specific build dependencies The host configuration tells the application how to reach the machine; it does not replace the machine's Android build environment. --- ## 21. Embedded Terminal The terminal uses VTE and provides a real interactive shell inside the application. The terminal is intentionally not treated as a static output window. It supports shell input and now provides desktop clipboard integration for terminal text. ### Copy Selected terminal text can be copied to the system clipboard. The terminal copy action should not replace normal: ```text Ctrl+C ``` terminal behavior, because Ctrl+C is commonly used to interrupt a running process. ### Paste Clipboard contents can be inserted into the terminal. ### Design consideration Terminal keyboard shortcuts must be implemented carefully because shortcuts such as Ctrl+C have established Unix terminal semantics. --- ## 22. Resource Monitor The Resource Monitor provides live system information through: ```text btop ``` with: ```text bpytop ``` as a fallback where supported by the current implementation. It is particularly useful during Android builds because compilation can consume large amounts of: - CPU - RAM - storage I/O - swap - filesystem capacity --- ## 23. Tools The Tools area contains application-side utilities. ### Splash selection The splash manager handles selection of available splash assets. ### Launcher icons The icon manager handles launcher icon selection. ### Desktop launcher The launcher utility creates a desktop entry for the builder. ### Clean ROM The clean operation invokes the appropriate backend/script workflow rather than embedding a large cleanup implementation in the GUI. --- ## 24. Updater Architecture The updater has three distinct responsibilities: ```text Python updater logic | +--> update discovery +--> download/extraction | GTK updater UI | +--> progress bar +--> status text +--> update dialog | scripts/updater.sh | +--> actual staged update operations ``` This separation matters because the shell script reports what is happening, while the GUI decides how those reports are presented. --- ## 25. Updater Progress Protocol The shell updater communicates progress using: ```text ::PROGRESS:::: ``` For example: ```text ::PROGRESS::3::5 ``` represents: ```text 3 / 5 ``` or: ```text 60% ``` Status messages use: ```text ::STATUS:: ``` Example: ```text ::STATUS::Backing Up Current Installation ... ``` The GUI listens for these markers and updates the updater interface. ### Adding an updater stage If another stage is required: 1. Increase `TOTAL_STEPS`. 2. Add a `::PROGRESS::N::TOTAL` message. 3. Add the corresponding `::STATUS::...` message. 4. Keep the numbering sequential. 5. Test both the script and GUI interpretation. Do not change the marker syntax unless the Python parser is changed at the same time. --- ## 26. Updater Status Appearance Updater status messages are intentionally displayed in: ```text cyan bold ``` The status text is separate from the progress calculation. Therefore: ```text status appearance ``` can be changed without changing: ```text progress percentage ``` and vice versa. The progress calculation is based on: ```text current / total ``` while the status label is simply the human-readable description associated with that stage. --- ## 27. Update JSON and Changelog The update JSON is loaded as a complete object. The update popup uses the available version information and the optional: ```json "changelog": "..." ``` field. For example: ```json { "version": 102, "display": "1.02", "file": "A-Team-Android_ROM_Builder-v1.02.7z", "changelog": "Improved terminal clipboard support." } ``` The popup can present: ```text Installed Version : 1.01 Available Version : 1.02 Changelog: Improved terminal clipboard support. ``` If the field is absent, the application uses its fallback text rather than failing the update dialog. --- ## 28. Adding a Device — Complete Example Suppose a new device is called: ```text example ``` ### Device configuration Create: ```text configs/devices/example.conf ``` Example: ```text DEVICE_CODENAME="example" DEVICE_DISPLAY_CODENAME="Example" DEVICE_DISPLAY_NAME="Example Phone" DEVICE_MANUFACTURER="Motorola" DEVICE_MODEL_NUMBER="XT0000" DEVICE_SYNC_SCRIPT="example-sync.sh" ``` ### Device sync script Create: ```text scripts/devices_sync/example-sync.sh ``` Make it executable: ```bash chmod +x scripts/devices_sync/example-sync.sh ``` ### Test it Run it manually with the required environment before involving the GUI. ### Test discovery Start the GUI and verify that: ```text Example Phone ``` appears in the device selector. ### Test sync Select the device and run: ```text Sync & Setup Device Source ``` This isolates the device integration into configuration plus one device-specific script. --- ## 29. Adding a ROM A new ROM normally needs: 1. A valid ROM source tree. 2. A recognizable ROM path. 3. A ROM configuration. 4. A compatible build command. 5. Any required synchronization logic. If the ROM has unique settings, put them in: ```text /rom.conf ``` rather than modifying the global: ```text configs/rom.conf ``` If it needs a unique build command, add the command to: ```text configs/rom_build_commands.conf ``` and implement the command behavior in: ```text scripts/build_options/rom_build_commands.sh ``` --- ## 30. Adding a Build Command There are two parts. ### Part 1 — GUI selection Add the command name to: ```text configs/rom_build_commands.conf ``` For example: ```text Aosp ``` ### Part 2 — command behavior Add a branch to: ```text rom_build_commands() ``` For example: ```bash elif [[ $BUILD_COMMAND == "aosp" ]]; then LUNCH_COMMAND="${ROM_BUILD_NAME}_${DEVICE_NAME}-${ROM_TARGET_RELEASE}-${BUILD_VARIANT}" ROM_BUILD_COMMAND="m" export LUNCH_COMMAND export ROM_BUILD_COMMAND ``` Then run: ```bash bash -n scripts/build_options/rom_build_commands.sh ``` before testing the GUI. --- ## 31. Adding a Configuration Variable Before adding a new variable, identify its scope. ### Device scope ```text configs/devices/.conf ``` Use for: ```text SOC codename model device-specific paths device-specific flags ``` ### ROM scope ```text rom.conf ``` Use for: ```text ROM name ROM build metadata ROM default command ROM manifest ROM release metadata ``` ### Application-wide setup ```text configs/a_team_setup.conf ``` Use for values shared across projects. ### Upload services ```text configs/upload_services.conf ``` Use for upload-service configuration. Keeping variable scope correct prevents device-specific details from leaking into ROM-wide configuration. --- ## 32. Debugging Strategy When something fails, isolate the layer. ### GUI problem Check: ```text gui.py builder/*.py ``` ### Configuration problem Check: ```text configs/ profiles/ ``` ### Sync problem Run: ```text scripts/sync.sh ``` directly. ### Device problem Run the device-specific script directly. ### Build problem Run: ```text scripts/build.sh ``` directly with the required environment. ### Updater problem Run: ```text scripts/updater.sh ``` directly and inspect: ```text ::PROGRESS:: ::STATUS:: ``` output. This approach avoids changing GUI code to solve a shell or Android-source problem. --- ## 33. Bash Validation Before committing a shell change: ```bash bash -n scripts/build.sh bash -n scripts/sync.sh bash -n scripts/gapps_sync.sh bash -n scripts/updater.sh ``` For the command-selection function: ```bash bash -n scripts/build_options/rom_build_commands.sh ``` Syntax validation does not prove that an Android build will succeed, but it catches malformed shell syntax before a full build. --- ## 34. Python Validation For Python changes: ```bash python3 -m py_compile gui.py ``` and for backend modules: ```bash python3 -m py_compile builder/*.py ``` For GTK changes, syntax validation is not enough. The affected UI path should also be exercised in an environment containing: ```text gi Gtk 3 VTE ``` because GTK errors commonly occur during widget creation or signal execution rather than Python parsing. --- ## 35. Preserving Executable Permissions The application contains executable shell scripts. Important files include: ```text scripts/*.sh scripts/build_options/*.sh scripts/devices_sync/*.sh ``` The updater is one example where executable permissions matter because the Python updater launches: ```text scripts/updater.sh ``` directly. When packaging a release, preserve executable mode, normally: ```text 0755 ``` for shell scripts and the executable application entry point where applicable. A ZIP process that strips Unix permissions can cause: ```text PermissionError: [Errno 13] Permission denied ``` even when the script contents themselves are correct. --- ## 36. UI Extension Pattern For a new button: 1. Add a width constant if its width should be configurable. 2. Create the GTK button. 3. Apply the shared sizing/alignment helper. 4. Connect its callback. 5. Put the actual operation in an appropriate backend or script. For example: ```python MY_BUTTON_WIDTH = 140 ``` then: ```python set_button_width( my_button, MY_BUTTON_WIDTH ) ``` This keeps layout changes localized. --- ## 37. UI Layout Maintenance When adjusting spacing: - Change the corresponding named constant. - Avoid replacing unrelated margins. - Keep the existing alignment model. - Do not duplicate spacing constants for the same visual relationship. - Verify the neighboring controls after a change. The current UI intentionally exposes independent spacing values for sections that need independent tuning. --- ## 38. Recommended Development Workflow For a new feature: ### Step 1 — Identify the layer Decide whether the feature belongs in: ```text GUI backend config script ``` ### Step 2 — Find the existing path Reuse the existing action/config/script architecture where possible. ### Step 3 — Make the smallest change Avoid changing unrelated layout or configuration code. ### Step 4 — Validate syntax Run Python or Bash syntax checks. ### Step 5 — Exercise the affected operation Do not stop at syntax validation. ### Step 6 — Verify packaging Ensure scripts retain executable permissions. ### Step 7 — Update documentation Update `README.md` for user-visible functionality and `README-TECHNICAL.md` for implementation details. --- ## 39. Documentation Boundary `README.md` should answer: > What does the application do, how do I run it, and how do I configure it? `README-TECHNICAL.md` should answer: > How does it work, where is the code, how do the components communicate, and how do I extend or debug it? Avoid duplicating every implementation detail in the normal README. The technical document should be detailed where implementation knowledge matters, but should remain organized around the application's actual architecture and workflows. --- ## 40. Current Extension Points The cleanest existing extension points are: ```text configs/devices/ Add devices configs/rom.conf Add ROM defaults /rom.conf Add ROM-local configuration configs/rom_build_commands.conf Add build command choices scripts/devices_sync/ Add device-specific sync logic scripts/build_options/ Add build-option behavior scripts/ Add reusable workflow operations builder/ Add reusable Python-side functionality gui.py Add/modify user interface ``` When possible, use these extension points instead of introducing special-case logic into unrelated components.