# 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_ROOT>/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::<current>::<total>
```

For example:

```text
::PROGRESS::3::5
```

represents:

```text
3 / 5
```

or:

```text
60%
```

Status messages use:

```text
::STATUS::<message>
```

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_ROOT>/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/<device>.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_ROOT>/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.
