Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ jobs:
from PyInstaller.utils.hooks import collect_all;
from openadb.version import ACBRIDGE_APK_FILENAME, RELEASE_EXE_FILENAME;
assert callable(collect_all);
assert ACBRIDGE_APK_FILENAME == 'ACBridge-3.0.2.apk';
assert RELEASE_EXE_FILENAME == 'OpenADB-3.0.2.exe'"
assert ACBRIDGE_APK_FILENAME == 'ACBridge-3.0.3.apk';
assert RELEASE_EXE_FILENAME == 'OpenADB-3.0.3.exe'"

- name: Check repository privacy guardrails
shell: pwsh
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/device-lab.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ jobs:
$null -eq $json -or
$json.schema -ne "openadb.device-lab.v1" -or
$json.product.name -ne "OpenADB" -or
$json.product.version -ne "3.0.2" -or
$json.product.version -ne "3.0.3" -or
$json.product.source_commit -ne $expectedSourceCommit -or
[string]::IsNullOrWhiteSpace([string]$json.environment.os) -or
[string]::IsNullOrWhiteSpace([string]$json.environment.release) -or
Expand Down
48 changes: 24 additions & 24 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
name: OpenADB 3.0.2 release
name: OpenADB 3.0.3 release

on:
push:
tags:
- v3.0.2
- v3.0.3
workflow_dispatch:
inputs:
tag:
description: Release tag; dispatch this workflow from the same tag ref
required: true
default: v3.0.2
default: v3.0.3
type: string
allow_unsigned_stable:
description: Explicitly publish an unsigned stable release (artifact keeps the -unsigned suffix)
Expand All @@ -31,7 +31,7 @@ jobs:
tag: ${{ steps.release-ref.outputs.tag }}
allow_unsigned_stable: ${{ steps.release-ref.outputs.allow_unsigned_stable }}
steps:
- name: Require the immutable 3.0.2 tag
- name: Require the immutable 3.0.3 tag
id: release-ref
shell: pwsh
env:
Expand All @@ -47,8 +47,8 @@ jobs:
'${{ github.ref_name }}'
}

