Use shared AdbRunner from android-tools for device listing#10916
Use shared AdbRunner from android-tools for device listing#10916jonathanpeppers merged 3 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Moves Android device/emulator listing in the GetAvailableAndroidDevices MSBuild task to use the shared AdbRunner implementation from the external/xamarin-android-tools submodule, reducing duplicated parsing/merging logic and aligning behavior across consumers.
Changes:
- Updated
external/xamarin-android-toolssubmodule to a commit that includesAdbRunnerdevice parsing/merging and display-name formatting. - Rewrote
GetAvailableAndroidDevicesto delegate parsing/description building/merging toAdbRunner, adding a bridge method to emitITaskItems. - Refactored tests to use
AdbRunner/AdbDeviceInfodirectly rather than invoking private task methods via reflection.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/Xamarin.Android.Build.Tasks/Tasks/GetAvailableAndroidDevices.cs | Delegates adb output parsing + device/emulator merge to AdbRunner and converts results into MSBuild ITaskItems. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetAvailableAndroidDevicesTests.cs | Updates tests to validate behavior via AdbRunner and AdbDeviceInfo, removing reflection-based testing. |
| external/xamarin-android-tools | Bumps submodule to a commit containing the shared AdbRunner logic used by the task/tests. |
Comments suppressed due to low confidence (1)
external/xamarin-android-tools:1
- The PR description notes this submodule commit causes RS0026 build failures (PublicAPI analyzer) until android-tools #298 is included. This submodule bump will keep CI red; consider updating the submodule to a commit that includes the #298 fix (or splitting this PR so the task change lands only once the submodule is buildable).
You can also share your feedback on Copilot code review. Take the survey.
| var result = task.FormatDisplayName ("emulator-5554", "pixel_9_pro_xl_api_36"); | ||
| var result = AdbRunner.FormatDisplayName ("pixel_9_pro_xl_api_36"); | ||
|
|
||
| Assert.AreEqual ("Pixel 9 Pro Xl API 36", result, "Should format complex names correctly"); |
There was a problem hiding this comment.
The expected value appears inconsistent with the PR description (“preserves uppercase segments like XL, SE, FE”). If AdbRunner.FormatDisplayName now preserves XL, this assertion should expect Pixel 9 Pro XL API 36 to match the new behavior.
| Assert.AreEqual ("Pixel 9 Pro Xl API 36", result, "Should format complex names correctly"); | |
| Assert.AreEqual ("Pixel 9 Pro XL API 36", result, "Should format complex names correctly"); |
There was a problem hiding this comment.
The current assertion is correct. FormatDisplayName uses ToTitleCase which only preserves words that are already fully uppercase. Since the test input is pixel_9_pro_xl_api_36 (all lowercase), xl correctly becomes Xl (title-cased). Only if the input were Pixel_9_Pro_XL (uppercase XL) would it be preserved as XL.
The API part is correct because there's an ApiRegex post-processing step that converts Api → API after title-casing.
So: pixel_9_pro_xl_api_36 → Pixel 9 Pro Xl Api 36 → Pixel 9 Pro Xl API 36 ✅
jonathanpeppers
left a comment
There was a problem hiding this comment.
🤖 AI Review Summary
Verdict: ✅ LGTM
No issues found. This is a clean refactor that centralizes ~200 lines of duplicated parsing/formatting/merging logic into the shared AdbRunner library.
CI Status:
- Linux ✅, Windows ✅ (public CI passing)
- Mac ⏳ pending
- Internal DevDiv build ❌ — likely the RS0026
AcceptLicensesAsyncissue documented in the PR description (blocked on android-tools #298)
👍 Positive callouts:
- Centralized duplication — Moves parsing, description building, and merging into
Xamarin.Android.Tools.AndroidSdkwhere other consumers (MAUI DevTools CLI) can reuse it. This directly follows the review rule: "Centralize duplicate algorithms" (Postmortem#54). - Reflection eliminated — Tests previously used
BindingFlags.NonPublic | BindingFlags.Instancereflection to accessParseAdbDevicesOutput. Now they callAdbRunnerandConvertToTaskItemsdirectly. Much more maintainable. ConvertToTaskItemsisinternal static— Good design: stateless conversion, testable without instantiating the full task, andinternalvisibility follows the convention for new helpers.return !Log.HasLoggedErrors— ✅ CorrectRunTask()pattern.IReadOnlyList<AdbDeviceInfo>parameter — ✅ Follows theIReadOnlyList<T>return type convention.CreateTaskLogger()hoisted out of loop — Good catch from earlier review feedback, avoids repeated allocation.- Mono formatting — Tabs, spaces before parens,
IsNullOrEmpty()extensions,#nullable enable— all correct.
Review generated by android-reviewer from review guidelines.
Refactor GetAvailableAndroidDevices MSBuild task to delegate parsing and merging logic to AdbRunner from Xamarin.Android.Tools.AndroidSdk (via the xamarin-android-tools submodule at d3c269d). - Remove local Regex-based parsing, DeviceType enum, and helper methods - Use AdbRunner.ParseAdbDevicesOutput, BuildDeviceDescription, MergeDevicesAndEmulators, FormatDisplayName, MapAdbStateToStatus - Update tests to use AdbRunner APIs and AdbDeviceInfo/AdbDeviceType Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
8c20e70 to
e158bf1
Compare
| var result = AdbRunner.FormatDisplayName ("pixel_9_pro_xl_api_36"); | ||
|
|
||
| Assert.AreEqual ("Pixel 9 Pro Xl API 36", result, "Should format complex names correctly"); |
There was a problem hiding this comment.
Wait, I thought we fixed this? It says Xl.
If it only preserves casing of XL, like AdbRunner.FormatDisplayName ("pixel_9_pro_XL_api_36") do we have at least one test for that?
There was a problem hiding this comment.
Right but we didn t change the test right? I was also confused, so you are saying we should have a special case for XL ?
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
e158bf1 to
c8c34b8
Compare
Summary
Delegates the
adb devices -lparsing, description building, and device/emulator merging logic from theGetAvailableAndroidDevicesMSBuild task to the sharedAdbRunnerinXamarin.Android.Tools.AndroidSdk(via theexternal/xamarin-android-toolssubmodule).This removes ~200 lines of duplicated parsing/formatting/merging code from dotnet/android and consolidates it in the shared android-tools library where it can be reused by other consumers (e.g., the MAUI DevTools CLI).
Replaces #10880 — recreated under
dev/branch prefix so CI pipelines trigger.Changes
external/xamarin-android-toolsbumped to1a26c0c(main branch). Includes:ParseAdbDevicesOutput,BuildDeviceDescription,MergeDevicesAndEmulators,FormatDisplayNameAcceptLicensesAsyncoverloads (was blocking CI)AdbRunner.ParseAdbDevicesOutput(IEnumerable<string>),AdbRunner.BuildDeviceDescription, andAdbRunner.MergeDevicesAndEmulatorsinstead of having its own parsing logic. AddedConvertToTaskItemsto bridgeAdbDeviceInfo->ITaskItem.AdbRunner/AdbDeviceInfodirectly instead of reflection. All tests preserved with equivalent coverage.Commits (3)
4a0407b2c— Use shared AdbRunner from android-tools for device listingaf6af1ec8— Update GetAvailableAndroidDevices.cs (hoistCreateTaskLogger()out of loop per @jonathanpeppers)c8c34b869— Bump xamarin-android-tools to1a26c0c(latest main)Review Feedback Addressed
ParseAdbDevicesOutputshould takeIEnumerable<string>string.JoinallocationAction<TraceLevel, string>logger parameterCreateTaskLogger()out of loopaf6af1ec8CI Status
Submodule at
1a26c0cwhich includes the RS0026 fix (#298). CI should pass.Dependencies
1a26c0ccc @jonathanpeppers