Skip to content

Commit 66eb698

Browse files
committed
refactor(cli): Add OnStepFinished and log flash timings
Introduce OnStepFinished(Action<string, TimeSpan, bool>) to FastbootDriver and instrument flash code paths to measure duration and success for each flash step. Wrap Flash/FlashAll/Dynamic partition flows and FlashUnsparseImage with Stopwatch and invoke the callback (e.g. "Flashing <partition>", elapsed, success). FastbootCLI collects these step results for flash/flashall/update commands and prints per-step status and timing after execution. Also remove a DataTransferProgressChanged write in the device-list flow. Includes a brief comment for the new callback.
1 parent 7fa1414 commit 66eb698

5 files changed

Lines changed: 113 additions & 37 deletions

File tree

FastbootCLI/Program.cs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,15 @@ static void Main(string[] args)
160160
if (!string.IsNullOrEmpty(step)) Console.Error.WriteLine(step);
161161
};
162162

163+
var stepResults = new List<(string Step, TimeSpan Duration, bool Success)>();
164+
util.OnStepFinished = (step, duration, success) =>
165+
{
166+
if (step.StartsWith("Flash") || step.StartsWith("Flashing"))
167+
{
168+
stepResults.Add((step, duration, success));
169+
}
170+
};
171+
163172
foreach (var cmd in pendingCommands)
164173
{
165174
try
@@ -174,6 +183,14 @@ static void Main(string[] args)
174183
Environment.Exit(1);
175184
}
176185
}
186+
187+
if (pendingCommands.Any(c => c.Command is "flash" or "flashall" or "update"))
188+
{
189+
foreach (var (step, duration, success) in stepResults)
190+
{
191+
Console.Error.WriteLine($"{step,-30} {(success ? "Success" : "Failed"),-4} Time: {duration.TotalSeconds:F2} s");
192+
}
193+
}
177194
}
178195

179196
static void ExecuteDeviceList(List<string> args)
@@ -204,13 +221,6 @@ static void ExecuteCommand(FastbootDriver util, string command, List<string> arg
204221
return;
205222
}
206223

207-
util.DataTransferProgressChanged += (s, e) =>
208-
{
209-
int percent = (int)(e.Item1 * 100 / e.Item2);
210-
Console.Error.Write($"\r{command} ({e.Item1}/{e.Item2}) {percent}% ");
211-
if (e.Item1 == e.Item2) Console.Error.WriteLine();
212-
};
213-
214224
if (wipeUserdata && (command == "flashall" || command == "update"))
215225
{
216226
Console.Error.WriteLine("Wiping userdata/cache as requested by -w...");

FirmwareKit.Comm.Fastboot/Command/Flash.cs

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,34 +45,50 @@ static bool IsSparseHeader(Stream s)
4545
// log sizes so that callers can understand why we convert to sparse
4646
FastbootDebug.Log($"FlashUnsparseImage: imageSize={imageSize}, maxDownloadSize={maxDownloadSize}, isSparse={isSparse}");
4747

48-
if (isSparse)
48+
var sw = System.Diagnostics.Stopwatch.StartNew();
49+
bool success = false;
50+
try
4951
{
50-
NotifyCurrentStep($"Flashing sparse image to {partition}...");
51-
using var sparseImage = SparseFile.ImportAuto(stream, validateCrc: false, verbose: false);
52-
return FlashSparseFile(partition, sparseImage, maxDownloadSize);
53-
}
54-
55-
// Only send raw if the image will fit in a single transfer
56-
if (imageSize <= maxDownloadSize)
57-
{
58-
if (canSeek) stream.Seek(originalPosition, SeekOrigin.Begin);
59-
return FlashRawImage(partition, stream, imageSize);
60-
}
52+
if (isSparse)
53+
{
54+
NotifyCurrentStep($"Flashing sparse image to {partition}...");
55+
using var sparseImage = SparseFile.ImportAuto(stream, validateCrc: false, verbose: false);
56+
var resp = FlashSparseFile(partition, sparseImage, maxDownloadSize);
57+
success = resp.Result == FastbootState.Success;
58+
return resp;
59+
}
60+
61+
// Only send raw if the image will fit in a single transfer
62+
if (imageSize <= maxDownloadSize)
63+
{
64+
if (canSeek) stream.Seek(originalPosition, SeekOrigin.Begin);
65+
var resp = FlashRawImage(partition, stream, imageSize);
66+
success = resp.Result == FastbootState.Success;
67+
return resp;
68+
}
6169

62-
if (!canSeek)
63-
{
64-
return new FastbootResponse
70+
if (!canSeek)
6571
{
66-
Result = FastbootState.Fail,
67-
Response = "raw image exceeds max-download-size and requires a seekable stream for sparse conversion"
68-
};
72+
return new FastbootResponse
73+
{
74+
Result = FastbootState.Fail,
75+
Response = "raw image exceeds max-download-size and requires a seekable stream for sparse conversion"
76+
};
77+
}
78+
79+
NotifyCurrentStep($"Converting large raw image to sparse chunks for {partition}...");
80+
stream.Seek(originalPosition, SeekOrigin.Begin);
81+
using (var sparseImage = SparseFile.ImportAuto(stream, validateCrc: false, verbose: false))
82+
{
83+
var resp = FlashSparseFile(partition, sparseImage, maxDownloadSize);
84+
success = resp.Result == FastbootState.Success;
85+
return resp;
86+
}
6987
}
70-
71-
NotifyCurrentStep($"Converting large raw image to sparse chunks for {partition}...");
72-
stream.Seek(originalPosition, SeekOrigin.Begin);
73-
using (var sparseImage = SparseFile.ImportAuto(stream, validateCrc: false, verbose: false))
88+
finally
7489
{
75-
return FlashSparseFile(partition, sparseImage, maxDownloadSize);
90+
sw.Stop();
91+
OnStepFinished?.Invoke($"Flash {partition}", sw.Elapsed, success);
7692
}
7793
}
7894

