deepadb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +631 -0
- package/build/bridge/adb-bridge.d.ts +65 -0
- package/build/bridge/adb-bridge.d.ts.map +1 -0
- package/build/bridge/adb-bridge.js +164 -0
- package/build/bridge/adb-bridge.js.map +1 -0
- package/build/bridge/device-manager.d.ts +41 -0
- package/build/bridge/device-manager.d.ts.map +1 -0
- package/build/bridge/device-manager.js +109 -0
- package/build/bridge/device-manager.js.map +1 -0
- package/build/bridge/local-bridge.d.ts +92 -0
- package/build/bridge/local-bridge.d.ts.map +1 -0
- package/build/bridge/local-bridge.js +345 -0
- package/build/bridge/local-bridge.js.map +1 -0
- package/build/config/config.d.ts +39 -0
- package/build/config/config.d.ts.map +1 -0
- package/build/config/config.js +84 -0
- package/build/config/config.js.map +1 -0
- package/build/graphql-api.d.ts +36 -0
- package/build/graphql-api.d.ts.map +1 -0
- package/build/graphql-api.js +296 -0
- package/build/graphql-api.js.map +1 -0
- package/build/http-transport.d.ts +26 -0
- package/build/http-transport.d.ts.map +1 -0
- package/build/http-transport.js +105 -0
- package/build/http-transport.js.map +1 -0
- package/build/index.d.ts +14 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +66 -0
- package/build/index.js.map +1 -0
- package/build/middleware/chipset.d.ts +29 -0
- package/build/middleware/chipset.d.ts.map +1 -0
- package/build/middleware/chipset.js +123 -0
- package/build/middleware/chipset.js.map +1 -0
- package/build/middleware/cleanup.d.ts +24 -0
- package/build/middleware/cleanup.d.ts.map +1 -0
- package/build/middleware/cleanup.js +53 -0
- package/build/middleware/cleanup.js.map +1 -0
- package/build/middleware/fetch-utils.d.ts +19 -0
- package/build/middleware/fetch-utils.d.ts.map +1 -0
- package/build/middleware/fetch-utils.js +64 -0
- package/build/middleware/fetch-utils.js.map +1 -0
- package/build/middleware/logger.d.ts +17 -0
- package/build/middleware/logger.d.ts.map +1 -0
- package/build/middleware/logger.js +38 -0
- package/build/middleware/logger.js.map +1 -0
- package/build/middleware/output-processor.d.ts +57 -0
- package/build/middleware/output-processor.d.ts.map +1 -0
- package/build/middleware/output-processor.js +162 -0
- package/build/middleware/output-processor.js.map +1 -0
- package/build/middleware/sanitize.d.ts +30 -0
- package/build/middleware/sanitize.d.ts.map +1 -0
- package/build/middleware/sanitize.js +46 -0
- package/build/middleware/sanitize.js.map +1 -0
- package/build/middleware/security.d.ts +52 -0
- package/build/middleware/security.d.ts.map +1 -0
- package/build/middleware/security.js +123 -0
- package/build/middleware/security.js.map +1 -0
- package/build/middleware/ui-dump.d.ts +23 -0
- package/build/middleware/ui-dump.d.ts.map +1 -0
- package/build/middleware/ui-dump.js +59 -0
- package/build/middleware/ui-dump.js.map +1 -0
- package/build/server.d.ts +18 -0
- package/build/server.d.ts.map +1 -0
- package/build/server.js +133 -0
- package/build/server.js.map +1 -0
- package/build/tool-context.d.ts +22 -0
- package/build/tool-context.d.ts.map +1 -0
- package/build/tool-context.js +9 -0
- package/build/tool-context.js.map +1 -0
- package/build/tools/accessibility.d.ts +10 -0
- package/build/tools/accessibility.d.ts.map +1 -0
- package/build/tools/accessibility.js +259 -0
- package/build/tools/accessibility.js.map +1 -0
- package/build/tools/at-commands.d.ts +20 -0
- package/build/tools/at-commands.d.ts.map +1 -0
- package/build/tools/at-commands.js +378 -0
- package/build/tools/at-commands.js.map +1 -0
- package/build/tools/baseband.d.ts +15 -0
- package/build/tools/baseband.d.ts.map +1 -0
- package/build/tools/baseband.js +323 -0
- package/build/tools/baseband.js.map +1 -0
- package/build/tools/build.d.ts +6 -0
- package/build/tools/build.d.ts.map +1 -0
- package/build/tools/build.js +80 -0
- package/build/tools/build.js.map +1 -0
- package/build/tools/ci.d.ts +9 -0
- package/build/tools/ci.d.ts.map +1 -0
- package/build/tools/ci.js +163 -0
- package/build/tools/ci.js.map +1 -0
- package/build/tools/control.d.ts +10 -0
- package/build/tools/control.d.ts.map +1 -0
- package/build/tools/control.js +197 -0
- package/build/tools/control.js.map +1 -0
- package/build/tools/device-farm.d.ts +10 -0
- package/build/tools/device-farm.d.ts.map +1 -0
- package/build/tools/device-farm.js +140 -0
- package/build/tools/device-farm.js.map +1 -0
- package/build/tools/device-profiles.d.ts +16 -0
- package/build/tools/device-profiles.d.ts.map +1 -0
- package/build/tools/device-profiles.js +272 -0
- package/build/tools/device-profiles.js.map +1 -0
- package/build/tools/device.d.ts +6 -0
- package/build/tools/device.d.ts.map +1 -0
- package/build/tools/device.js +72 -0
- package/build/tools/device.js.map +1 -0
- package/build/tools/diagnostics.d.ts +7 -0
- package/build/tools/diagnostics.d.ts.map +1 -0
- package/build/tools/diagnostics.js +153 -0
- package/build/tools/diagnostics.js.map +1 -0
- package/build/tools/emulator.d.ts +9 -0
- package/build/tools/emulator.d.ts.map +1 -0
- package/build/tools/emulator.js +223 -0
- package/build/tools/emulator.js.map +1 -0
- package/build/tools/files.d.ts +6 -0
- package/build/tools/files.d.ts.map +1 -0
- package/build/tools/files.js +78 -0
- package/build/tools/files.js.map +1 -0
- package/build/tools/firmware-analysis.d.ts +24 -0
- package/build/tools/firmware-analysis.d.ts.map +1 -0
- package/build/tools/firmware-analysis.js +623 -0
- package/build/tools/firmware-analysis.js.map +1 -0
- package/build/tools/forwarding.d.ts +7 -0
- package/build/tools/forwarding.d.ts.map +1 -0
- package/build/tools/forwarding.js +64 -0
- package/build/tools/forwarding.js.map +1 -0
- package/build/tools/health.d.ts +7 -0
- package/build/tools/health.d.ts.map +1 -0
- package/build/tools/health.js +112 -0
- package/build/tools/health.js.map +1 -0
- package/build/tools/logcat-watch.d.ts +11 -0
- package/build/tools/logcat-watch.d.ts.map +1 -0
- package/build/tools/logcat-watch.js +209 -0
- package/build/tools/logcat-watch.js.map +1 -0
- package/build/tools/logs.d.ts +6 -0
- package/build/tools/logs.d.ts.map +1 -0
- package/build/tools/logs.js +83 -0
- package/build/tools/logs.js.map +1 -0
- package/build/tools/mirroring.d.ts +14 -0
- package/build/tools/mirroring.d.ts.map +1 -0
- package/build/tools/mirroring.js +243 -0
- package/build/tools/mirroring.js.map +1 -0
- package/build/tools/multi-device.d.ts +9 -0
- package/build/tools/multi-device.d.ts.map +1 -0
- package/build/tools/multi-device.js +138 -0
- package/build/tools/multi-device.js.map +1 -0
- package/build/tools/network-capture.d.ts +10 -0
- package/build/tools/network-capture.d.ts.map +1 -0
- package/build/tools/network-capture.js +143 -0
- package/build/tools/network-capture.js.map +1 -0
- package/build/tools/network-discovery.d.ts +21 -0
- package/build/tools/network-discovery.d.ts.map +1 -0
- package/build/tools/network-discovery.js +284 -0
- package/build/tools/network-discovery.js.map +1 -0
- package/build/tools/ota-monitor.d.ts +16 -0
- package/build/tools/ota-monitor.d.ts.map +1 -0
- package/build/tools/ota-monitor.js +211 -0
- package/build/tools/ota-monitor.js.map +1 -0
- package/build/tools/packages.d.ts +6 -0
- package/build/tools/packages.d.ts.map +1 -0
- package/build/tools/packages.js +237 -0
- package/build/tools/packages.js.map +1 -0
- package/build/tools/plugins.d.ts +22 -0
- package/build/tools/plugins.d.ts.map +1 -0
- package/build/tools/plugins.js +118 -0
- package/build/tools/plugins.js.map +1 -0
- package/build/tools/prompts.d.ts +9 -0
- package/build/tools/prompts.d.ts.map +1 -0
- package/build/tools/prompts.js +94 -0
- package/build/tools/prompts.js.map +1 -0
- package/build/tools/qemu.d.ts +18 -0
- package/build/tools/qemu.d.ts.map +1 -0
- package/build/tools/qemu.js +791 -0
- package/build/tools/qemu.js.map +1 -0
- package/build/tools/registry.d.ts +13 -0
- package/build/tools/registry.d.ts.map +1 -0
- package/build/tools/registry.js +221 -0
- package/build/tools/registry.js.map +1 -0
- package/build/tools/regression.d.ts +10 -0
- package/build/tools/regression.d.ts.map +1 -0
- package/build/tools/regression.js +215 -0
- package/build/tools/regression.js.map +1 -0
- package/build/tools/resources.d.ts +10 -0
- package/build/tools/resources.d.ts.map +1 -0
- package/build/tools/resources.js +77 -0
- package/build/tools/resources.js.map +1 -0
- package/build/tools/ril-intercept.d.ts +24 -0
- package/build/tools/ril-intercept.d.ts.map +1 -0
- package/build/tools/ril-intercept.js +273 -0
- package/build/tools/ril-intercept.js.map +1 -0
- package/build/tools/screen-record.d.ts +9 -0
- package/build/tools/screen-record.d.ts.map +1 -0
- package/build/tools/screen-record.js +95 -0
- package/build/tools/screen-record.js.map +1 -0
- package/build/tools/screenshot-diff.d.ts +13 -0
- package/build/tools/screenshot-diff.d.ts.map +1 -0
- package/build/tools/screenshot-diff.js +370 -0
- package/build/tools/screenshot-diff.js.map +1 -0
- package/build/tools/selinux-audit.d.ts +17 -0
- package/build/tools/selinux-audit.d.ts.map +1 -0
- package/build/tools/selinux-audit.js +301 -0
- package/build/tools/selinux-audit.js.map +1 -0
- package/build/tools/shell.d.ts +6 -0
- package/build/tools/shell.d.ts.map +1 -0
- package/build/tools/shell.js +63 -0
- package/build/tools/shell.js.map +1 -0
- package/build/tools/snapshot.d.ts +9 -0
- package/build/tools/snapshot.d.ts.map +1 -0
- package/build/tools/snapshot.js +192 -0
- package/build/tools/snapshot.js.map +1 -0
- package/build/tools/split-apk.d.ts +13 -0
- package/build/tools/split-apk.d.ts.map +1 -0
- package/build/tools/split-apk.js +229 -0
- package/build/tools/split-apk.js.map +1 -0
- package/build/tools/test-gen.d.ts +14 -0
- package/build/tools/test-gen.d.ts.map +1 -0
- package/build/tools/test-gen.js +252 -0
- package/build/tools/test-gen.js.map +1 -0
- package/build/tools/testing.d.ts +9 -0
- package/build/tools/testing.d.ts.map +1 -0
- package/build/tools/testing.js +144 -0
- package/build/tools/testing.js.map +1 -0
- package/build/tools/thermal-power.d.ts +19 -0
- package/build/tools/thermal-power.d.ts.map +1 -0
- package/build/tools/thermal-power.js +330 -0
- package/build/tools/thermal-power.js.map +1 -0
- package/build/tools/ui.d.ts +6 -0
- package/build/tools/ui.d.ts.map +1 -0
- package/build/tools/ui.js +266 -0
- package/build/tools/ui.js.map +1 -0
- package/build/tools/wireless.d.ts +7 -0
- package/build/tools/wireless.d.ts.map +1 -0
- package/build/tools/wireless.js +78 -0
- package/build/tools/wireless.js.map +1 -0
- package/build/tools/workflow-market.d.ts +17 -0
- package/build/tools/workflow-market.d.ts.map +1 -0
- package/build/tools/workflow-market.js +237 -0
- package/build/tools/workflow-market.js.map +1 -0
- package/build/tools/workflow.d.ts +32 -0
- package/build/tools/workflow.d.ts.map +1 -0
- package/build/tools/workflow.js +374 -0
- package/build/tools/workflow.js.map +1 -0
- package/build/ws-transport.d.ts +30 -0
- package/build/ws-transport.d.ts.map +1 -0
- package/build/ws-transport.js +133 -0
- package/build/ws-transport.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Session Tools — Structured test workflow organization.
|
|
3
|
+
*
|
|
4
|
+
* Captures numbered test steps with screenshots and logcat into
|
|
5
|
+
* organized directories for reproducibility and documentation.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
10
|
+
import { OutputProcessor } from "../middleware/output-processor.js";
|
|
11
|
+
import { isOnDevice } from "../config/config.js";
|
|
12
|
+
import { shellEscape } from "../middleware/sanitize.js";
|
|
13
|
+
/** Active test session. Only one at a time. */
|
|
14
|
+
let activeSession = null;
|
|
15
|
+
export function registerTestingTools(ctx) {
|
|
16
|
+
ctx.server.tool("adb_test_session_start", "Start a structured test session. Creates a named directory for organizing numbered screenshots and logcat captures.", {
|
|
17
|
+
name: z.string().describe("Test session name (e.g., 'login_flow', 'threat_detection')"),
|
|
18
|
+
device: z.string().optional().describe("Device serial"),
|
|
19
|
+
}, async ({ name, device }) => {
|
|
20
|
+
try {
|
|
21
|
+
if (activeSession) {
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: "text", text: `Session '${activeSession.name}' is already active. Stop it first with adb_test_session_end.` }],
|
|
24
|
+
isError: true,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const resolved = await ctx.deviceManager.resolveDevice(device);
|
|
28
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").substring(0, 19);
|
|
29
|
+
const safeName = name.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
30
|
+
const dirName = `${safeName}_${timestamp}`;
|
|
31
|
+
const directory = join(ctx.config.tempDir, "tests", dirName);
|
|
32
|
+
mkdirSync(directory, { recursive: true });
|
|
33
|
+
// Clear logcat so our captures start fresh
|
|
34
|
+
await ctx.bridge.shell("logcat -c", { device: resolved.serial, ignoreExitCode: true });
|
|
35
|
+
activeSession = {
|
|
36
|
+
name,
|
|
37
|
+
directory,
|
|
38
|
+
device: resolved.serial,
|
|
39
|
+
stepCount: 0,
|
|
40
|
+
startedAt: Date.now(),
|
|
41
|
+
steps: [],
|
|
42
|
+
lastLogcatTimestamp: Date.now(),
|
|
43
|
+
};
|
|
44
|
+
// Write session manifest header
|
|
45
|
+
const manifest = `# Test Session: ${name}\n`
|
|
46
|
+
+ `Started: ${new Date().toISOString()}\n`
|
|
47
|
+
+ `Device: ${resolved.serial}\n\n`
|
|
48
|
+
+ `## Steps\n\n`;
|
|
49
|
+
writeFileSync(join(directory, "steps.md"), manifest);
|
|
50
|
+
return {
|
|
51
|
+
content: [{
|
|
52
|
+
type: "text",
|
|
53
|
+
text: `Test session started: ${name}\nDirectory: ${directory}\nDevice: ${resolved.serial}\nLogcat cleared. Use adb_test_step to capture numbered steps.`,
|
|
54
|
+
}],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
ctx.server.tool("adb_test_step", "Capture a numbered test step: takes a screenshot and captures logcat since the last step. Saves both to the session directory.", {
|
|
62
|
+
description: z.string().describe("Description of what this step tests or verifies"),
|
|
63
|
+
captureScreenshot: z.boolean().optional().default(true).describe("Take a screenshot for this step"),
|
|
64
|
+
captureLogcat: z.boolean().optional().default(true).describe("Capture logcat since last step"),
|
|
65
|
+
}, async ({ description, captureScreenshot, captureLogcat }) => {
|
|
66
|
+
if (!activeSession) {
|
|
67
|
+
return { content: [{ type: "text", text: "No active test session. Start one with adb_test_session_start." }], isError: true };
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const session = activeSession;
|
|
71
|
+
session.stepCount++;
|
|
72
|
+
const stepNum = String(session.stepCount).padStart(3, "0");
|
|
73
|
+
const stepPrefix = `${stepNum}_${description.replace(/[^a-zA-Z0-9_-]/g, "_").substring(0, 40)}`;
|
|
74
|
+
const results = [`Step ${stepNum}: ${description}`];
|
|
75
|
+
// Screenshot
|
|
76
|
+
if (captureScreenshot) {
|
|
77
|
+
const screenshotFile = `${stepPrefix}.png`;
|
|
78
|
+
const remoteDir = isOnDevice() ? "/data/local/tmp" : "/sdcard";
|
|
79
|
+
const remotePath = `${remoteDir}/DA_test_${stepNum}.png`;
|
|
80
|
+
const localPath = join(session.directory, screenshotFile);
|
|
81
|
+
try {
|
|
82
|
+
await ctx.bridge.shell(`screencap -p '${shellEscape(remotePath)}'`, { device: session.device, timeout: 15000 });
|
|
83
|
+
await ctx.bridge.exec(["pull", remotePath, localPath], { device: session.device, timeout: 30000 });
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
await ctx.bridge.shell(`rm '${shellEscape(remotePath)}'`, { device: session.device, ignoreExitCode: true }).catch(() => { });
|
|
87
|
+
}
|
|
88
|
+
results.push(`Screenshot: ${screenshotFile}`);
|
|
89
|
+
}
|
|
90
|
+
// Logcat since last step
|
|
91
|
+
if (captureLogcat) {
|
|
92
|
+
const logcatFile = `${stepPrefix}_logcat.txt`;
|
|
93
|
+
const localPath = join(session.directory, logcatFile);
|
|
94
|
+
const logResult = await ctx.bridge.shell("logcat -d -t 500", {
|
|
95
|
+
device: session.device, timeout: 10000, ignoreExitCode: true,
|
|
96
|
+
});
|
|
97
|
+
writeFileSync(localPath, logResult.stdout);
|
|
98
|
+
// Clear for next step
|
|
99
|
+
await ctx.bridge.shell("logcat -c", { device: session.device, ignoreExitCode: true });
|
|
100
|
+
const lineCount = logResult.stdout.split("\n").filter((l) => l.trim()).length;
|
|
101
|
+
results.push(`Logcat: ${logcatFile} (${lineCount} lines)`);
|
|
102
|
+
}
|
|
103
|
+
// Update manifest
|
|
104
|
+
const stepEntry = `### Step ${stepNum}: ${description}\n`
|
|
105
|
+
+ `Timestamp: ${new Date().toISOString()}\n`
|
|
106
|
+
+ results.slice(1).map((r) => `- ${r}`).join("\n") + "\n\n";
|
|
107
|
+
const manifestPath = join(session.directory, "steps.md");
|
|
108
|
+
writeFileSync(manifestPath, stepEntry, { flag: "a" });
|
|
109
|
+
session.steps.push({
|
|
110
|
+
number: session.stepCount,
|
|
111
|
+
description,
|
|
112
|
+
timestamp: new Date().toISOString(),
|
|
113
|
+
});
|
|
114
|
+
session.lastLogcatTimestamp = Date.now();
|
|
115
|
+
return { content: [{ type: "text", text: results.join("\n") }] };
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
ctx.server.tool("adb_test_session_end", "End the active test session. Writes a summary manifest and returns the session directory path.", {}, async () => {
|
|
122
|
+
if (!activeSession) {
|
|
123
|
+
return { content: [{ type: "text", text: "No active test session." }], isError: true };
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const session = activeSession;
|
|
127
|
+
const elapsed = ((Date.now() - session.startedAt) / 1000).toFixed(1);
|
|
128
|
+
// Write summary footer to manifest
|
|
129
|
+
const summary = `---\n\n## Summary\n`
|
|
130
|
+
+ `Total steps: ${session.stepCount}\n`
|
|
131
|
+
+ `Duration: ${elapsed}s\n`
|
|
132
|
+
+ `Ended: ${new Date().toISOString()}\n`;
|
|
133
|
+
const manifestPath = join(session.directory, "steps.md");
|
|
134
|
+
writeFileSync(manifestPath, summary, { flag: "a" });
|
|
135
|
+
const result = `Test session '${session.name}' ended.\nSteps captured: ${session.stepCount}\nDuration: ${elapsed}s\nDirectory: ${session.directory}`;
|
|
136
|
+
activeSession = null;
|
|
137
|
+
return { content: [{ type: "text", text: result }] };
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../../src/tools/testing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thermal & Power Profiling — Temperature, CPU frequency, and battery drain analysis.
|
|
3
|
+
*
|
|
4
|
+
* Captures thermal zone temperatures, CPU frequency scaling states, cooling
|
|
5
|
+
* device activity, and battery drain rates. Complements the existing regression
|
|
6
|
+
* detection module by providing baselines for issues that manifest as heat or
|
|
7
|
+
* battery drain rather than frame drops or memory growth.
|
|
8
|
+
*
|
|
9
|
+
* Data sources:
|
|
10
|
+
* - /sys/class/thermal/thermal_zone{n}/ — temperature readings per zone
|
|
11
|
+
* - /sys/devices/system/cpu/cpu{n}/cpufreq/ — CPU frequency and governor
|
|
12
|
+
* - /sys/class/power_supply/battery/ — detailed battery state
|
|
13
|
+
* - dumpsys batterystats — historical battery usage statistics
|
|
14
|
+
*
|
|
15
|
+
* All sysfs reads use hardcoded paths — no user input reaches shell interpolation.
|
|
16
|
+
*/
|
|
17
|
+
import { ToolContext } from "../tool-context.js";
|
|
18
|
+
export declare function registerThermalPowerTools(ctx: ToolContext): void;
|
|
19
|
+
//# sourceMappingURL=thermal-power.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thermal-power.d.ts","sourceRoot":"","sources":["../../src/tools/thermal-power.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAgBjD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAoXhE"}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thermal & Power Profiling — Temperature, CPU frequency, and battery drain analysis.
|
|
3
|
+
*
|
|
4
|
+
* Captures thermal zone temperatures, CPU frequency scaling states, cooling
|
|
5
|
+
* device activity, and battery drain rates. Complements the existing regression
|
|
6
|
+
* detection module by providing baselines for issues that manifest as heat or
|
|
7
|
+
* battery drain rather than frame drops or memory growth.
|
|
8
|
+
*
|
|
9
|
+
* Data sources:
|
|
10
|
+
* - /sys/class/thermal/thermal_zone{n}/ — temperature readings per zone
|
|
11
|
+
* - /sys/devices/system/cpu/cpu{n}/cpufreq/ — CPU frequency and governor
|
|
12
|
+
* - /sys/class/power_supply/battery/ — detailed battery state
|
|
13
|
+
* - dumpsys batterystats — historical battery usage statistics
|
|
14
|
+
*
|
|
15
|
+
* All sysfs reads use hardcoded paths — no user input reaches shell interpolation.
|
|
16
|
+
*/
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
import { join } from "path";
|
|
19
|
+
import { mkdirSync, writeFileSync, readFileSync, existsSync, readdirSync } from "fs";
|
|
20
|
+
import { OutputProcessor } from "../middleware/output-processor.js";
|
|
21
|
+
import { validateShellArg } from "../middleware/sanitize.js";
|
|
22
|
+
function getThermalDir(tempDir) {
|
|
23
|
+
return join(tempDir, "thermal-profiles");
|
|
24
|
+
}
|
|
25
|
+
export function registerThermalPowerTools(ctx) {
|
|
26
|
+
ctx.server.tool("adb_thermal_snapshot", "Capture a thermal and power snapshot: all thermal zone temperatures, per-CPU frequencies and governors, cooling device states, and battery temperature/current draw. Optionally save as a baseline for later comparison.", {
|
|
27
|
+
save: z.boolean().optional().default(false).describe("Save snapshot as a baseline JSON file"),
|
|
28
|
+
label: z.string().optional().default("snapshot").describe("Label for saved baseline"),
|
|
29
|
+
device: z.string().optional().describe("Device serial"),
|
|
30
|
+
}, async ({ save, label, device }) => {
|
|
31
|
+
try {
|
|
32
|
+
const resolved = await ctx.deviceManager.resolveDevice(device);
|
|
33
|
+
const serial = resolved.serial;
|
|
34
|
+
const sections = [];
|
|
35
|
+
sections.push("=== Thermal & Power Snapshot ===");
|
|
36
|
+
// Read thermal zones
|
|
37
|
+
const thermalResult = await ctx.bridge.shell("for z in /sys/class/thermal/thermal_zone*; do " +
|
|
38
|
+
"echo \"ZONE:$(basename $z):$(cat $z/type 2>/dev/null):$(cat $z/temp 2>/dev/null)\"; " +
|
|
39
|
+
"done 2>/dev/null", { device: serial, timeout: 10000, ignoreExitCode: true });
|
|
40
|
+
const zones = [];
|
|
41
|
+
for (const line of thermalResult.stdout.split("\n")) {
|
|
42
|
+
const match = line.match(/^ZONE:(\S+):(\S*):(\d+)/);
|
|
43
|
+
if (match) {
|
|
44
|
+
const tempC = parseInt(match[3], 10) / 1000; // millidegrees to degrees
|
|
45
|
+
zones.push({ name: match[1], type: match[2] || "unknown", temp: tempC });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (zones.length > 0) {
|
|
49
|
+
sections.push(`\nThermal zones (${zones.length}):`);
|
|
50
|
+
const maxTemp = Math.max(...zones.map((z) => z.temp));
|
|
51
|
+
for (const z of zones) {
|
|
52
|
+
const warn = z.temp > 55 ? " 🔥 CRITICAL" : z.temp > 45 ? " ⚠ HOT" : "";
|
|
53
|
+
sections.push(` ${z.name} [${z.type}]: ${z.temp.toFixed(1)}°C${warn}`);
|
|
54
|
+
}
|
|
55
|
+
sections.push(` Peak: ${maxTemp.toFixed(1)}°C`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
sections.push("\nThermal zones: not accessible (may require root)");
|
|
59
|
+
}
|
|
60
|
+
// Read CPU frequencies
|
|
61
|
+
const cpuResult = await ctx.bridge.shell("for c in /sys/devices/system/cpu/cpu[0-9]*; do " +
|
|
62
|
+
"echo \"CPU:$(basename $c):" +
|
|
63
|
+
"$(cat $c/cpufreq/scaling_cur_freq 2>/dev/null || echo 0):" +
|
|
64
|
+
"$(cat $c/cpufreq/scaling_max_freq 2>/dev/null || echo 0):" +
|
|
65
|
+
"$(cat $c/cpufreq/scaling_min_freq 2>/dev/null || echo 0):" +
|
|
66
|
+
"$(cat $c/cpufreq/scaling_governor 2>/dev/null || echo unknown)\"; " +
|
|
67
|
+
"done 2>/dev/null", { device: serial, timeout: 10000, ignoreExitCode: true });
|
|
68
|
+
const cpus = [];
|
|
69
|
+
for (const line of cpuResult.stdout.split("\n")) {
|
|
70
|
+
const match = line.match(/^CPU:cpu(\d+):(\d+):(\d+):(\d+):(\S+)/);
|
|
71
|
+
if (match) {
|
|
72
|
+
cpus.push({
|
|
73
|
+
cpu: parseInt(match[1], 10),
|
|
74
|
+
curFreqMhz: parseInt(match[2], 10) / 1000,
|
|
75
|
+
maxFreqMhz: parseInt(match[3], 10) / 1000,
|
|
76
|
+
minFreqMhz: parseInt(match[4], 10) / 1000,
|
|
77
|
+
governor: match[5],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (cpus.length > 0) {
|
|
82
|
+
sections.push(`\nCPU frequencies (${cpus.length} cores):`);
|
|
83
|
+
for (const c of cpus) {
|
|
84
|
+
const pct = c.maxFreqMhz > 0 ? ((c.curFreqMhz / c.maxFreqMhz) * 100).toFixed(0) : "?";
|
|
85
|
+
sections.push(` cpu${c.cpu}: ${c.curFreqMhz.toFixed(0)} MHz / ${c.maxFreqMhz.toFixed(0)} MHz (${pct}%) [${c.governor}]`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Read battery details from sysfs
|
|
89
|
+
const battResult = await ctx.bridge.shell("echo \"LEVEL:$(cat /sys/class/power_supply/battery/capacity 2>/dev/null)\" && " +
|
|
90
|
+
"echo \"TEMP:$(cat /sys/class/power_supply/battery/temp 2>/dev/null)\" && " +
|
|
91
|
+
"echo \"CURRENT:$(cat /sys/class/power_supply/battery/current_now 2>/dev/null)\" && " +
|
|
92
|
+
"echo \"VOLTAGE:$(cat /sys/class/power_supply/battery/voltage_now 2>/dev/null)\" && " +
|
|
93
|
+
"echo \"STATUS:$(cat /sys/class/power_supply/battery/status 2>/dev/null)\"", { device: serial, timeout: 10000, ignoreExitCode: true });
|
|
94
|
+
const battParsed = {};
|
|
95
|
+
for (const line of battResult.stdout.split("\n")) {
|
|
96
|
+
const sep = line.indexOf(":");
|
|
97
|
+
if (sep > 0)
|
|
98
|
+
battParsed[line.substring(0, sep)] = line.substring(sep + 1).trim();
|
|
99
|
+
}
|
|
100
|
+
const battLevel = parseInt(battParsed["LEVEL"] ?? "0", 10);
|
|
101
|
+
const battTemp = parseInt(battParsed["TEMP"] ?? "0", 10) / 10;
|
|
102
|
+
const battCurrent = parseInt(battParsed["CURRENT"] ?? "0", 10) / 1000; // μA to mA
|
|
103
|
+
const battVoltage = parseInt(battParsed["VOLTAGE"] ?? "0", 10) / 1000000; // μV to V
|
|
104
|
+
const battStatus = battParsed["STATUS"] ?? "unknown";
|
|
105
|
+
sections.push(`\nBattery:`);
|
|
106
|
+
sections.push(` Level: ${battLevel}%`);
|
|
107
|
+
sections.push(` Temperature: ${battTemp.toFixed(1)}°C${battTemp > 40 ? " ⚠ WARM" : ""}`);
|
|
108
|
+
sections.push(` Current: ${battCurrent.toFixed(0)} mA${battCurrent < 0 ? " (discharging)" : " (charging)"}`);
|
|
109
|
+
sections.push(` Voltage: ${battVoltage.toFixed(2)} V`);
|
|
110
|
+
sections.push(` Status: ${battStatus}`);
|
|
111
|
+
if (battCurrent < 0 && battVoltage > 0) {
|
|
112
|
+
const powerW = Math.abs(battCurrent / 1000) * battVoltage;
|
|
113
|
+
sections.push(` Power draw: ${(powerW * 1000).toFixed(0)} mW (${powerW.toFixed(2)} W)`);
|
|
114
|
+
}
|
|
115
|
+
// Cooling devices
|
|
116
|
+
const coolingResult = await ctx.bridge.shell("for c in /sys/class/thermal/cooling_device*; do " +
|
|
117
|
+
"echo \"COOL:$(basename $c):$(cat $c/type 2>/dev/null):$(cat $c/cur_state 2>/dev/null):$(cat $c/max_state 2>/dev/null)\"; " +
|
|
118
|
+
"done 2>/dev/null | head -20", { device: serial, timeout: 10000, ignoreExitCode: true });
|
|
119
|
+
const coolingLines = coolingResult.stdout.split("\n").filter((l) => l.startsWith("COOL:"));
|
|
120
|
+
if (coolingLines.length > 0) {
|
|
121
|
+
sections.push(`\nCooling devices (${coolingLines.length}):`);
|
|
122
|
+
for (const line of coolingLines) {
|
|
123
|
+
const parts = line.split(":");
|
|
124
|
+
if (parts.length >= 5) {
|
|
125
|
+
const active = parts[3] !== "0" ? " ACTIVE" : "";
|
|
126
|
+
sections.push(` ${parts[1]} [${parts[2]}]: state ${parts[3]}/${parts[4]}${active}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Save if requested
|
|
131
|
+
if (save) {
|
|
132
|
+
const snapshot = {
|
|
133
|
+
timestamp: new Date().toISOString(),
|
|
134
|
+
device: serial,
|
|
135
|
+
zones,
|
|
136
|
+
cpus,
|
|
137
|
+
battery: {
|
|
138
|
+
level: battLevel,
|
|
139
|
+
temperature: battTemp,
|
|
140
|
+
currentNow: battCurrent,
|
|
141
|
+
voltageNow: battVoltage,
|
|
142
|
+
status: battStatus,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
const dir = getThermalDir(ctx.config.tempDir);
|
|
146
|
+
if (!existsSync(dir))
|
|
147
|
+
mkdirSync(dir, { recursive: true });
|
|
148
|
+
const safeLabel = label.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
149
|
+
const safeDevice = serial.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
150
|
+
const filePath = join(dir, `${safeDevice}_${safeLabel}_${Date.now()}.json`);
|
|
151
|
+
writeFileSync(filePath, JSON.stringify(snapshot, null, 2));
|
|
152
|
+
sections.push(`\nSaved: ${filePath}`);
|
|
153
|
+
}
|
|
154
|
+
return { content: [{ type: "text", text: sections.join("\n") }] };
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
ctx.server.tool("adb_thermal_compare", "Compare current thermal/power state against a saved baseline. Reports temperature changes per zone, CPU frequency shifts, and battery drain rate differences.", {
|
|
161
|
+
baselinePath: z.string().optional().describe("Path to baseline JSON. If omitted, uses the most recent baseline for the device."),
|
|
162
|
+
device: z.string().optional().describe("Device serial"),
|
|
163
|
+
}, async ({ baselinePath, device }) => {
|
|
164
|
+
try {
|
|
165
|
+
const resolved = await ctx.deviceManager.resolveDevice(device);
|
|
166
|
+
const serial = resolved.serial;
|
|
167
|
+
// Find baseline
|
|
168
|
+
let savedPath = baselinePath;
|
|
169
|
+
if (!savedPath) {
|
|
170
|
+
const dir = getThermalDir(ctx.config.tempDir);
|
|
171
|
+
if (!existsSync(dir)) {
|
|
172
|
+
return { content: [{ type: "text", text: "No thermal baselines saved. Use adb_thermal_snapshot with save=true first." }], isError: true };
|
|
173
|
+
}
|
|
174
|
+
const safeDevice = serial.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
175
|
+
const files = readdirSync(dir)
|
|
176
|
+
.filter((f) => f.startsWith(safeDevice) && f.endsWith(".json"))
|
|
177
|
+
.sort()
|
|
178
|
+
.reverse();
|
|
179
|
+
if (files.length === 0) {
|
|
180
|
+
return { content: [{ type: "text", text: `No thermal baselines for device ${serial}.` }], isError: true };
|
|
181
|
+
}
|
|
182
|
+
savedPath = join(dir, files[0]);
|
|
183
|
+
}
|
|
184
|
+
if (!existsSync(savedPath)) {
|
|
185
|
+
return { content: [{ type: "text", text: `Baseline not found: ${savedPath}` }], isError: true };
|
|
186
|
+
}
|
|
187
|
+
let baseline;
|
|
188
|
+
try {
|
|
189
|
+
baseline = JSON.parse(readFileSync(savedPath, "utf-8"));
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return { content: [{ type: "text", text: `Corrupt baseline file: ${savedPath}` }], isError: true };
|
|
193
|
+
}
|
|
194
|
+
// Capture current state (reuse the snapshot logic inline)
|
|
195
|
+
const thermalResult = await ctx.bridge.shell("for z in /sys/class/thermal/thermal_zone*; do " +
|
|
196
|
+
"echo \"ZONE:$(basename $z):$(cat $z/type 2>/dev/null):$(cat $z/temp 2>/dev/null)\"; " +
|
|
197
|
+
"done 2>/dev/null", { device: serial, timeout: 10000, ignoreExitCode: true });
|
|
198
|
+
const currentZones = [];
|
|
199
|
+
for (const line of thermalResult.stdout.split("\n")) {
|
|
200
|
+
const match = line.match(/^ZONE:(\S+):(\S*):(\d+)/);
|
|
201
|
+
if (match)
|
|
202
|
+
currentZones.push({ name: match[1], type: match[2] || "unknown", temp: parseInt(match[3], 10) / 1000 });
|
|
203
|
+
}
|
|
204
|
+
const battResult = await ctx.bridge.shell("cat /sys/class/power_supply/battery/temp 2>/dev/null && echo '|' && " +
|
|
205
|
+
"cat /sys/class/power_supply/battery/current_now 2>/dev/null", { device: serial, timeout: 5000, ignoreExitCode: true });
|
|
206
|
+
const battParts = battResult.stdout.split("|").map((s) => s.trim());
|
|
207
|
+
const currentBattTemp = parseInt(battParts[0] ?? "0", 10) / 10;
|
|
208
|
+
const currentBattCurrent = parseInt(battParts[1] ?? "0", 10) / 1000;
|
|
209
|
+
const sections = [];
|
|
210
|
+
sections.push("=== Thermal Comparison ===");
|
|
211
|
+
sections.push(`Baseline: ${baseline.timestamp.substring(0, 19)}`);
|
|
212
|
+
sections.push(`Current: ${new Date().toISOString().substring(0, 19)}\n`);
|
|
213
|
+
// Compare zones
|
|
214
|
+
let zonesHotter = 0;
|
|
215
|
+
let zonesCooler = 0;
|
|
216
|
+
if (currentZones.length > 0 && baseline.zones.length > 0) {
|
|
217
|
+
sections.push("Thermal zones:");
|
|
218
|
+
const baselineMap = new Map(baseline.zones.map((z) => [z.name, z.temp]));
|
|
219
|
+
for (const cz of currentZones) {
|
|
220
|
+
const bTemp = baselineMap.get(cz.name);
|
|
221
|
+
if (bTemp !== undefined) {
|
|
222
|
+
const diff = cz.temp - bTemp;
|
|
223
|
+
const marker = diff > 3 ? " ⚠ HOTTER" : diff < -3 ? " COOLER" : "";
|
|
224
|
+
if (diff > 0)
|
|
225
|
+
zonesHotter++;
|
|
226
|
+
if (diff < 0)
|
|
227
|
+
zonesCooler++;
|
|
228
|
+
sections.push(` ${cz.name}: ${bTemp.toFixed(1)}°C → ${cz.temp.toFixed(1)}°C (${diff > 0 ? "+" : ""}${diff.toFixed(1)}°C)${marker}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// Compare battery
|
|
233
|
+
sections.push("\nBattery:");
|
|
234
|
+
const baseBattTemp = baseline.battery.temperature ?? 0;
|
|
235
|
+
const baseBattCurrent = baseline.battery.currentNow ?? 0;
|
|
236
|
+
const battTempDiff = currentBattTemp - baseBattTemp;
|
|
237
|
+
sections.push(` Temperature: ${baseBattTemp.toFixed(1)}°C → ${currentBattTemp.toFixed(1)}°C (${battTempDiff > 0 ? "+" : ""}${battTempDiff.toFixed(1)}°C)`);
|
|
238
|
+
const currentDiff = currentBattCurrent - baseBattCurrent;
|
|
239
|
+
sections.push(` Current draw: ${baseBattCurrent.toFixed(0)} mA → ${currentBattCurrent.toFixed(0)} mA (${currentDiff > 0 ? "+" : ""}${currentDiff.toFixed(0)} mA)`);
|
|
240
|
+
// Summary
|
|
241
|
+
sections.push("\nSummary:");
|
|
242
|
+
sections.push(` Zones hotter: ${zonesHotter}, cooler: ${zonesCooler}`);
|
|
243
|
+
if (zonesHotter > zonesCooler + 2) {
|
|
244
|
+
sections.push(" ⚠ Device is running significantly hotter than baseline.");
|
|
245
|
+
}
|
|
246
|
+
else if (zonesCooler > zonesHotter + 2) {
|
|
247
|
+
sections.push(" ✓ Device is running cooler than baseline.");
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
sections.push(" ✓ Thermal state is similar to baseline.");
|
|
251
|
+
}
|
|
252
|
+
return { content: [{ type: "text", text: sections.join("\n") }] };
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
ctx.server.tool("adb_battery_drain", "Measure battery drain rate over a specified duration. Takes initial and final readings and calculates mA draw, mW power consumption, and estimated percentage per hour. Useful for profiling power impact of specific operations.", {
|
|
259
|
+
durationMs: z.number().min(3000).max(60000).optional().default(10000).describe("Measurement duration in ms (3s-60s, default 10s)"),
|
|
260
|
+
packageName: z.string().optional().describe("If specified, show battery stats for this package (requires root for detailed stats)"),
|
|
261
|
+
device: z.string().optional().describe("Device serial"),
|
|
262
|
+
}, async ({ durationMs, packageName, device }) => {
|
|
263
|
+
try {
|
|
264
|
+
if (packageName) {
|
|
265
|
+
const pkgErr = validateShellArg(packageName, "packageName");
|
|
266
|
+
if (pkgErr)
|
|
267
|
+
return { content: [{ type: "text", text: pkgErr }], isError: true };
|
|
268
|
+
}
|
|
269
|
+
const resolved = await ctx.deviceManager.resolveDevice(device);
|
|
270
|
+
const serial = resolved.serial;
|
|
271
|
+
const duration = Math.min(Math.max(durationMs, 3000), 60000); // 3-60 seconds
|
|
272
|
+
const readBattery = async () => {
|
|
273
|
+
const result = await ctx.bridge.shell("cat /sys/class/power_supply/battery/capacity 2>/dev/null && echo '|' && " +
|
|
274
|
+
"cat /sys/class/power_supply/battery/temp 2>/dev/null && echo '|' && " +
|
|
275
|
+
"cat /sys/class/power_supply/battery/current_now 2>/dev/null && echo '|' && " +
|
|
276
|
+
"cat /sys/class/power_supply/battery/voltage_now 2>/dev/null", { device: serial, timeout: 5000, ignoreExitCode: true });
|
|
277
|
+
const parts = result.stdout.split("|").map((s) => parseInt(s.trim(), 10));
|
|
278
|
+
return {
|
|
279
|
+
level: parts[0] || 0,
|
|
280
|
+
temp: (parts[1] || 0) / 10,
|
|
281
|
+
current: (parts[2] || 0) / 1000, // μA → mA
|
|
282
|
+
voltage: (parts[3] || 0) / 1000000, // μV → V
|
|
283
|
+
};
|
|
284
|
+
};
|
|
285
|
+
// Initial reading
|
|
286
|
+
const start = await readBattery();
|
|
287
|
+
const startTime = Date.now();
|
|
288
|
+
// Wait
|
|
289
|
+
await new Promise((r) => setTimeout(r, duration));
|
|
290
|
+
// Final reading
|
|
291
|
+
const end = await readBattery();
|
|
292
|
+
const elapsed = (Date.now() - startTime) / 1000;
|
|
293
|
+
const sections = [];
|
|
294
|
+
sections.push(`=== Battery Drain Measurement ===`);
|
|
295
|
+
sections.push(`Duration: ${elapsed.toFixed(1)}s\n`);
|
|
296
|
+
sections.push("Battery state:");
|
|
297
|
+
sections.push(` Level: ${start.level}% → ${end.level}%`);
|
|
298
|
+
sections.push(` Temperature: ${start.temp.toFixed(1)}°C → ${end.temp.toFixed(1)}°C`);
|
|
299
|
+
// Average current draw
|
|
300
|
+
const avgCurrent = (start.current + end.current) / 2;
|
|
301
|
+
const avgVoltage = (start.voltage + end.voltage) / 2;
|
|
302
|
+
sections.push(`\nPower consumption:`);
|
|
303
|
+
sections.push(` Average current: ${Math.abs(avgCurrent).toFixed(0)} mA${avgCurrent < 0 ? " (discharging)" : " (charging)"}`);
|
|
304
|
+
sections.push(` Average voltage: ${avgVoltage.toFixed(2)} V`);
|
|
305
|
+
if (avgCurrent < 0 && avgVoltage > 0) {
|
|
306
|
+
const powerMw = Math.abs(avgCurrent) * avgVoltage;
|
|
307
|
+
sections.push(` Power draw: ${powerMw.toFixed(0)} mW (${(powerMw / 1000).toFixed(2)} W)`);
|
|
308
|
+
// Estimate drain per hour
|
|
309
|
+
// Typical phone battery 3000-5000 mAh
|
|
310
|
+
const drainPerHour = (Math.abs(avgCurrent) / 30); // rough % per hour assuming 3000mAh
|
|
311
|
+
sections.push(` Estimated drain: ~${drainPerHour.toFixed(1)}%/hour (assuming 3000mAh battery)`);
|
|
312
|
+
}
|
|
313
|
+
// Package-specific stats if requested
|
|
314
|
+
if (packageName) {
|
|
315
|
+
const statsResult = await ctx.bridge.shell(`dumpsys batterystats ${packageName} | grep -E 'Uid|Total|Screen|Wifi|Cell|Sensor|Wake' | head -20`, { device: serial, timeout: 10000, ignoreExitCode: true });
|
|
316
|
+
if (statsResult.stdout.trim()) {
|
|
317
|
+
sections.push(`\nBattery stats for ${packageName}:`);
|
|
318
|
+
for (const line of statsResult.stdout.trim().split("\n").slice(0, 15)) {
|
|
319
|
+
sections.push(` ${line.trim()}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return { content: [{ type: "text", text: sections.join("\n") }] };
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=thermal-power.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thermal-power.js","sourceRoot":"","sources":["../../src/tools/thermal-power.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/tools/ui.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAYjD,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAiNtD"}
|