Skip to content

[flutter_tools] Fix wireless ADB device discovery when serial contains spaces#187943

Merged
auto-submit[bot] merged 5 commits into
flutter:masterfrom
bkonyi:fix-wireless-adb-spaces
Jul 8, 2026
Merged

[flutter_tools] Fix wireless ADB device discovery when serial contains spaces#187943
auto-submit[bot] merged 5 commits into
flutter:masterfrom
bkonyi:fix-wireless-adb-spaces

Conversation

@bkonyi

@bkonyi bkonyi commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Description

When ADB registers a wireless device, it uses the mDNS service name as the device serial. If there is an mDNS name conflict (e.g. due to toggling wireless debugging off and on quickly), ADB appends a suffix like " (2)" to the service name, resulting in a serial with a space (e.g. adb-SERIAL (2)._adb-tls-connect._tcp).

Previously, the regex used to parse adb devices -l output truncated the serial at the first space, leading to corrupted device IDs and "device not found" errors when the tool tried to communicate with the device.

This change updates the regex in android_device_discovery.dart to use an anchored lazy match that correctly identifies the boundary between the serial and the state, allowing spaces in the serial.

It explicitly handles the "no permissions" state (which is the only known state containing a space) and uses a generic match (\S+) for all other single-word states.

Detailed comments have been added to the regex to explain this design.

Related Issues

Tests

  • Added a new exhaustive test case in android_device_discovery_test.dart (AndroidDevices can parse various adb device outputs exhaustively) that verifies various combinations of serials (with/without spaces, containing state keywords) and states.
  • Ran all tests in packages/flutter_tools/test/general.shard/android/android_device_discovery_test.dart and they passed.

…s spaces

When ADB registers a wireless device, it uses the mDNS service name as
the device serial. If there is an mDNS name conflict, ADB appends a
suffix like " (2)" to the service name, resulting in a serial with a
space (e.g. "adb-SERIAL (2)._adb-tls-connect._tcp").

Previously, the regex used to parse `adb devices -l` output truncated
the serial at the first space, leading to corrupted device IDs and
"device not found" errors.

This change updates the regex to use an anchored lazy match that
correctly identifies the boundary between the serial and the state,
allowing spaces in the serial. It explicitly handles the "no permissions"
state (which contains a space) and uses a generic match for all other
single-word states.

An exhaustive test case has been added to verify various combinations of
serials (with/without spaces, containing state keywords) and states.
@bkonyi
bkonyi requested a review from a team as a code owner June 12, 2026 18:21
@bkonyi
bkonyi requested review from reidbaker and removed request for a team June 12, 2026 18:21
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 12, 2026
@github-actions github-actions Bot added tool Affects the "flutter" command-line tool. See also t: labels. team-android Owned by Android platform team labels Jun 12, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the regular expression _kDeviceRegex in android_device_discovery.dart to support parsing device serials with spaces and 'no permissions' states, and adds comprehensive unit tests to verify various adb devices output formats. Feedback suggests refining the regular expression to allow optional trailing whitespace and carriage returns to prevent matching failures on Windows.


// 015d172c98400a03 device usb:340787200X product:nakasi model:Nexus_7 device:grouper
static final _kDeviceRegex = RegExp(r'^(\S+)\s+(\S+)(.*)');
static final _kDeviceRegex = RegExp(r'^(.*?)\s+(no permissions|\S+)(?:\s+(\w+:.*)|$)');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the output line contains any trailing whitespace (such as a trailing space or a carriage return \r on Windows), the current regular expression will fail to match. This is because the last group (?:\s+(\w+:.*)|$) expects either a space followed by key-value pairs, or the absolute end of the string ($). If there is trailing whitespace, neither branch matches, causing the entire regex match to fail.\n\nTo make the parsing more robust against trailing whitespace and carriage returns, we can change the end-of-string anchor $ to \s*$ to allow optional trailing whitespace.