FirmwareKit.Comm.Fastboot/Command/FlashAll.cs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,19 @@ public void FlashFromDirectory(string directory, bool skipSecondary = false)
5454
if (File.Exists(img))
5555
{
5656
NotifyCurrentStep($"Flashing {p}...");
57-
using var fs = File.OpenRead(img);
58-
FlashUnsparseImage(p, fs, fs.Length).ThrowIfError();
57+
var sw = System.Diagnostics.Stopwatch.StartNew();
58+
bool success = false;
59+
try
60+
{
61+
using var fs = File.OpenRead(img);
62+
FlashUnsparseImage(p, fs, fs.Length).ThrowIfError();
63+
success = true;
64+
}
65+
finally
66+
{
67+
sw.Stop();
68+
OnStepFinished?.Invoke($"Flashing {p}", sw.Elapsed, success);
69+
}
5970
}
6071
}
6172

@@ -77,12 +88,24 @@ public void FlashFromDirectory(string directory, bool skipSecondary = false)
7788
if (File.Exists(img))
7889
{
7990
NotifyCurrentStep($"Flashing {p}...");
80-
using var fs = File.OpenRead(img);
81-
FlashUnsparseImage(p, fs, fs.Length).ThrowIfError();
91+
var sw = System.Diagnostics.Stopwatch.StartNew();
92+
bool success = false;
93+
try
94+
{
95+
using var fs = File.OpenRead(img);
96+
FlashUnsparseImage(p, fs, fs.Length).ThrowIfError();
97+
success = true;
98+
}
99+
finally
100+
{
101+
sw.Stop();
102+
OnStepFinished?.Invoke($"Flashing {p}", sw.Elapsed, success);
103+
}
82104
}
83105
}
84106

85107
NotifyCurrentStep("Flash completed.");
108+
OnStepFinished?.Invoke("Flash completed", TimeSpan.Zero, true);
86109
}
87110

