Skip to content

Module Map and Boundaries

星冉 edited this page Jul 21, 2026 · 1 revision

Module Map and Boundaries

中文 · Architecture index

This is the canonical guide to code ownership and dependency boundaries. It consolidates the useful material from the former Architecture Principles and Directory and Boundary Rules pages. It deliberately removes file-length thresholds that were never enforced by the build or checks.

Repository boundaries

Screen-Remote/                 outer repository: wiki, scripts, and reference projects
├── Screen-Remote/             Android application subrepository
│   └── app/                   the current single application module
├── external/dadb/             local included build: ADB protocol and Android transports
└── external/wiki/             long-lived documentation

Application Kotlin code lives under Screen-Remote/app/src/main/java/com/screen/remote/android/. Native code and packaged assets live in the same module under src/main/cpp/ and src/main/assets/. external/dadb has separate ownership; the main application consumes only its public capabilities.

Application code map

Layer Current directory Owns Must not own
Assembly app Application, Activity, top-level navigation, and global assembly Protocol, transport, or decoder details
User scenarios feature Compose screens, ViewModels, screen state, and user actions Direct assembly of the ADB → server → socket → decoder path
Technical capabilities infrastructure Concrete ADB, scrcpy, media, and system-API implementations Product navigation or presentation state
Stable foundations core Domain models, persistence, design system, localization, and common rules Unstable implementation used by only one feature
System coordination service Foreground service, keep-alive behavior, and Android lifecycle coordination A second session entry point or state machine

These are code layers inside one Gradle module, not five independent build modules. Read dependency direction as “higher layers use lower-level capabilities while lower layers do not know higher-level scenarios,” not as a mechanical requirement for each directory to depend on the preceding one.

Key subdomains

  • feature/session: session list, editing, and configuration presentation.
  • feature/remote: remote screen, interaction, and user-visible runtime state.
  • feature/device: device discovery, pairing, and ADB-key UI.
  • feature/settings: application settings, logs, backup, and management entry points.
  • feature/codec: codec selection, probing, and test UI.
  • infrastructure/adb: connection, USB, mDNS, pairing, keys, and shell.
  • infrastructure/scrcpy: server, protocol, sequential socket connection, streams, control, and session runtime.
  • infrastructure/media: video and audio codecs, decoding, rendering, and playback.

Tests should mirror the ownership of the code under test. Cross-domain regression tests belong to the domain closest to the main path they verify.

Stable architecture principles

The session is the runtime boundary

The configuration snapshot, connection resources, component states, events, and cleanup responsibility of one remote-control activity should belong to the same session. SessionManager manages active sessions; concrete state and event models live under infrastructure/scrcpy/session. Do not spread mutable session facts into conflicting global state.

One formal source for each fact

Facts such as ADB availability, socket closure, and decoder failure should originate from formal state or events. Logs, monitoring, statistics, and UI consume or project those facts; they must not derive competing state machines.

Separate configuration, capability, and runtime state

  • Persisted configuration such as ScrcpyConfig expresses user intent.
  • The device capability cache represents discovered, reusable device facts.
  • ConnectionCandidate and attempt records represent strategy and results for a connection run.
  • Session state, events, and component snapshots represent what is happening in the current run.

Do not write a one-off connection result back as new configuration semantics, and do not treat a historical cache entry as proof of a current connection.

ADB and scrcpy ownership

  • ADB owns transports, authentication and pairing, connections, shell, file transfer, and generic capabilities such as forwarding.
  • scrcpy owns server deployment and startup, remote-control sockets, metadata, stream and control processing, reconnection, and cleanup.
  • scrcpy may call ADB capabilities. ADB does not depend on scrcpy and does not own remote-screen, first-frame, or decoder state.
  • Even when an ADB command performs a forward or shell action, orchestration ownership remains with scrcpy if that action exists solely to start a scrcpy session.

File and directory decisions

Add or split code according to responsibility closure and reading paths:

  1. Identify whether the code solves a user-scenario, technical-capability, stable-foundation, or system-lifecycle problem.
  2. Split same-domain collaborators when one object has independently changing responsibilities. Do not mechanically fragment a continuous main path to shorten a file.
  3. Keep screen-local components, constants, and models in their feature. Move them to core only when their semantics are stable and multiple scenarios reuse them.
  4. Add a directory only when it groups a coherent ownership set and reduces lookup cost. Avoid low-information layers such as internal/component/partial.
  5. A wrapper that only forwards a call and provides neither third-party isolation nor independent policy is not a useful abstraction.
  6. UI and ViewModels may express user intent, but infrastructure runtime orchestration owns low-level connection and cleanup.

File size is a review signal, not an architecture fact. Reviews should consider the number of responsibilities, reasons to change, information density, and navigation cost. If hard thresholds become necessary, enforce them in static checks before documenting them as rules.

New-code checklist

  • Can its owner be stated in one sentence?
  • Does a lower layer now know about an upper-layer screen or product concept?
  • Does it introduce a second configuration, connection, or session truth?
  • Does the split reduce comprehension cost instead of merely moving code?
  • Do startup, failure, cancellation, and closure remain under one resource owner?
  • Are related tests located in the same ownership domain and do they cover the key constraints?

Further reading

Clone this wiki locally