Suggested change
static final _kDeviceRegex = RegExp(r'^(.*?)\s+(no permissions|\S+)(?:\s+(\w+:.*)|$)');
static final _kDeviceRegex = RegExp(r'^(.*?)\s+(no permissions|\S+)(?:\s+(\w+:.*)|\s*$)');

Add detailed comments explaining the structure of the regex used to
parse `adb devices -l` output, specifically why we explicitly handle
the "no permissions" state (due to it containing a space) and how the
anchored lazy match prevents false positives.
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 12, 2026
@bkonyi bkonyi added the CICD Run CI/CD label Jun 12, 2026
…eturns

Address feedback from gemini-code-assist. On Windows, `adb devices -l`
output lines may end with `\r` (carriage return). When split by `\n`,
the trailing `\r` remains on the line, which can cause matching
failures with our anchored regex (as `$` matches after `\r`, but `\S+`
stops before it, leaving `\r` unmatched by the anchor).

Trimming each line at the start of the loop robustly removes any
trailing `\r` (and other leading/trailing whitespace), ensuring
reliable parsing on all platforms.
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 12, 2026
@bkonyi bkonyi added the CICD Run CI/CD label Jun 12, 2026
@camsim99

Copy link
Copy Markdown
Contributor

Just FYI: #187845 also seeks to address this issue.

@gmackall
gmackall requested review from a team, gmackall and reidbaker and removed request for a team and reidbaker June 30, 2026 21:02
gmackall
gmackall previously approved these changes Jul 7, 2026
# Conflicts:
#	packages/flutter_tools/lib/src/android/android_device_discovery.dart
@bkonyi
bkonyi requested a review from gmackall July 7, 2026 20:19
@bkonyi bkonyi added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 7, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Jul 8, 2026
Merged via the queue into flutter:master with commit 629df07 Jul 8, 2026
163 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 8, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Jul 10, 2026
…12169)

Manual roll Flutter from 91939cc4db78 to dc2a8703e12b (50 revisions)

Manual roll requested by [email protected]

flutter/flutter@91939cc...dc2a870

