trace_replay: Retrieve performance metrics for timed out replays

Retrieve performance metrics even if replay can't be finished in time.
In this case instead of failing with timout error we will try to
replay as many frames as possible and return obtained metrics with
successful result. The actual replayed frames count will be returned
as well.

BUG=b:209829784
TEST=tested on local dut

Change-Id: I8c478c34509298775daf33b424493ee313febc9d
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/graphics/+/3324065
Reviewed-by: Po-Hsien Wang <pwang@chromium.org>
Reviewed-by: Ilja Friedel <ihf@chromium.org>
Tested-by: Robert Tarasov <tutankhamen@chromium.org>
Commit-Queue: Robert Tarasov <tutankhamen@chromium.org>
diff --git a/src/trace_replay/cmd/trace_replay/main.go b/src/trace_replay/cmd/trace_replay/main.go
index c6aba41..7e5926d 100644
--- a/src/trace_replay/cmd/trace_replay/main.go
+++ b/src/trace_replay/cmd/trace_replay/main.go
@@ -40,6 +40,9 @@
 	defaultTimeout = 60 * 60
 	// Maximum allowed replay time for one trace in seonds
 	replayMaxTime = 15 * 60
+	// Minimum replay timeout for one trace in seconds.
+	// Can't be less than 10 due to nested app timeout which is (replayMinTime-10)
+	replayMinTime = 30
 	// Cooling down time before each trace replay in seconds
 	replayCoolDownTime = 30
 )
@@ -446,10 +449,18 @@
 }
 
 func replayTrace(ctx context.Context, config replayAppConfig, traceFileName string, timeoutInSeconds uint32) (map[string]comm.ValueEntry, error) {
+	if timeoutInSeconds < replayMinTime {
+		return nil, errors.New("The requested timeout is too short to replay a trace file. Requested: %d, wanted >= %d", timeoutInSeconds, replayMinTime)
+	}
 	ctx, cancel := context.WithTimeout(ctx, time.Duration(timeoutInSeconds)*time.Second)
 	defer cancel()
+	appArgs := config.Args
 
-	exitCode, stdout, stderr := runCommand(ctx, config.EnvVars, config.AppName, append(config.Args, traceFileName)...)
+	// Add nested timeout to glretrace/eglretrace
+	appArgs = append(appArgs, fmt.Sprintf("--timeout=%d", timeoutInSeconds-10))
+
+	appArgs = append(appArgs, traceFileName)
+	exitCode, stdout, stderr := runCommand(ctx, config.EnvVars, config.AppName, appArgs...)
 	if exitCode != 0 {
 		return nil, errors.New("Failed to replay trace file [%s]. Exit code: %d. %s", traceFileName, exitCode, stderr)
 	}