1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
// Author: cirakg & claude ai
// Summary: Debug-only diagnostics: start-up time, memory, screen markers for UI scripts, and the performance overlay.
//
// Debug builds print one machine-readable line per event to the simulator
// console: "DIAG", the event name, then key=value pairs, for example
// DIAG first_frame startup_ms=1 mem_used=6984 mem_total=781888
// tools/check_budgets.py reads these lines and compares them with
// tools/budgets.json. Plain key=value pairs are used instead of JSON because
// the simulator console escapes quotes. Release builds compile the empty
// (:release) versions instead, so a real watch running a release build never
// logs anything.
//
// UI scripts (docker/scripts/screenshots.sh) wait for "DIAG shown <screen>"
// lines before taking a screenshot, and read the PIN keypad's key positions
// from "DIAG pin_keys" to tap them.
//
// Security rule: only timings and memory counters ever go through here, never
// secrets, codes or entry names. This is the only file allowed to call
// System.println outside tests (enforced by tools/lint_project.py).
import Toybox.Graphics;
import Toybox.Lang;
import Toybox.System;
// (:glance): the app object calls markStart() before the non-glance code is
// loaded (apps with a glance load the rest only for the full app).
(:glance)
module Diag {
// System.getTimer() value when the app object was created.
(:debug)
var startMs as Number = 0;
// Start the start-up timer. Called from OtpWalletApp.initialize().
(:debug)
function markStart() as Void {
startMs = System.getTimer();
}
(:release)
function markStart() as Void {
}
// Report start-up time and memory use after the first complete frame.
// startup_ms covers app object creation to the end of the first draw. The
// time the system needs to load the program before that is invisible to
// the app; app-diag.sh measures it from outside (README section 18).
(:debug)
function firstFrame() as Void {
var stats = System.getSystemStats();
System.println("DIAG first_frame startup_ms=" + (System.getTimer() - startMs)
+ " mem_used=" + stats.usedMemory + " mem_total=" + stats.totalMemory);
}
(:release)
function firstFrame() as Void {
}
// A screen finished its first draw since it was shown.
(:debug)
function shown(screen as String) as Void {
System.println("DIAG shown " + screen);
}
(:release)
function shown(screen as String) as Void {
}
// Free-form key=value data for UI scripts (never secrets).
(:debug)
function data(event as String, values as String) as Void {
System.println("DIAG " + event + " " + values);
}
(:release)
function data(event as String, values as String) as Void {
}
// The performance overlay (toggled in the debug menu): draw time of the
// frame that started at startMs, and memory use.
(:debug)
var overlayOn as Boolean = false;
(:debug)
function overlay(dc as Graphics.Dc, frameStartMs as Number) as Void {
if (!overlayOn) {
return;
}
var stats = System.getSystemStats();
var text = (System.getTimer() - frameStartMs) + " ms " + (stats.usedMemory * 100 / stats.totalMemory) + "% mem";
dc.setColor(Graphics.COLOR_YELLOW, Graphics.COLOR_BLACK);
dc.drawText(dc.getWidth() / 2, dc.getHeight() - dc.getFontHeight(Graphics.FONT_XTINY) - 2, Graphics.FONT_XTINY,
text, Graphics.TEXT_JUSTIFY_CENTER);
}
(:release)
function overlay(dc as Graphics.Dc, frameStartMs as Number) as Void {
}
// Peak memory while long work runs (sampled by the import job).
(:debug)
var peakMemory as Number = 0;
(:debug)
function sampleMemory() as Void {
var used = System.getSystemStats().usedMemory;
if (used > peakMemory) {
peakMemory = used;
}
}
(:release)
function sampleMemory() as Void {
}
// Reports an import's size, duration and peak memory for UI scripts.
(:debug)
function importDone(entries as Number, wallMs as Number) as Void {
System.println("DIAG import entries=" + entries + " wall_ms=" + wallMs + " mem_peak=" + peakMemory
+ " mem_total=" + System.getSystemStats().totalMemory);
}
(:release)
function importDone(entries as Number, wallMs as Number) as Void {
}
}
|