88111
private void FlashDynamicPartitions(string directory, string superEmptyPath)
@@ -125,8 +148,19 @@ private void FlashDynamicPartitions(string directory, string superEmptyPath)
125148
if (File.Exists(img))
126149
{
127150
string target = p + (GetVar("slot-suffix") ?? "");
128-
using var fs = File.OpenRead(img);
129-
FlashUnsparseImage(target, fs, fs.Length).ThrowIfError();
151+
var sw = System.Diagnostics.Stopwatch.StartNew();
152+
bool success = false;
153+
try
154+
{
155+
using var fs = File.OpenRead(img);
156+
FlashUnsparseImage(target, fs, fs.Length).ThrowIfError();
157+
success = true;
158+
}
159+
finally
160+
{
161+
sw.Stop();
162+
OnStepFinished?.Invoke($"Flashing {target}", sw.Elapsed, success);
163+
}
130164
}
131165
}
132166
}

FirmwareKit.Comm.Fastboot/Command/InternalFlashSparseFile.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,21 @@ public FastbootResponse FlashSparseFile(string partition, SparseFile sparseFile,
5151

5252
if (blockCount == 0)
5353
{
54-
// Keep compatibility with previous fallback behavior when limit is unrealistically small.
5554
if (partIndex == 0 && startBlock == 0)
5655
{
5756
using var singleSparseStream = new SparseImageStream(sparseFile, 0, totalBlocks, includeCrc: false, fullRange: true, disposeSource: false);
5857
long singleLength = singleSparseStream.Length;
58+
var swSingle = System.Diagnostics.Stopwatch.StartNew();
5959
var singleDownload = DownloadData(singleSparseStream, singleLength);
60+
swSingle.Stop();
61+
OnStepFinished?.Invoke($"Flash {partition} (single)", swSingle.Elapsed, singleDownload.Result == FastbootState.Success);
6062
if (singleDownload.Result != FastbootState.Success)
6163
return singleDownload;
6264
NotifyCurrentStep($"Flashing {partition} (single)...");
65+
var swFlash = System.Diagnostics.Stopwatch.StartNew();
6366
last = RawCommand("flash:" + partition);
67+
swFlash.Stop();
68+
OnStepFinished?.Invoke($"Flash {partition} (single) commit", swFlash.Elapsed, last.Result == FastbootState.Success);
6469
if (last.Result != FastbootState.Success)
6570
return last;
6671
return last;
@@ -77,14 +82,20 @@ public FastbootResponse FlashSparseFile(string partition, SparseFile sparseFile,
7782
using var sparseStream = new SparseImageStream(sparseFile, startBlock, blockCount, includeCrc: false, fullRange: true, disposeSource: false);
7883
long sparseLength = sparseStream.Length;
7984

85+
var swDownload = System.Diagnostics.Stopwatch.StartNew();
8086
var download = DownloadData(sparseStream, sparseLength);
87+
swDownload.Stop();
88+
OnStepFinished?.Invoke($"Flash {partition} block {partIndex + 1} download", swDownload.Elapsed, download.Result == FastbootState.Success);
8189
if (download.Result != FastbootState.Success)
8290
{
8391
return download;
8492
}
8593

8694
NotifyCurrentStep($"Flashing {partition} ({partIndex + 1})...");
95+
var swFlashBlock = System.Diagnostics.Stopwatch.StartNew();
8796
last = RawCommand("flash:" + partition);
97+
swFlashBlock.Stop();
98+
OnStepFinished?.Invoke($"Flash {partition} block {partIndex + 1} commit", swFlashBlock.Elapsed, last.Result == FastbootState.Success);
8899
if (last.Result != FastbootState.Success)
89100
{
90101
return last;

FirmwareKit.Comm.Fastboot/FastbootDriver.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ namespace FirmwareKit.Comm.Fastboot;
99

1010
public partial class FastbootDriver : IDisposable
1111
{
12+
/// <summary>
13+
/// 回调:每个烧录步骤完成时触发,参数为(步骤名,耗时,是否成功)
14+
/// </summary>
15+
public Action<string, TimeSpan, bool>? OnStepFinished { get; set; }
16+
1217
public void Dispose()
1318
{
1419
FastbootDebug.Log($"Dispose()");

0 commit comments

Comments
 (0)