Skip to content

fix(Android): Overhaul serial port — deadlock, async writes, Qt 6.10 …#14282

Draft
HTRamsey wants to merge 3 commits intomavlink:masterfrom
HTRamsey:fix/android-serial-overhaul
Draft

fix(Android): Overhaul serial port — deadlock, async writes, Qt 6.10 …#14282
HTRamsey wants to merge 3 commits intomavlink:masterfrom
HTRamsey:fix/android-serial-overhaul

Conversation

@HTRamsey
Copy link
Copy Markdown
Collaborator

@HTRamsey HTRamsey commented Apr 16, 2026

…API parity

Fix critical deadlock in JNI read callback (s_ptrLock held across
newDataArrived), make writeData() non-blocking via async IO manager
writes, and map Java IOExceptions to ResourceError for hot-unplug
detection.

Assert DTR on open for CP210x/CH340 chips (fixes Radiomaster AX12),
sync public API with Qt 6.10.2 (sendBreak, settingsRestoredOnClose,
writeBufferSize stubs), fix readyRead reentrancy guard, remove dead
code (6 unused JNI control line getters, _writeDataOneShot), and
harden JNI bridge (bounded token loop, cache lock, exception ordering).

Also fixes FTDI driver races (volatile statics, endpoint fallback
scoped to single-port devices, no double-close on open failure)
and adds u-blox 9 (ZED-F9P) to the probe table.## Description

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)
  • CI/Build changes
  • Other

Testing

  • Tested locally
  • Added/updated unit tests
  • Tested with simulator (SITL)
  • Tested with hardware

Platforms Tested

  • Linux
  • Windows
  • macOS
  • Android
  • iOS

Flight Stacks Tested

  • PX4
  • ArduPilot

Screenshots

Checklist

  • I have read the Contribution Guidelines
  • I have read the Code of Conduct
  • My code follows the project's coding standards
  • I have added tests that prove my fix/feature works
  • New and existing unit tests pass locally

Related Issues


By submitting this pull request, I confirm that my contribution is made under the terms of the project's dual license (Apache 2.0 and GPL v3).

…API parity

Fix critical deadlock in JNI read callback (s_ptrLock held across
newDataArrived), make writeData() non-blocking via async IO manager
writes, and map Java IOExceptions to ResourceError for hot-unplug
detection.

Assert DTR on open for CP210x/CH340 chips (fixes Radiomaster AX12),
sync public API with Qt 6.10.2 (sendBreak, settingsRestoredOnClose,
writeBufferSize stubs), fix readyRead reentrancy guard, remove dead
code (6 unused JNI control line getters, _writeDataOneShot), and
harden JNI bridge (bounded token loop, cache lock, exception ordering).

Also fixes FTDI driver races (volatile statics, endpoint fallback
scoped to single-port devices, no double-close on open failure)
and adds u-blox 9 (ZED-F9P) to the probe table.
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 16, 2026

Codecov Report

❌ Patch coverage is 0% with 25 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (master@77a19a4). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/Comms/LinkManager.cc 0.00% 24 Missing and 1 partial ⚠️

❌ Your patch check has failed because the patch coverage (0.00%) is below the target coverage (30.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##             master   #14282   +/-   ##
=========================================
  Coverage          ?   25.51%           
=========================================
  Files             ?      754           
  Lines             ?    68025           
  Branches          ?    31527           
=========================================
  Hits              ?    17358           
  Misses            ?    38026           
  Partials          ?    12641           
Flag Coverage Δ
unittests 25.51% <0.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/Comms/LinkManager.h 50.00% <ø> (ø)
src/Comms/LinkManager.cc 9.66% <0.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 77a19a4...0a69c28. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 16, 2026

Build Results

Platform Status

Platform Status Details
Linux Passed View
Windows Passed View
MacOS Passed View
Android Failed View

Some builds failed.

Pre-commit

Check Status Details
pre-commit Failed (non-blocking) View

Pre-commit hooks: 4 passed, 36 failed, 7 skipped.

Test Results

linux-coverage: 78 passed, 0 skipped
linux-sanitizers: 78 passed, 0 skipped
Total: 156 passed, 0 skipped

Code Coverage

Coverage: 58.1%

No baseline available for comparison

Artifact Sizes

Artifact Size
QGroundControl 247.80 MB
QGroundControl-aarch64 177.23 MB
QGroundControl-installer-AMD64 134.82 MB
QGroundControl-installer-AMD64-ARM64 77.44 MB
QGroundControl-installer-ARM64 106.17 MB
QGroundControl-x86_64 172.37 MB
No baseline available for comparison

Updated: 2026-04-16 09:16:42 UTC • Triggered by: Android

…apse

- Migrate all AndroidSerial JNI calls to QJniObject::callStaticMethod<T>(),
  removing manual method ID caching (JniMethodCache, JniContext, ~180 lines)
- Convert QGCUsbSerialManager to singleton with ConcurrentHashMap resource model
- Collapse QGCFtdiDriver into QGCFtdiSerialDriver (D2XX lifecycle + serial port)
- Extract QGCUsbPermissionHandler from QGCUsbSerialManager
- Fix stale QGCFtdiDriver reference after collapse
- Restore test helpers with lightweight no-Context constructor
- Fix getOrCreateResourceId placeholder insertion
- Simplify read path: O(1) swap drain, eliminate intermediate buffer machinery
- Restructure write path: writeBuffer + QTimer drain (matches Qt Win pattern)
- Zero-copy read drain via QRingBuffer::append(QByteArray&&)
- QObjectPrivate::connect for type-safe private slot dispatch
- Add writeBufferMaxSize support, align QSERIALPORT_BUFFERSIZE to 32K
- Fix BlockingQueuedConnection deadlock in dispatchToPortObject
- Remove dead code: cleanupJniCache, unused AndroidSerial::read()
- Fix stale _bufferBytesEstimate references, explicit int narrowing in write
- Wire sendBreak/writeBufferSize through to private implementation
Two targeted fixes for serial port "Access denied" after FC reboot:

1. _portAlreadyConnected() returns false when a link exists in _rgLinks
   but isConnected() is false, allowing autoconnect to retry instead of
   skipping the port forever.

2. Manual serial connect preempts any existing autoconnect link on the
   same port via _disconnectAutoConnectLink(), preventing exclusive-
   handle conflicts on Windows.

Ref: mavlink#13932
@HTRamsey HTRamsey force-pushed the fix/android-serial-overhaul branch from cc4b5c4 to 0a69c28 Compare April 16, 2026 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant