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
|
// Author: cirakg & claude ai
// Summary: Debug-only menu items: load demo entries, the performance overlay and the on-watch benchmark.
//
// Release builds compile the empty (:release) module instead, so none of this
// reaches the Store build. The benchmark is how the watch's real speed gets
// measured (docs/PERFORMANCE.md): sideload a debug build and run it.
import Toybox.Lang;
import Toybox.System;
import Toybox.Timer;
import Toybox.WatchUi;
(:debug)
module DebugMenu {
function addItems(menu as WatchUi.Menu2) as Void {
menu.addItem(new WatchUi.MenuItem("Debug: demo entries", "Adds fake entries", :debugDemo, null));
menu.addItem(new WatchUi.MenuItem("Debug: overlay", Diag.overlayOn ? "On" : "Off", :debugOverlay, null));
menu.addItem(new WatchUi.MenuItem("Debug: benchmark", "Takes a few seconds", :debugBench, null));
}
function handle(id as Object?) as Void {
if (id == :debugDemo) {
try {
Fixtures.load(AppState.theVault());
} catch (e instanceof VaultError) {
// Entry cap or full store: load what fits.
}
AppState.theCodes().clear();
WatchUi.popView(WatchUi.SLIDE_DOWN);
} else if (id == :debugOverlay) {
Diag.overlayOn = !Diag.overlayOn;
WatchUi.popView(WatchUi.SLIDE_DOWN);
} else if (id == :debugBench) {
var runner = new BenchRunner();
bench = runner;
WatchUi.switchToView(new InfoView("Benchmark", ["Measuring…"], "bench_running"), new InfoDelegate(),
WatchUi.SLIDE_LEFT);
runner.start();
}
}
// The running benchmark (kept so its timer isn't collected).
var bench as BenchRunner? = null;
// Times the operations the budgets depend on, one per timer event, so no
// event comes near the watchdog limit (it is enforced on the watch and in
// normal simulator runs).
class BenchRunner {
private var _lines as Array<String> = [] as Array<String>;
private var _step as Number = 0;
private var _timer as Timer.Timer? = null;
function initialize() {
}
function start() as Void {
var t = new Timer.Timer();
t.start(method(:tick), 200, true);
_timer = t;
}
function tick() as Void {
var t = System.getTimer();
if (_step == 0) {
for (var i = 0; i < 5; i++) {
Otp.totp(Hashes.SHA1, new [20]b, 1800000000l, 30, 6);
}
_lines.add("TOTP SHA-1: " + (System.getTimer() - t) / 5 + " ms");
} else if (_step == 1) {
Otp.totp(Hashes.SHA512, new [64]b, 1800000000l, 30, 6);
_lines.add("TOTP SHA-512: " + (System.getTimer() - t) + " ms");
} else if (_step == 2) {
_lines.add("PIN derivation: " + Kdf.calibrate(1000, Kdf.ITERATIONS_PER_STEP) + " iterations per second");
} else if (_step == 3) {
var vault = AppState.theVault();
var ids = vault.ids();
for (var i = 0; i < ids.size(); i++) {
vault.header(ids[i]);
}
_lines.add("Headers: " + ids.size() + " in " + (System.getTimer() - t) + " ms");
} else if (_step == 4) {
SelfTest.run();
_lines.add("Self-test: " + (System.getTimer() - t) + " ms");
} else {
var stats = System.getSystemStats();
_lines.add("Memory: " + stats.usedMemory / 1024 + " of " + stats.totalMemory / 1024 + " KB");
var timer = _timer;
if (timer != null) {
timer.stop();
}
bench = null;
WatchUi.switchToView(new InfoView("Benchmark", _lines, "bench"), new InfoDelegate(), WatchUi.SLIDE_IMMEDIATE);
return;
}
_step++;
}
}
}
(:release)
module DebugMenu {
function addItems(menu as WatchUi.Menu2) as Void {
}
function handle(id as Object?) as Void {
}
}
|