aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/res
diff options
context:
space:
mode:
authorLena <lena@omega>2026-01-01 00:00:00 +0000
committerLena <lena@omega>2026-06-24 22:14:50 +0300
commiteb0c8951196c637e44daf3c0617b131b997d5d2c (patch)
tree2f83b6a41cee745467e53fc401942b82cea286ea /app/src/main/res
downloadscrcpy-android-0.1.tar.gz
scrcpy-android: mirror an Android device over wireless ADB0.1
Native Java app for Android 12+ that mirrors another Android device over wireless ADB, forwarding video, audio, touch input, and clipboard. Bundles a pinned scrcpy-server.jar and the vendored libadb-android stack. Supports h264/h265/av1 video and raw/opus audio with in-app codec selection. No NDK, no Kotlin. Includes JVM unit tests and a Docker-based emulator e2e rig.
Diffstat (limited to 'app/src/main/res')
-rw-r--r--app/src/main/res/drawable/bg_card.xml8
-rw-r--r--app/src/main/res/drawable/bg_field.xml18
-rw-r--r--app/src/main/res/drawable/bg_status_pill.xml7
-rw-r--r--app/src/main/res/drawable/btn_primary.xml11
-rw-r--r--app/src/main/res/drawable/btn_secondary.xml12
-rw-r--r--app/src/main/res/drawable/ic_device.xml14
-rw-r--r--app/src/main/res/drawable/ic_launcher_background.xml7
-rw-r--r--app/src/main/res/drawable/ic_launcher_foreground.xml52
-rw-r--r--app/src/main/res/drawable/ic_notification.xml21
-rw-r--r--app/src/main/res/drawable/ic_settings.xml12
-rw-r--r--app/src/main/res/layout/device_row.xml28
-rw-r--r--app/src/main/res/layout/main.xml181
-rw-r--r--app/src/main/res/layout/mirror.xml67
-rw-r--r--app/src/main/res/layout/settings.xml294
-rw-r--r--app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml6
-rw-r--r--app/src/main/res/values/colors.xml16
-rw-r--r--app/src/main/res/values/dimens.xml17
-rw-r--r--app/src/main/res/values/ids.xml10
-rw-r--r--app/src/main/res/values/strings.xml36
-rw-r--r--app/src/main/res/values/styles.xml73
-rw-r--r--app/src/main/res/values/themes.xml32
21 files changed, 922 insertions, 0 deletions
diff --git a/app/src/main/res/drawable/bg_card.xml b/app/src/main/res/drawable/bg_card.xml
new file mode 100644
index 0000000..17a0cfa
--- /dev/null
+++ b/app/src/main/res/drawable/bg_card.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Rounded surface panel used to group related controls. -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/surface"/>
+ <stroke android:width="1dp" android:color="@color/stroke"/>
+ <corners android:radius="@dimen/card_radius"/>
+</shape>
diff --git a/app/src/main/res/drawable/bg_field.xml b/app/src/main/res/drawable/bg_field.xml
new file mode 100644
index 0000000..e656ad4
--- /dev/null
+++ b/app/src/main/res/drawable/bg_field.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Text-field box. Accent border when focused, neutral otherwise. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true">
+ <shape android:shape="rectangle">
+ <solid android:color="@color/surface_alt"/>
+ <stroke android:width="2dp" android:color="@color/accent"/>
+ <corners android:radius="@dimen/field_radius"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@color/surface_alt"/>
+ <stroke android:width="1dp" android:color="@color/stroke"/>
+ <corners android:radius="@dimen/field_radius"/>
+ </shape>
+ </item>
+</selector>
diff --git a/app/src/main/res/drawable/bg_status_pill.xml b/app/src/main/res/drawable/bg_status_pill.xml
new file mode 100644
index 0000000..ae91094
--- /dev/null
+++ b/app/src/main/res/drawable/bg_status_pill.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Floating scrim pill behind the Mirror status text and buttons. -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/status_scrim"/>
+ <corners android:radius="@dimen/button_radius"/>
+</shape>
diff --git a/app/src/main/res/drawable/btn_primary.xml b/app/src/main/res/drawable/btn_primary.xml
new file mode 100644
index 0000000..75aab01
--- /dev/null
+++ b/app/src/main/res/drawable/btn_primary.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Filled accent button with the platform press ripple on top. -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?android:attr/colorControlHighlight">
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@color/accent"/>
+ <corners android:radius="@dimen/button_radius"/>
+ </shape>
+ </item>
+</ripple>
diff --git a/app/src/main/res/drawable/btn_secondary.xml b/app/src/main/res/drawable/btn_secondary.xml
new file mode 100644
index 0000000..2c3a618
--- /dev/null
+++ b/app/src/main/res/drawable/btn_secondary.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Outlined accent button (transparent fill, accent border). -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?android:attr/colorControlHighlight">
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ <stroke android:width="1dp" android:color="@color/accent"/>
+ <corners android:radius="@dimen/button_radius"/>
+ </shape>
+ </item>
+</ripple>
diff --git a/app/src/main/res/drawable/ic_device.xml b/app/src/main/res/drawable/ic_device.xml
new file mode 100644
index 0000000..f12a226
--- /dev/null
+++ b/app/src/main/res/drawable/ic_device.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Small phone outline used as the leading glyph on saved-device rows. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:strokeColor="@color/accent"
+ android:strokeWidth="2"
+ android:strokeLineJoin="round"
+ android:fillColor="#00000000"
+ android:pathData="M8,3 H16 A2,2 0 0 1 18,5 V19 A2,2 0 0 1 16,21 H8 A2,2 0 0 1 6,19 V5 A2,2 0 0 1 8,3 Z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..e26af1f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Dark CRT-terminal blue. Plain solid colour so the adaptive icon
+ reads cleanly under any launcher crop (circle, squircle, square). -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="#0E1E28"/>
+</shape>
diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 0000000..e5b7400
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Foreground: a fresh take on wireless screen mirroring.
+ 1. A small phone (source) and a larger phone (target display).
+ 2. Cyan wireless arcs rising from the small phone toward the large
+ one - the wireless ADB link / casting direction.
+ 3. A play triangle on the large screen - references scrcpy's
+ upstream identity ("playing what the device is showing").
+ Geometry mirrors the AI-generated reference 1:1. The arcs carry the
+ one accent colour; everything else is the light foreground tone.
+ For the Android 13+ themed (monochrome) icon the same drawable is
+ reused: the system tints by coverage, so the colours here are
+ irrelevant in that mode. Adaptive viewport is 108x108; all content
+ stays inside the inner safe zone. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+
+ <!-- Phone outlines (source 20x34, target 28x50), stroke only. -->
+ <path
+ android:strokeColor="#E8E8E8"
+ android:strokeWidth="3"
+ android:strokeLineJoin="round"
+ android:fillColor="#00000000"
+ android:pathData="M57,29 H75 A5,5 0 0 1 80,34 V74 A5,5 0 0 1 75,79 H57 A5,5 0 0 1 52,74 V34 A5,5 0 0 1 57,29 Z
+ M30,47 H42 A4,4 0 0 1 46,51 V77 A4,4 0 0 1 42,81 H30 A4,4 0 0 1 26,77 V51 A4,4 0 0 1 30,47 Z"/>
+
+ <!-- Speaker slits and home indicators on both phones. -->
+ <path
+ android:strokeColor="#E8E8E8"
+ android:strokeWidth="2"
+ android:strokeLineCap="round"
+ android:fillColor="#00000000"
+ android:pathData="M62,35 H70 M61,74 H71 M32,52 H40 M32,76 H40"/>
+
+ <!-- Play triangle, filled, inside the large phone screen. -->
+ <path
+ android:fillColor="#E8E8E8"
+ android:pathData="M61,46 L61,62 L74,54 Z"/>
+
+ <!-- Wireless arcs: three concentric quarter-arcs centred at (40,48),
+ sweeping from north to east so they fan up-right from the small
+ phone toward the large one. -->
+ <path
+ android:strokeColor="#3FD0D6"
+ android:strokeWidth="2.5"
+ android:strokeLineCap="round"
+ android:fillColor="#00000000"
+ android:pathData="M40,43 A5,5 0 0 1 45,48 M40,39.5 A8.5,8.5 0 0 1 48.5,48 M40,36 A12,12 0 0 1 52,48"/>
+
+</vector>
diff --git a/app/src/main/res/drawable/ic_notification.xml b/app/src/main/res/drawable/ic_notification.xml
new file mode 100644
index 0000000..f592b9d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_notification.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Status-bar notification icon: white-on-transparent silhouette (the
+ launcher mipmap is the wrong shape and colour for a small icon). The
+ system tints it. Phone outline with a play triangle, matching the
+ app's visual identity. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="#FFFFFF">
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="1.8"
+ android:strokeLineJoin="round"
+ android:fillColor="#00000000"
+ android:pathData="M7,2 H17 A2,2 0 0 1 19,4 V20 A2,2 0 0 1 17,22 H7 A2,2 0 0 1 5,20 V4 A2,2 0 0 1 7,2 Z"/>
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M10,8 L10,16 L16,12 Z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml
new file mode 100644
index 0000000..696f6c2
--- /dev/null
+++ b/app/src/main/res/drawable/ic_settings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Gear glyph for the Settings action in the Main header. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="@color/on_surface_muted">
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94l-0.36,-2.54c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41l-0.36,2.54c-0.59,0.24 -1.13,0.57 -1.62,0.94l-2.39,-0.96c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.82,11.69 4.82,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
+</vector>
diff --git a/app/src/main/res/layout/device_row.xml b/app/src/main/res/layout/device_row.xml
new file mode 100644
index 0000000..f06ab20
--- /dev/null
+++ b/app/src/main/res/layout/device_row.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Saved-device row: phone glyph + "host:port" label, with the platform
+ touch ripple. Bound by an ArrayAdapter via R.id.device_label. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:minHeight="56dp"
+ android:paddingHorizontal="@dimen/space_sm"
+ android:paddingVertical="@dimen/space_md"
+ android:background="?android:attr/selectableItemBackground">
+
+ <ImageView
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:src="@drawable/ic_device"
+ android:contentDescription="@null"/>
+
+ <TextView
+ android:id="@+id/device_label"
+ style="@style/DeviceLabel"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginStart="@dimen/space_md"/>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml
new file mode 100644
index 0000000..acd4a3c
--- /dev/null
+++ b/app/src/main/res/layout/main.xml
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="@dimen/space_lg">
+
+ <!-- Header: app glyph + name, Settings on the right. -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:layout_marginBottom="@dimen/space_lg">
+
+ <ImageView
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:src="@drawable/ic_launcher_foreground"
+ android:scaleType="fitCenter"
+ android:contentDescription="@null"/>
+
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginStart="@dimen/space_sm"
+ android:text="@string/app_name"
+ android:textColor="@color/on_surface"
+ android:textSize="22sp"
+ android:textStyle="bold"/>
+
+ <ImageButton
+ android:id="@+id/settings"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:src="@drawable/ic_settings"
+ android:scaleType="centerInside"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/settings"/>
+
+ </LinearLayout>
+
+ <!-- Pairing form. Fields are grouped and labelled by where their
+ value comes from on the target's Wireless debugging screen. -->
+ <LinearLayout
+ style="@style/Card"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/pair_a_device"/>
+
+ <TextView
+ style="@style/Caption"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/pair_help"/>
+
+ <TextView
+ style="@style/FieldLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/label_host"/>
+
+ <EditText
+ android:id="@+id/host"
+ style="@style/Field"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/host_hint"
+ android:inputType="text"
+ android:autofillHints="postalAddress"/>
+
+ <TextView
+ style="@style/FieldLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/label_pairing"/>
+
+ <TextView
+ style="@style/Caption"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/sub_pairing"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginTop="@dimen/space_xs">
+
+ <EditText
+ android:id="@+id/pair_port"
+ style="@style/Field"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginEnd="@dimen/space_sm"
+ android:hint="@string/pair_port_hint"
+ android:inputType="number"
+ android:autofillHints="off"/>
+
+ <EditText
+ android:id="@+id/pair_code"
+ style="@style/Field"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:hint="@string/pair_code_hint"
+ android:inputType="numberPassword"
+ android:maxLength="6"
+ android:autofillHints="off"/>
+
+ </LinearLayout>
+
+ <TextView
+ style="@style/FieldLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/label_connect"/>
+
+ <TextView
+ style="@style/Caption"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/sub_connect"/>
+
+ <EditText
+ android:id="@+id/connect_port"
+ style="@style/Field"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/space_xs"
+ android:hint="@string/connect_port_hint"
+ android:inputType="number"
+ android:autofillHints="off"/>
+
+ <Button
+ android:id="@+id/pair"
+ style="@style/Button.Primary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/space_lg"
+ android:text="@string/pair_and_save"/>
+
+ </LinearLayout>
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/saved_devices"/>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+
+ <ListView
+ android:id="@+id/devices"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:divider="@color/stroke"
+ android:dividerHeight="1dp"/>
+
+ <TextView
+ android:id="@+id/devices_empty"
+ style="@style/Note"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:paddingTop="@dimen/space_xl"
+ android:text="@string/no_devices_yet"/>
+
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/mirror.xml b/app/src/main/res/layout/mirror.xml
new file mode 100644
index 0000000..cf24e11
--- /dev/null
+++ b/app/src/main/res/layout/mirror.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Release Mirror layout: SurfaceView for the video pipeline plus a
+ floating top status pill with Record and a Reconnect button (visible
+ only when the session is in DISCONNECTED state). The debug layout
+ under src/debug/res/layout/mirror.xml shadows this with a TextureView
+ and extra stats overlay used by the e2e screen capture. -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#000000">
+
+ <SurfaceView
+ android:id="@+id/surface"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"/>
+
+ <LinearLayout
+ android:id="@+id/status_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:layout_margin="@dimen/space_sm"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:paddingHorizontal="@dimen/space_md"
+ android:paddingVertical="@dimen/space_sm"
+ android:background="@drawable/bg_status_pill">
+
+ <TextView
+ android:id="@+id/status_text"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:textColor="#ffffff"
+ android:textSize="14sp"
+ android:fontFamily="monospace"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:text="@string/connecting"/>
+
+ <Button
+ android:id="@+id/record"
+ style="@style/Button.Secondary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/space_sm"
+ android:minHeight="0dp"
+ android:paddingHorizontal="@dimen/space_md"
+ android:paddingVertical="@dimen/space_xs"
+ android:text="@string/record"/>
+
+ <Button
+ android:id="@+id/reconnect"
+ style="@style/Button.Secondary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/space_sm"
+ android:minHeight="0dp"
+ android:paddingHorizontal="@dimen/space_md"
+ android:paddingVertical="@dimen/space_xs"
+ android:text="@string/reconnect"
+ android:visibility="gone"/>
+
+ </LinearLayout>
+
+</FrameLayout>
diff --git a/app/src/main/res/layout/settings.xml b/app/src/main/res/layout/settings.xml
new file mode 100644
index 0000000..5d4e450
--- /dev/null
+++ b/app/src/main/res/layout/settings.xml
@@ -0,0 +1,294 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="@dimen/space_lg">
+
+ <TextView
+ style="@style/Note"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/space_lg"
+ android:text="@string/settings_apply_on_reconnect"/>
+
+ <LinearLayout
+ style="@style/Card"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/video_codec"/>
+
+ <RadioGroup
+ android:id="@+id/video_codec"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <RadioButton
+ android:id="@+id/video_h264"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="H.264 (default)"/>
+
+ <RadioButton
+ android:id="@+id/video_h265"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="H.265"/>
+
+ <RadioButton
+ android:id="@+id/video_av1"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="AV1 (requires target Android 14+)"/>
+
+ </RadioGroup>
+
+ </LinearLayout>
+
+ <LinearLayout
+ style="@style/Card"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/audio_codec"/>
+
+ <RadioGroup
+ android:id="@+id/audio_codec"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <RadioButton
+ android:id="@+id/audio_raw"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Raw PCM (1.5 Mbps, default)"/>
+
+ <RadioButton
+ android:id="@+id/audio_opus"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Opus (~128 kbps)"/>
+
+ </RadioGroup>
+
+ </LinearLayout>
+
+ <LinearLayout
+ style="@style/Card"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/max_size"/>
+
+ <RadioGroup
+ android:id="@+id/max_size"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <RadioButton
+ android:id="@+id/max_size_0"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Original (default)"/>
+
+ <RadioButton
+ android:id="@+id/max_size_480"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="480"/>
+
+ <RadioButton
+ android:id="@+id/max_size_720"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="720"/>
+
+ <RadioButton
+ android:id="@+id/max_size_1080"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="1080"/>
+
+ <RadioButton
+ android:id="@+id/max_size_1440"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="1440"/>
+
+ <RadioButton
+ android:id="@+id/max_size_2160"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="2160"/>
+
+ </RadioGroup>
+
+ </LinearLayout>
+
+ <LinearLayout
+ style="@style/Card"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/video_bit_rate"/>
+
+ <RadioGroup
+ android:id="@+id/video_bit_rate"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <RadioButton
+ android:id="@+id/bit_rate_1m"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="1 Mbps"/>
+
+ <RadioButton
+ android:id="@+id/bit_rate_2m"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="2 Mbps"/>
+
+ <RadioButton
+ android:id="@+id/bit_rate_4m"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="4 Mbps"/>
+
+ <RadioButton
+ android:id="@+id/bit_rate_8m"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="8 Mbps (default)"/>
+
+ <RadioButton
+ android:id="@+id/bit_rate_16m"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="16 Mbps"/>
+
+ </RadioGroup>
+
+ </LinearLayout>
+
+ <LinearLayout
+ style="@style/Card"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/max_fps"/>
+
+ <RadioGroup
+ android:id="@+id/max_fps"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <RadioButton
+ android:id="@+id/max_fps_0"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Unlimited (default)"/>
+
+ <RadioButton
+ android:id="@+id/max_fps_30"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="30"/>
+
+ <RadioButton
+ android:id="@+id/max_fps_60"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="60"/>
+
+ <RadioButton
+ android:id="@+id/max_fps_90"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="90"/>
+
+ <RadioButton
+ android:id="@+id/max_fps_120"
+ style="@style/RadioOption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="120"/>
+
+ </RadioGroup>
+
+ </LinearLayout>
+
+ <LinearLayout
+ style="@style/Card"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="0dp">
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/display"/>
+
+ <CheckBox
+ android:id="@+id/show_status_bar"
+ style="@style/RadioOption"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/show_status_bar"/>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..93542a7
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background"/>
+ <foreground android:drawable="@drawable/ic_launcher_foreground"/>
+ <monochrome android:drawable="@drawable/ic_launcher_foreground"/>
+</adaptive-icon>
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..7e9fa9b
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Dark palette built around the launcher icon's CRT-blue. The light
+ foreground (#E8E8E8) matches the icon; the cyan/teal accent tints
+ interactive controls. Hex values live here only; layouts reference
+ them by name. -->
+<resources>
+ <color name="bg">#0B1620</color>
+ <color name="surface">#14242E</color>
+ <color name="surface_alt">#0E1E28</color>
+ <color name="stroke">#283D49</color>
+ <color name="accent">#3FD0D6</color>
+ <color name="on_surface">#E8E8E8</color>
+ <color name="on_surface_muted">#8AA0AB</color>
+ <color name="on_accent">#04222B</color>
+ <color name="status_scrim">#B3000000</color>
+</resources>
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..0ec4c88
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Single spacing scale and corner radii, referenced everywhere so the
+ layout rhythm stays consistent. -->
+<resources>
+ <dimen name="space_xs">4dp</dimen>
+ <dimen name="space_sm">8dp</dimen>
+ <dimen name="space_md">12dp</dimen>
+ <dimen name="space_lg">16dp</dimen>
+ <dimen name="space_xl">24dp</dimen>
+
+ <dimen name="card_radius">14dp</dimen>
+ <dimen name="field_radius">8dp</dimen>
+ <dimen name="button_radius">10dp</dimen>
+
+ <dimen name="card_padding">16dp</dimen>
+ <dimen name="touch_min">48dp</dimen>
+</resources>
diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml
new file mode 100644
index 0000000..f551102
--- /dev/null
+++ b/app/src/main/res/values/ids.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- IDs referenced from Mirror.java that live only in the debug
+ layout (src/debug/res/layout/mirror.xml). Declaring them here
+ means R.id.* is stable across both build types; findViewById
+ returns null in release where the views are absent. -->
+<resources>
+ <item name="overlay_target" type="id"/>
+ <item name="overlay_stats" type="id"/>
+ <item name="overlay_event" type="id"/>
+</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..a9a552c
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">scrcpy</string>
+ <string name="host_hint">192.168.1.42</string>
+ <string name="pair_port_hint">37123</string>
+ <string name="pair_code_hint">6 digits</string>
+ <string name="connect_port_hint">41234</string>
+ <string name="pair_help">On the target: Settings &gt; Developer options &gt; Wireless debugging</string>
+ <string name="label_host">Host / IP address</string>
+ <string name="label_pairing">Pairing port and code</string>
+ <string name="sub_pairing">From the “Pair device with pairing code” dialog</string>
+ <string name="label_connect">Connection port</string>
+ <string name="sub_connect">Shown on the Wireless debugging screen</string>
+ <string name="pair_and_save">Pair and save</string>
+ <string name="pair_a_device">Pair a device</string>
+ <string name="saved_devices">Saved devices</string>
+ <string name="notif_session_active">Mirroring active</string>
+ <string name="settings">Settings</string>
+ <string name="video_codec">Video codec</string>
+ <string name="audio_codec">Audio codec</string>
+ <string name="forget_device">Forget device?</string>
+ <string name="max_size">Max size (long edge, px)</string>
+ <string name="video_bit_rate">Video bit rate</string>
+ <string name="max_fps">Max fps</string>
+ <string name="reconnect">Reconnect</string>
+ <string name="connecting">connecting…</string>
+ <string name="disconnected">disconnected</string>
+ <string name="record">Record</string>
+ <string name="record_on">Stop recording</string>
+ <string name="hint_long_press_back">Long-press Back to send it to the target device.</string>
+ <string name="pairing">Pairing…</string>
+ <string name="settings_apply_on_reconnect">Changes apply on the next connection.</string>
+ <string name="display">Display</string>
+ <string name="show_status_bar">Show status bar (IP, resolution, Record) while mirroring</string>
+ <string name="no_devices_yet">No devices paired yet - fill the fields above and tap Pair.</string>
+</resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..d0b07ac
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Reusable widget styles. Applied per-widget via style="@style/..." so
+ behaviour stays explicit and visible at the call site. -->
+<resources>
+ <style name="Card">
+ <item name="android:orientation">vertical</item>
+ <item name="android:background">@drawable/bg_card</item>
+ <item name="android:padding">@dimen/card_padding</item>
+ <item name="android:layout_marginBottom">@dimen/space_lg</item>
+ </style>
+
+ <style name="SectionHeader">
+ <item name="android:textColor">@color/on_surface</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:paddingBottom">@dimen/space_sm</item>
+ </style>
+
+ <style name="Field" parent="@android:style/Widget.Material.EditText">
+ <item name="android:background">@drawable/bg_field</item>
+ <item name="android:textColor">@color/on_surface</item>
+ <item name="android:textColorHint">@color/on_surface_muted</item>
+ <item name="android:paddingHorizontal">@dimen/space_md</item>
+ <item name="android:paddingVertical">@dimen/space_md</item>
+ <item name="android:minHeight">@dimen/touch_min</item>
+ </style>
+
+ <style name="Button.Primary" parent="@android:style/Widget.Material.Button">
+ <item name="android:background">@drawable/btn_primary</item>
+ <item name="android:textColor">@color/on_accent</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:textAllCaps">false</item>
+ <item name="android:minHeight">@dimen/touch_min</item>
+ </style>
+
+ <style name="Button.Secondary" parent="@android:style/Widget.Material.Button">
+ <item name="android:background">@drawable/btn_secondary</item>
+ <item name="android:textColor">@color/accent</item>
+ <item name="android:textAllCaps">false</item>
+ <item name="android:minWidth">0dp</item>
+ </style>
+
+ <style name="RadioOption">
+ <item name="android:textColor">@color/on_surface</item>
+ <item name="android:textSize">15sp</item>
+ <item name="android:paddingTop">@dimen/space_sm</item>
+ <item name="android:paddingBottom">@dimen/space_sm</item>
+ <item name="android:minHeight">44dp</item>
+ </style>
+
+ <style name="Note">
+ <item name="android:textStyle">italic</item>
+ <item name="android:textColor">@color/on_surface_muted</item>
+ </style>
+
+ <style name="FieldLabel">
+ <item name="android:textColor">@color/on_surface</item>
+ <item name="android:textSize">13sp</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:paddingTop">@dimen/space_md</item>
+ </style>
+
+ <style name="Caption">
+ <item name="android:textColor">@color/on_surface_muted</item>
+ <item name="android:textSize">12sp</item>
+ </style>
+
+ <style name="DeviceLabel">
+ <item name="android:textColor">@color/on_surface</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:fontFamily">monospace</item>
+ </style>
+</resources>
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..3d702c6
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Custom theme on the platform's built-in Material theme (ships with
+ Android, not a dependency). Setting the colour attributes makes the
+ framework auto-tint EditText focus, radio buttons, checkboxes, the
+ action bar, and the cursor. NoActionBar / Fullscreen inherit the
+ same colours via dotted-name inheritance. -->
+<resources>
+ <style name="Theme.Scrcpy" parent="@android:style/Theme.Material">
+ <item name="android:colorBackground">@color/bg</item>
+ <item name="android:windowBackground">@color/bg</item>
+ <item name="android:colorPrimary">@color/surface</item>
+ <item name="android:colorPrimaryDark">@color/bg</item>
+ <item name="android:colorAccent">@color/accent</item>
+ <item name="android:textColorPrimary">@color/on_surface</item>
+ <item name="android:textColorSecondary">@color/on_surface_muted</item>
+ <item name="android:textColorHint">@color/on_surface_muted</item>
+ <item name="android:statusBarColor">@color/bg</item>
+ <item name="android:navigationBarColor">@color/bg</item>
+ </style>
+
+ <style name="Theme.Scrcpy.NoActionBar">
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowNoTitle">true</item>
+ </style>
+
+ <style name="Theme.Scrcpy.Fullscreen">
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowFullscreen">true</item>
+ <item name="android:windowBackground">@android:color/black</item>
+ </style>
+</resources>