if ($tag -ne 'v3.0.2') {
throw "This release workflow is intentionally restricted to v3.0.2; received '$tag'."
if ($tag -ne 'v3.0.3') {
throw "This release workflow is intentionally restricted to v3.0.3; received '$tag'."
}
if ($env:CURRENT_REF -ne "refs/tags/$tag") {
throw "Run a manual release from the $tag tag ref, not from a branch or a different tag."
Expand Down Expand Up @@ -212,7 +212,7 @@ jobs:
if (@(Compare-Object $requiredTopLevel $actualTopLevel).Count -ne 0) {
throw 'BUILD_STATUS.json has missing or unexpected top-level fields.'
}
if ($status.version -ne '3.0.2') {
if ($status.version -ne '3.0.3') {
throw "Unexpected build version '$($status.version)'."
}
if ($status.signed -isnot [bool]) {
Expand All @@ -236,21 +236,21 @@ jobs:
$bridgeKeys = @($status.acbridge.PSObject.Properties.Name)
if (@(Compare-Object @('package', 'version_name', 'version_code', 'apk_filename') $bridgeKeys).Count -ne 0 -or
$status.acbridge.package -ne 'com.communism420.acbridge' -or
$status.acbridge.version_name -ne '3.0.2' -or
[int]$status.acbridge.version_code -ne 30201 -or
$status.acbridge.apk_filename -ne 'ACBridge-3.0.2.apk') {
$status.acbridge.version_name -ne '3.0.3' -or
[int]$status.acbridge.version_code -ne 30301 -or
$status.acbridge.apk_filename -ne 'ACBridge-3.0.3.apk') {
throw 'BUILD_STATUS.json contains unexpected ACBridge metadata.'
}

$expectedName = if ($status.signed) {
'OpenADB-3.0.2.exe'
'OpenADB-3.0.3.exe'
} else {
'OpenADB-3.0.2-unsigned.exe'
'OpenADB-3.0.3-unsigned.exe'
}
$expectedArtifactName = if ($status.signed) {
'OpenADB-3.0.2-windows-signed'
'OpenADB-3.0.3-windows-signed'
} else {
'OpenADB-3.0.2-windows-unsigned'
'OpenADB-3.0.3-windows-unsigned'
}
if ($env:BUILD_ARTIFACT_NAME -ne $expectedArtifactName -or
$env:BUILD_OUTPUT_FILENAME -ne $expectedName -or
Expand All @@ -261,7 +261,7 @@ jobs:
if ($status.filename -ne $expectedName) {
throw "Build filename '$($status.filename)' does not match its signed status."
}
$executables = @(Get-ChildItem -LiteralPath $release -File -Filter 'OpenADB-3.0.2*.exe')
$executables = @(Get-ChildItem -LiteralPath $release -File -Filter 'OpenADB-3.0.3*.exe')
if ($executables.Count -ne 1 -or $executables[0].Name -ne $expectedName) {
throw 'The build artifact must contain exactly one correctly named OpenADB executable.'
}
Expand Down Expand Up @@ -303,7 +303,7 @@ jobs:
throw "Unsigned build has an unexpected Authenticode state: $($signature.Status)."
}

$apkSource = 'openadb/resources/acbridge/ACBridge-3.0.2.apk'
$apkSource = 'openadb/resources/acbridge/ACBridge-3.0.3.apk'
if (-not (Test-Path -LiteralPath $apkSource -PathType Leaf) -or
(Get-Item -LiteralPath $apkSource).Length -le 0) {
throw 'The versioned ACBridge APK is missing or empty at the release tag.'
Expand All @@ -312,7 +312,7 @@ jobs:

$releaseFiles = @(
$exe.FullName,
(Join-Path $release 'ACBridge-3.0.2.apk'),
(Join-Path $release 'ACBridge-3.0.3.apk'),
$statusPath
)
$newSums = foreach ($file in $releaseFiles) {
Expand Down Expand Up @@ -344,10 +344,10 @@ jobs:
$changelog = Get-Content -LiteralPath 'CHANGELOG_EN.md' -Raw -Encoding utf8
$match = [regex]::Match(
$changelog,
'(?ms)^## \[3\.0\.2\].*?(?=^## \[|\z)'
'(?ms)^## \[3\.0\.3\].*?(?=^## \[|\z)'
)
if (-not $match.Success) {
throw 'CHANGELOG_EN.md does not contain a 3.0.2 release section.'
throw 'CHANGELOG_EN.md does not contain a 3.0.3 release section.'
}
$status = Get-Content -LiteralPath 'release/BUILD_STATUS.json' -Raw -Encoding utf8 |
ConvertFrom-Json
Expand All @@ -360,7 +360,7 @@ jobs:
}

$notes = @"
# OpenADB 3.0.2
# OpenADB 3.0.3

## Artifact status

Expand Down Expand Up @@ -419,11 +419,11 @@ jobs:
}

$title = if ($env:SIGNED -eq 'true') {
'OpenADB 3.0.2'
'OpenADB 3.0.3'
} elseif ($env:STABLE -eq 'true') {
'OpenADB 3.0.2 (explicitly approved unsigned)'
'OpenADB 3.0.3 (explicitly approved unsigned)'
} else {
'OpenADB 3.0.2 unsigned preview'
'OpenADB 3.0.3 unsigned preview'
}
$arguments = @(
'release', 'create', $env:RELEASE_TAG,
Expand All @@ -436,7 +436,7 @@ jobs:
}
$arguments += @(
(Join-Path 'release' $env:EXE_FILENAME),
'release/ACBridge-3.0.2.apk',
'release/ACBridge-3.0.3.apk',
'release/BUILD_STATUS.json',
'release/SHA256SUMS.txt'
)
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/windows-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ on:
required: false
push:
tags:
- "v3.0.2"
- "v3.0.3"

permissions:
contents: read
Expand All @@ -39,7 +39,7 @@ defaults:
shell: pwsh

env:
OPENADB_VERSION: "3.0.2"
OPENADB_VERSION: "3.0.3"
PLATFORM_TOOLS_VERSION: "37.0.0"
PLATFORM_TOOLS_ARCHIVE: "platform-tools_r37.0.0-win.zip"
PLATFORM_TOOLS_ARCHIVE_SHA1: "f29bfb58d0d6f9a57d7dbcba6cc259f9ca6f58f1"
Expand Down
70 changes: 64 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,67 @@
All notable OpenADB changes made since the start of the local audit and project
redesign are documented in this file.

The format is based on Keep a Changelog. The current public project version is
3.0.2.
The format is based on Keep a Changelog. The current development version is
3.0.3.

## [3.0.2] — Unreleased
## [3.0.3] — Unreleased

### Fixed

- Fixed PC-to-Android P2P uploads to removable MicroSD/USB storage failing
after startup with `.openadb-*.part: open failed: EACCES (Permission
denied)` when Android's global All files access setting was enabled.
- ACBridge now resolves removable destinations through the matching persisted
Storage Access Framework tree before considering any direct filesystem
fallback. A global primary-storage permission can no longer silently bypass
an existing MicroSD/USB SAF grant.
- Storage access is selected once before ACBridge publishes `READY` and the
same pinned backend is used for the complete upload. This removes the former
check/use mismatch and prevents the PC from sending buffered file data to a
destination that only appeared writable.
- On TV firmware without a usable SAF picker, the compatibility fallback now
requires the storage-access flow to record approval for that removable
volume, Android's global storage-manager permission, and a successful
create/delete write probe. The probe completes before the P2P data server is
opened; if it fails, ACBridge clears the fallback approval and remains in
the permission flow instead of starting a transfer that will fail with
`EACCES`.
- Persisted SAF trees are now accepted only while Android still reports an
active read/write grant. ACBridge pins the grant by volume and performs a real
create/open/delete probe in the exact destination before publishing
`READY`, including when the destination is the granted tree root.
- The storage picker now reports success only after Android confirms an exact,
persistent read/write tree grant. Invalid picker results and failed direct
write probes are rejected, and removable-storage probing runs off the Android
UI thread.
- Privileged bridge commands now use a shell-permission-protected activity;
the public launcher rejects command extras and destructive operations from
public bridge settings.

### Version

- Updated OpenADB, ACBridge, Windows metadata, build workflows, screenshots,
and active release documentation to version 3.0.3.
- ACBridge 3.0.3 uses `versionCode 30301` and is rebuilt from source as
`ACBridge-3.0.3.apk`.

### Validation

- Added source-level regressions for SAF-first removable-storage routing with
All files access enabled, pre-`READY` access pinning, active read/write-grant
checks, per-volume fallback approval, and Unicode removable paths. Added a
host regression that converts the exact removable `.part`/`EACCES` failure
into one permission request and one bounded retry.
- A disposable Android 16 emulator with global All files access enabled
transferred 2,097,455 bytes through an approved public removable SAF tree;
SHA-256 matched and no `.openadb-*` residue remained. After clearing the SAF
grant, ACBridge requested permission without opening the data connection or
creating the remote file. The emulator also rejected a command sent to the
public launcher and accepted the storage flow through the DUMP-protected
command activity. Physical Android TV MicroSD validation remains pending
because no physical ADB device was connected.

## [3.0.2] — Unreleased (superseded by 3.0.3)

### Fixed

Expand Down Expand Up @@ -47,7 +104,7 @@ The format is based on Keep a Changelog. The current public project version is
- Updated OpenADB, ACBridge, Windows metadata, build workflows, screenshots,
and active release documentation to version 3.0.2.
- ACBridge 3.0.2 uses `versionCode 30201` under the documented version-code
policy and is released as `ACBridge-3.0.2.apk`.
policy and was built as `ACBridge-3.0.2.apk`.

### Validation

Expand Down Expand Up @@ -359,8 +416,9 @@ a self-contained Windows executable was prepared.
`/storage/self/primary/` to `/storage/emulated/0/`.
- Partially received files are written to temporary `.part` or SAF documents
and removed after cancellation or failure.
- After successful verification, the temporary file atomically replaces the
existing destination file.
- After successful verification, ACBridge commits the temporary file. Providers
without rename support use a non-atomic copy fallback when replacing an
existing destination.
- ACBridge was updated to `versionName 2.0.0`, `versionCode 20004`.
- The primary bundled APK was renamed to `ACBridge-2.0.0.apk`; the compatible
`ACBridge.apk` contains the same build.
Expand Down
70 changes: 64 additions & 6 deletions CHANGELOG_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,67 @@
All notable OpenADB changes made since the start of the local audit and project
redesign are documented in this file.

The format is based on Keep a Changelog. The current public project version is
3.0.2.
The format is based on Keep a Changelog. The current development version is
3.0.3.

## [3.0.2] — Unreleased
## [3.0.3] — Unreleased

### Fixed

- Fixed PC-to-Android P2P uploads to removable MicroSD/USB storage failing
after startup with `.openadb-*.part: open failed: EACCES (Permission
denied)` when Android's global All files access setting was enabled.
- ACBridge now resolves removable destinations through the matching persisted
Storage Access Framework tree before considering any direct filesystem
fallback. A global primary-storage permission can no longer silently bypass
an existing MicroSD/USB SAF grant.
- Storage access is selected once before ACBridge publishes `READY` and the
same pinned backend is used for the complete upload. This removes the former
check/use mismatch and prevents the PC from sending buffered file data to a
destination that only appeared writable.
- On TV firmware without a usable SAF picker, the compatibility fallback now
requires the storage-access flow to record approval for that removable
volume, Android's global storage-manager permission, and a successful
create/delete write probe. The probe completes before the P2P data server is
opened; if it fails, ACBridge clears the fallback approval and remains in
the permission flow instead of starting a transfer that will fail with
`EACCES`.
- Persisted SAF trees are now accepted only while Android still reports an
active read/write grant. ACBridge pins the grant by volume and performs a real
create/open/delete probe in the exact destination before publishing
`READY`, including when the destination is the granted tree root.
- The storage picker now reports success only after Android confirms an exact,
persistent read/write tree grant. Invalid picker results and failed direct
write probes are rejected, and removable-storage probing runs off the Android
UI thread.
- Privileged bridge commands now use a shell-permission-protected activity;
the public launcher rejects command extras and destructive operations from
public bridge settings.

### Version

- Updated OpenADB, ACBridge, Windows metadata, build workflows, screenshots,
and active release documentation to version 3.0.3.
- ACBridge 3.0.3 uses `versionCode 30301` and is rebuilt from source as
`ACBridge-3.0.3.apk`.

### Validation

- Added source-level regressions for SAF-first removable-storage routing with
All files access enabled, pre-`READY` access pinning, active read/write-grant
checks, per-volume fallback approval, and Unicode removable paths. Added a
host regression that converts the exact removable `.part`/`EACCES` failure
into one permission request and one bounded retry.
- A disposable Android 16 emulator with global All files access enabled
transferred 2,097,455 bytes through an approved public removable SAF tree;
SHA-256 matched and no `.openadb-*` residue remained. After clearing the SAF
grant, ACBridge requested permission without opening the data connection or
creating the remote file. The emulator also rejected a command sent to the
public launcher and accepted the storage flow through the DUMP-protected
command activity. Physical Android TV MicroSD validation remains pending
because no physical ADB device was connected.

## [3.0.2] — Unreleased (superseded by 3.0.3)

### Fixed

Expand Down Expand Up @@ -47,7 +104,7 @@ The format is based on Keep a Changelog. The current public project version is
- Updated OpenADB, ACBridge, Windows metadata, build workflows, screenshots,
and active release documentation to version 3.0.2.
- ACBridge 3.0.2 uses `versionCode 30201` under the documented version-code
policy and is released as `ACBridge-3.0.2.apk`.
policy and was built as `ACBridge-3.0.2.apk`.

### Validation

Expand Down Expand Up @@ -359,8 +416,9 @@ a self-contained Windows executable was prepared.
`/storage/self/primary/` to `/storage/emulated/0/`.
- Partially received files are written to temporary `.part` or SAF documents
and removed after cancellation or failure.
- After successful verification, the temporary file atomically replaces the
existing destination file.
- After successful verification, ACBridge commits the temporary file. Providers
without rename support use a non-atomic copy fallback when replacing an
existing destination.
- ACBridge was updated to `versionName 2.0.0`, `versionCode 20004`.
- The primary bundled APK was renamed to `ACBridge-2.0.0.apk`; the compatible
`ACBridge.apk` contains the same build.
Expand Down
2 changes: 1 addition & 1 deletion GUI_AUDIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Дата аудита: 10 июля 2026 года

Текущая версия: OpenADB 3.0.2
Текущая версия: OpenADB 3.0.3

Среда: Windows, Python 3.14.3, PySide6 6.11.1, экран 1920×1080, системная тёмная тема

Expand Down
2 changes: 1 addition & 1 deletion GUI_REDESIGN_REPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Дата: 12 июля 2026 года

Версия отчёта: OpenADB 3.0.2
Версия отчёта: OpenADB 3.0.3

Платформа проверки: Windows, Python 3.14.3, PySide6 6.11.1

Expand Down
Loading
Loading