# Universal Android Debloater Configuration System: Structure and Session Persistence

> Explore the Universal Android Debloater Next Generation's TOML configuration system. Learn how it structures UI settings and device toggles, ensuring session persistence with automatic serialization.

- Repository: [Universal-Debloater-Alliance/universal-android-debloater-next-generation](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation)
- Tags: internals
- Published: 2026-06-20

---

**The Universal Android Debloater Next Generation (UAD-ng) persists user preferences across sessions using a TOML-based configuration system that separates global UI settings from device-specific toggles, implementing automatic serialization through the `Config` struct in [`crates/uad-core/src/config.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/config.rs).**

The Universal Android Debloater Next Generation (UAD-ng) relies on a robust Rust-based configuration system to maintain user preferences between application launches. This open-source Android debloating tool stores settings in a structured TOML file that survives OS reboots and binary updates. Understanding how the **configuration system** structures and persists data is essential for contributors and advanced users who need to customize the tool's behavior or trace device-specific settings.

## Core Configuration Architecture

### The Config Struct Hierarchy

At the heart of the system lies the **`Config`** struct defined in [`crates/uad-core/src/config.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/config.rs) (lines 13-18). This struct acts as the root container with two primary fields: `general` (holding `GeneralSettings`) and `devices` (a vector of `DeviceSettings`). The hierarchical design allows the application to maintain universal UI preferences while supporting granular, per-device configurations.

### Global vs Device-Specific Settings

**`GeneralSettings`** (lines 20-25) handles application-wide values including the theme name, expert mode toggle, and backup folder path. These settings apply regardless of which Android device is connected.

**`DeviceSettings`** (lines 36-44) manages connection-specific configurations such as `disable_mode` and `multi_user_mode`. Each device entry includes a unique `device_id` for identification. Notably, the `BackupSettings` field within `DeviceSettings` carries the `#[serde(skip)]` attribute, meaning runtime backup metadata persists only in memory and never writes to disk.

## Persistence Mechanism and File Format

### TOML Storage Location

The configuration system writes data to a lazy-initialized path defined by **`CONFIG_FILE`** in [`crates/uad-core/src/config.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/config.rs) (lines 56-58). This resolves to `<CONFIG_DIR>/config.toml`, where `CONFIG_DIR` follows platform-specific user configuration directories (typically `~/.config/universal-android-debloater/` on Linux). The directory initializes at startup if absent.

### Loading Configuration on Startup

When the application launches, the GUI calls **`Config::load_configuration_file()`** (lines 79-90). This function attempts to read and deserialize the TOML file using `toml::from_str`. If the file is missing or corrupted, the method automatically generates a fresh configuration with default values and writes it to disk, ensuring the application never fails due to missing config files.

### Saving and Updating Settings

Persistence occurs through **`Config::save_device_settings()`** (lines 58-75). This method accepts updated `DeviceSettings` and `GeneralSettings`, merges them into the existing configuration structure, serializes the entire `Config` struct to TOML format, and atomically writes the content back to `CONFIG_FILE`. The UI triggers this routine immediately after any settings change, ensuring zero data loss between sessions.

## UI Integration and Settings Views

The GUI layer in [`crates/uad-gui/src/views/settings.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-gui/src/views/settings.rs) bridges user interactions with the configuration system. During initialization, `Settings::default` loads the current configuration via `load_configuration_file()` and populates the interface with stored values. When users toggle options like expert mode (handled in `handle_expert_mode`), the view updates its internal state and immediately invokes `save_device_settings()` to persist the change. This create-read-update cycle ensures the TOML file always reflects the latest user preferences.

## Working with the Configuration System

Practical code examples for interacting with the configuration layer:

Loading the entire configuration:

```rust
use uad_core::config::Config;

// Reads from ~/.config/universal-android-debloater/config.toml
let cfg = Config::load_configuration_file();
println!("Current theme: {}", cfg.general.theme);

```

Reading specific global settings:

```rust
let backup_dir = Config::load_configuration_file()
    .general
    .backup_folder;
println!("Backups stored at: {}", backup_dir.display());

```

Updating device-specific settings:

```rust
use uad_core::config::{Config, DeviceSettings, GeneralSettings};

let mut cfg = Config::load_configuration_file();

let device = DeviceSettings {
    device_id: "ABC123".into(),
    disable_mode: true,
    multi_user_mode: false,
    backup: Default::default(),
};

// Persist changes while preserving existing general settings
cfg.save_device_settings(device, cfg.general.clone());

```

## Summary

- The **configuration system** uses a hierarchical `Config` struct with separate `GeneralSettings` and `DeviceSettings` components defined in [`crates/uad-core/src/config.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/config.rs).
- All persistent data stores in a **TOML file** at `<CONFIG_DIR>/config.toml`, with `BackupSettings` explicitly excluded from serialization via `#[serde(skip)]`.
- **`load_configuration_file()`** handles automatic initialization and deserialization, while **`save_device_settings()`** manages atomic write-back operations.
- The GUI in [`crates/uad-gui/src/views/settings.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-gui/src/views/settings.rs) maintains real-time synchronization between user interface changes and disk persistence.
- Because the system uses plain TOML, configurations survive application updates and OS reboots as long as the user configuration directory remains intact.

## Frequently Asked Questions

### Where does Universal Android Debloater store its configuration file?

The application stores its configuration in a TOML file located at `<CONFIG_DIR>/config.toml`, where `CONFIG_DIR` resolves to the platform-specific user configuration directory (such as `~/.config/universal-android-debloater/` on Linux or `%APPDATA%\universal-android-debloater` on Windows). This path is defined as a lazy-static `CONFIG_FILE` constant in [`crates/uad-core/src/config.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/config.rs).

### Why are my backup settings not saving between sessions?

Backup settings use the `BackupSettings` struct which carries the `#[serde(skip)]` attribute, meaning this data is intentionally excluded from serialization. This design keeps runtime backup metadata (like available backups list and current selection) in memory only, preventing stale backup references from persisting across application restarts while keeping the configuration file focused on user preferences.

### What happens if the configuration file is deleted or corrupted?

If `Config::load_configuration_file()` fails to find the file or encounters invalid TOML syntax, it automatically generates a fresh configuration with default values and writes it to disk. This fallback mechanism ensures the application always launches successfully, using factory defaults until the user modifies settings again through the GUI.

### How does the UI ensure settings persist immediately after I change them?

The Settings view in [`crates/uad-gui/src/views/settings.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-gui/src/views/settings.rs) implements immediate persistence by calling `save_device_settings()` within every toggle handler (such as `handle_expert_mode`). After updating the in-memory state, the UI reloads the configuration file, merges the new values, and writes the updated TOML back to disk, ensuring changes survive application crashes or system restarts.