> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/zwc456baby/ScrcpyForAndroid/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture Overview

> Understanding the two-module architecture of Scrcpy for Android and how client-server communication works

## Project Structure

Scrcpy for Android is built with a two-module Gradle architecture that separates client and server responsibilities:

```
scrcpy-for-android/
├── app/              # Client module (Android UI application)
├── server/           # Server module (Screen capture service)
├── build.gradle      # Root build configuration
└── settings.gradle   # Module configuration
```

### Module Configuration

The project uses Gradle's multi-module setup defined in `settings.gradle`:

```gradle theme={null}
include ':server', ':app'
```

<Note>
  The client module depends on the server module. During build, the server APK is packaged as `scrcpy-server.jar` and embedded into the client app's assets.
</Note>

## Build System

### Root Configuration

The root `build.gradle` configures common settings for all modules:

```gradle theme={null}
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:8.0.0'
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url "https://jitpack.io" }
    }
}
```

### Client Module (app/)

* **Package**: `org.client.scrcpy`
* **Min SDK**: 21 (Android 5.0)
* **Target SDK**: 31 (Android 12)
* **Build dependency**: Automatically builds and packages the server module

Key build configuration from `app/build.gradle:49-54`:

```gradle theme={null}
tasks.whenTaskAdded { task ->
    def buildType = gradle.startParameter.taskNames.any { 
        it.endsWith('Release') } ? 'Release' : 'Debug'
    
    task.dependsOn ":server:assemble${buildType}"
    task.dependsOn ":server:copyServer"
}
```

### Server Module (server/)

* **Package**: `org.server.scrcpy`
* **Output**: APK renamed to `scrcpy-server.jar`
* **Copied to**: `app/src/main/assets/`

The server module includes a custom Gradle task that packages the built APK:

```gradle theme={null}
tasks.register('copyServer', Copy) {
    // Copies server APK to client assets as scrcpy-server.jar
    rename { fileName -> 'scrcpy-server.jar' }
}
```

## Client-Server Communication Protocol

Scrcpy for Android uses a local TCP socket-based protocol for bidirectional communication between the client and server.

### Connection Flow

<Steps>
  <Step title="ADB Connection">
    Client establishes ADB connection to remote device using `SendCommands.java`
  </Step>

  <Step title="Server Deployment">
    Server JAR is pushed to `/data/local/tmp/scrcpy-server.jar` on the remote device
  </Step>

  <Step title="Port Forwarding">
    ADB forwards local port 7008 to remote port 7007: `adb forward tcp:7008 tcp:7007`
  </Step>

  <Step title="Server Launch">
    Server process starts on remote device via `app_process`
  </Step>

  <Step title="Socket Connection">
    Client connects to `127.0.0.1:7008`, server listens on port 7007
  </Step>
</Steps>

### Data Streams

The protocol supports two types of data streams:

#### Downstream (Server → Client)

1. **Device Resolution** (16 bytes): Initial handshake sends width and height
2. **Video Packets**: H.264 encoded video frames with metadata
3. **Audio Packets**: AAC encoded audio frames with metadata

Packet structure from `model/MediaPacket.java`:

```java theme={null}
// Packet Header
[Type: 1 byte][Flag: 1 byte][Timestamp: 8 bytes][Data Length: 4 bytes][Data: N bytes]
```

#### Upstream (Client → Server)

**Touch Events** (20 bytes per event):

```java theme={null}
[Action: 4 bytes][Button: 4 bytes][X: 4 bytes][Y: 4 bytes][PointerID: 4 bytes]
```

**Key Events** (4 bytes):

```java theme={null}
[KeyCode: 4 bytes]
```

### Connection Code Example

From `Scrcpy.java:227-290`, the connection establishment:

```java theme={null}
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), 5000);

dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());

// Read device resolution (16 bytes)
byte[] buf = new byte[16];
dataInputStream.read(buf, 0, 16);
for (int i = 0; i < remote_dev_resolution.length; i++) {
    remote_dev_resolution[i] = bytesToInt(buf, i * 4);
}
```

## Development Workflow

### Building the Project

```bash theme={null}
# Build debug version
./gradlew assembleDebug

# Build release version
./gradlew assembleRelease
```

The build process automatically:

1. Compiles the server module
2. Packages server APK as JAR
3. Copies JAR to client assets
4. Builds the client APK with embedded server

### Server Deployment

When the client app connects to a remote device (`MainActivity.java:746-769`):

1. Extracts `scrcpy-server.jar` from assets
2. Writes to local storage: `context.getExternalFilesDir("scrcpy")`
3. Pushes to remote device via ADB
4. Executes with `app_process`:

```bash theme={null}
CLASSPATH=/data/local/tmp/scrcpy-server.jar \
app_process / org.server.scrcpy.Server /<ip> <size> <bitrate>
```

### Code Organization

<CardGroup cols={2}>
  <Card title="Client Module" icon="mobile">
    * UI and lifecycle management
    * Video/audio decoding
    * Input event handling
    * ADB communication
  </Card>

  <Card title="Server Module" icon="server">
    * Screen capture
    * Video/audio encoding
    * Input event injection
    * System service wrappers
  </Card>
</CardGroup>

## Key Design Patterns

### Service-Based Architecture

The client uses an Android Service (`Scrcpy.java`) for background streaming, ensuring continuity when the activity is paused.

### Asynchronous Processing

Both encoding (server) and decoding (client) use worker threads to prevent blocking the main thread:

* `VideoDecoder.Worker` - Client-side decoding thread
* `AudioDecoder.Worker` - Client-side audio playback thread
* `ScreenEncoder` - Server-side video encoding
* `AudioEncoder.EncoderCallback` - Server-side audio encoding

### Resource Cleanup

Server auto-deletes JAR on startup (`Server.java:91-92`):

```java theme={null}
Process cmd = Runtime.getRuntime().exec(
    "rm /data/local/tmp/scrcpy-server.jar");
cmd.waitFor();
```

This prevents stale server versions from persisting.

## Next Steps

<CardGroup cols={2}>
  <Card title="Client Module Deep Dive" icon="code" href="/development/client-module">
    Explore MainActivity, decoders, and input handling
  </Card>

  <Card title="Server Module Deep Dive" icon="terminal" href="/development/server-module">
    Learn about encoders, capture, and event injection
  </Card>
</CardGroup>