2026-07-09 [email protected] [ios,macos] Update swiftc.py flags to match swiftc (flutter/flutter#189174)
2026-07-09 [email protected] [AGP 9] Update Warn Version to AGP 9+ (flutter/flutter#189109)
2026-07-09 [email protected] Sync CHANGELOG.md from stable (flutter/flutter#189203)
2026-07-09 [email protected] [web] Roll Chrome to 145 (framework) (flutter/flutter#182861)
2026-07-09 [email protected] Roll Packages from 52d84d6 to 20928d5 (6 revisions) (flutter/flutter#189194)
2026-07-09 [email protected] [web] Avoid absolute positioning for base CanvasKit canvas (flutter/flutter#188337)
2026-07-09 [email protected] Roll Dart SDK from cdb7217e65aa to a11fb7ed40a5 (6 revisions) (flutter/flutter#189195)
2026-07-09 [email protected] Fix dereference of nullptr in the moved-to-rect signal in the Linux embedder (flutter/flutter#189152)
2026-07-09 [email protected] Fix data for design packages (flutter/flutter#189140)
2026-07-09 [email protected] Roll Skia from 7b42d1251d54 to ab3a7b98c94d (2 revisions) (flutter/flutter#189181)
2026-07-09 [email protected] Roll Skia from 05d9d214e0b7 to 7b42d1251d54 (2 revisions) (flutter/flutter#189175)
2026-07-09 [email protected] Roll Skia from 542c8bdd7f4f to 05d9d214e0b7 (4 revisions) (flutter/flutter#189169)
2026-07-09 [email protected] UberSDF rect handling for thin (line-like) rectangles (flutter/flutter#188821)
2026-07-09 [email protected] Roll Skia from dd572c07f63c to 542c8bdd7f4f (4 revisions) (flutter/flutter#189160)
2026-07-09 [email protected] [flutter_tools] Fix hot restart for WASM web builds (flutter/flutter#187898)
2026-07-08 [email protected] Split FlViewRenderer into OpenGL and software backends (flutter/flutter#188824)
2026-07-08 [email protected] Promote android_hardware_smoke_tests out of bringup in CI (flutter/flutter#189081)
2026-07-08 [email protected] Roll Skia from 8df24be66531 to dd572c07f63c (4 revisions) (flutter/flutter#189150)
2026-07-08 [email protected] Expose LinuxWindowRegistrar on _window_linux.dart in order to better support out of tree LinuxWindowingOwners (flutter/flutter#188917)
2026-07-08 [email protected] Roll pub packages (flutter/flutter#189149)
2026-07-08 [email protected] fix(ci): harden some workflows (flutter/flutter#189087)
2026-07-08 [email protected] Roll Skia from 51a62da33da0 to 8df24be66531 (1 revision) (flutter/flutter#189139)
2026-07-08 [email protected] Roll Dart SDK to Dart 3.13 beta3 (flutter/flutter#189122)
2026-07-08 [email protected] [flutter_tools] Don't crash on non-UTF-8 plugin pubspec.yaml (flutter/flutter#188976)
2026-07-08 [email protected] [flutter_tools] Watch transitive #include headers for FragmentProgram hot reload (flutter/flutter#187945)
2026-07-08 [email protected] Roll Skia from 040d9f55de00 to 51a62da33da0 (1 revision) (flutter/flutter#189135)
2026-07-08 [email protected] Roll Packages from 92525f5 to 52d84d6 (7 revisions) (flutter/flutter#189134)
2026-07-08 [email protected] [flutter_tools] Forcefully kill hung subprocesses 5 seconds after timeout (flutter/flutter#187178)
2026-07-08 [email protected] Expose the app's build name and number as compile-time constants (flutter/flutter#187935)
2026-07-08 [email protected] Roll Skia from 1ff92f879815 to 040d9f55de00 (1 revision) (flutter/flutter#189131)
2026-07-08 [email protected] Roll Skia from 6137414bef5c to 1ff92f879815 (6 revisions) (flutter/flutter#189126)
2026-07-08 [email protected] [test cross imports] More test/rendering + flutter_test/test fixes (flutter/flutter#188954)
2026-07-08 [email protected] engine: explain why each candidate build was skipped in Flutter web loader (flutter/flutter#186254)
2026-07-08 [email protected] vscode: add missing unicode.h (flutter/flutter#189102)
2026-07-08 [email protected] Roll Fuchsia Linux SDK from 7RjQJBW3m-3Jl-7jr... to QcRFUtvCw2EobfJ8s... (flutter/flutter#189104)
2026-07-08 [email protected] Roll Skia from 075fbe4778d9 to 6137414bef5c (10 revisions) (flutter/flutter#189106)
2026-07-08 [email protected] engine: warn on WASM load failure when not crossOriginIsolated (flutter/flutter#186252)
2026-07-08 [email protected] Roll Dart SDK from c9bccc09e733 to db2155f56bf3 (2 revisions) (flutter/flutter#189105)
2026-07-08 [email protected] [flutter_tools] Prevent interactive device selection in machine mode (flutter/flutter#188267)
2026-07-08 [email protected] [flutter_tools] Fix wireless ADB device discovery when serial contains spaces (flutter/flutter#187943)
2026-07-07 [email protected] [web] Fix grouped autofill on iOS Chrome (flutter/flutter#187459)
2026-07-07 [email protected] Fix TextSelectionOverlay crash when layout is degenerate (flutter/flutter#188672)
2026-07-07 [email protected] [flutter_tools] Provision Android NDK in the main Gradle invocation (flutter/flutter#186337)
2026-07-07 [email protected] Android_hardware_smoke_test: Migrate to AGP 9 (flutter/flutter#189082)
...
@jtmcdole

Copy link
Copy Markdown
Member

This breaks some of our Mokeys!

IJU1234 device 20-3 product:mokey model:asdf -> IJU1234 device + 20-3

#189274

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD team-android Owned by Android platform team tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wireless ADB: device serial with space (mDNS conflict suffix " (2)") parsed incorrectly, device shown as "Android null (API null)"

4 participants