From 9306b8796c09ca8bb2948431cffc4caf8fa62fb5 Mon Sep 17 00:00:00 2001 From: Alexander Aprelev Date: Mon, 8 Jun 2026 20:52:24 -0700 Subject: [PATCH] [infra/android] Automatically reboot android devices stuck in fastboot mode. Should help with performing dart gardening duty, taking care of the bots stuck in fastboot mode manually. Like this: https://ci.chromium.org/ui/p/dart/builders/ci.sandbox/vm-aot-android-release-arm_x64/7497/overview. Change-Id: I20f142190a2987c4b76f85ad27f5adfaa047f5a2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/510191 Reviewed-by: Ryan Macnak Commit-Queue: Alexander Aprelev --- pkg/test_runner/lib/src/android.dart | 56 ++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/pkg/test_runner/lib/src/android.dart b/pkg/test_runner/lib/src/android.dart index 1b2442aa541..65854218e2b 100644 --- a/pkg/test_runner/lib/src/android.dart +++ b/pkg/test_runner/lib/src/android.dart @@ -387,6 +387,11 @@ class AdbHelper { multiLine: true, ); + static final RegExp _fastbootDeviceLineRegexp = RegExp( + r'^([a-zA-Z0-9:_.\-]+)[ \t]+fastboot$', + multiLine: true, + ); + static Future> listDevices() { return Process.run('adb', ['devices']).then((ProcessResult result) { if (result.exitCode != 0) { @@ -401,6 +406,30 @@ class AdbHelper { .toList(); }); } + + static Future> listFastbootDevices() async { + final result = await Process.run('fastboot', ['devices']); + if (result.exitCode != 0) { + throw Exception( + "Could not list fastboot devices [stdout: ${result.stdout}," + "stderr: ${result.stderr}]", + ); + } + return _fastbootDeviceLineRegexp + .allMatches(result.stdout as String) + .map((Match m) => m[1]!) + .toList(); + } + + static Future rebootFastbootDevices() async { + final result = await Process.run('fastboot', ['reboot']); + if (result.exitCode != 0) { + throw Exception( + "Could not list fastboot devices [stdout: ${result.stdout}," + "stderr: ${result.stderr}]", + ); + } + } } /// Represents an android intent. @@ -426,10 +455,29 @@ class AdbDevicePool { var names = await AdbHelper.listDevices(); var devices = names.map(AdbDevice.new).toList(); if (devices.isEmpty) { - throw Exception( - 'No android devices found. ' - 'Please make sure "adb devices" shows your device!', - ); + var fastbootDevices = await AdbHelper.listFastbootDevices(); + if (fastbootDevices.isNotEmpty) { + print('Connected device $fastbootDevices found in fastboot mode...'); + AdbHelper.rebootFastbootDevices(); + + final sw = Stopwatch()..start(); + const waitForDeviceToRebootInSeconds = 60; + while (sw.elapsed.inSeconds < waitForDeviceToRebootInSeconds) { + print('Waiting for device to comeback after fastboot reboot...\n'); + names = await AdbHelper.listDevices(); + if (names.isNotEmpty) { + devices = names.map(AdbDevice.new).toList(); + break; + } + await Future.delayed(const Duration(seconds: 5)); + } + } + if (devices.isEmpty) { + throw Exception( + 'No android devices found. ' + 'Please make sure "adb devices" shows your device!', + ); + } } print("Found ${devices.length} Android devices."); return AdbDevicePool(devices);