appium-android-driver 12.4.5 → 12.4.7
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/CHANGELOG.md +12 -0
- package/build/lib/commands/app-management.d.ts +167 -113
- package/build/lib/commands/app-management.d.ts.map +1 -1
- package/build/lib/commands/app-management.js +147 -103
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/find.d.ts +20 -3
- package/build/lib/commands/find.d.ts.map +1 -1
- package/build/lib/commands/find.js +10 -3
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/performance.d.ts +80 -51
- package/build/lib/commands/performance.d.ts.map +1 -1
- package/build/lib/commands/performance.js +113 -89
- package/build/lib/commands/performance.js.map +1 -1
- package/build/lib/commands/shell.d.ts +21 -0
- package/build/lib/commands/shell.d.ts.map +1 -1
- package/build/lib/commands/shell.js +21 -0
- package/build/lib/commands/shell.js.map +1 -1
- package/build/lib/commands/streamscreen.d.ts +34 -64
- package/build/lib/commands/streamscreen.d.ts.map +1 -1
- package/build/lib/commands/streamscreen.js +41 -80
- package/build/lib/commands/streamscreen.js.map +1 -1
- package/lib/commands/app-management.ts +639 -0
- package/lib/commands/find.ts +20 -3
- package/lib/commands/{performance.js → performance.ts} +167 -108
- package/lib/commands/shell.ts +21 -0
- package/lib/commands/{streamscreen.js → streamscreen.ts} +86 -109
- package/package.json +2 -2
- package/lib/commands/app-management.js +0 -533
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
// @ts-check
|
|
2
1
|
import {retryInterval} from 'asyncbox';
|
|
3
2
|
import _ from 'lodash';
|
|
3
|
+
import type {AndroidDriver} from '../driver';
|
|
4
|
+
import type {PerformanceDataType} from './types';
|
|
4
5
|
|
|
5
6
|
export const NETWORK_KEYS = [
|
|
6
7
|
[
|
|
@@ -14,9 +15,10 @@ export const NETWORK_KEYS = [
|
|
|
14
15
|
'bucketDuration',
|
|
15
16
|
],
|
|
16
17
|
['st', 'activeTime', 'rb', 'rp', 'tb', 'tp', 'op', 'bucketDuration'],
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
export const
|
|
18
|
+
] as const;
|
|
19
|
+
|
|
20
|
+
export const CPU_KEYS = ['user', 'kernel'] as const;
|
|
21
|
+
export const BATTERY_KEYS = ['power'] as const;
|
|
20
22
|
export const MEMORY_KEYS = [
|
|
21
23
|
'totalPrivateDirty',
|
|
22
24
|
'nativePrivateDirty',
|
|
@@ -33,7 +35,8 @@ export const MEMORY_KEYS = [
|
|
|
33
35
|
'nativeRss',
|
|
34
36
|
'dalvikRss',
|
|
35
37
|
'totalRss',
|
|
36
|
-
];
|
|
38
|
+
] as const;
|
|
39
|
+
|
|
37
40
|
export const SUPPORTED_PERFORMANCE_DATA_TYPES = Object.freeze({
|
|
38
41
|
cpuinfo:
|
|
39
42
|
'the amount of cpu by user and kernel process - cpu information for applications on real devices and simulators',
|
|
@@ -43,7 +46,8 @@ export const SUPPORTED_PERFORMANCE_DATA_TYPES = Object.freeze({
|
|
|
43
46
|
'the remaining battery power - battery power information for applications on real devices and simulators',
|
|
44
47
|
networkinfo:
|
|
45
48
|
'the network statistics - network rx/tx information for applications on real devices and simulators',
|
|
46
|
-
});
|
|
49
|
+
} as const);
|
|
50
|
+
|
|
47
51
|
export const MEMINFO_TITLES = Object.freeze({
|
|
48
52
|
NATIVE: 'Native',
|
|
49
53
|
DALVIK: 'Dalvik',
|
|
@@ -52,41 +56,49 @@ export const MEMINFO_TITLES = Object.freeze({
|
|
|
52
56
|
MTRACK: 'mtrack',
|
|
53
57
|
TOTAL: 'TOTAL',
|
|
54
58
|
HEAP: 'Heap',
|
|
55
|
-
});
|
|
59
|
+
} as const);
|
|
60
|
+
|
|
56
61
|
const RETRY_PAUSE_MS = 1000;
|
|
57
62
|
|
|
58
63
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
64
|
+
* Retrieves the list of available performance data types.
|
|
65
|
+
*
|
|
66
|
+
* @returns An array of supported performance data type names.
|
|
67
|
+
* The possible values are: 'cpuinfo', 'memoryinfo', 'batteryinfo', 'networkinfo'.
|
|
61
68
|
*/
|
|
62
|
-
export async function getPerformanceDataTypes(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
);
|
|
69
|
+
export async function getPerformanceDataTypes(
|
|
70
|
+
this: AndroidDriver,
|
|
71
|
+
): Promise<PerformanceDataType[]> {
|
|
72
|
+
return _.keys(SUPPORTED_PERFORMANCE_DATA_TYPES) as PerformanceDataType[];
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* @param
|
|
72
|
-
*
|
|
73
|
-
* @
|
|
76
|
+
* Retrieves performance data for the specified data type.
|
|
77
|
+
*
|
|
78
|
+
* @param packageName The package name of the application to get performance data for.
|
|
79
|
+
* Required for 'cpuinfo' and 'memoryinfo' data types.
|
|
80
|
+
* @param dataType The type of performance data to retrieve.
|
|
81
|
+
* Must be one of values returned by {@link getPerformanceDataTypes}.
|
|
82
|
+
* @param retries The number of retry attempts if data retrieval fails.
|
|
83
|
+
* @returns A two-dimensional array where the first row contains column names
|
|
84
|
+
* and subsequent rows contain the sampled data values.
|
|
85
|
+
* @throws {Error} If the data type is not supported or data retrieval fails.
|
|
74
86
|
*/
|
|
75
|
-
export async function getPerformanceData(
|
|
76
|
-
|
|
87
|
+
export async function getPerformanceData(
|
|
88
|
+
this: AndroidDriver,
|
|
89
|
+
packageName: string,
|
|
90
|
+
dataType: string,
|
|
91
|
+
retries: number = 2,
|
|
92
|
+
): Promise<any[][]> {
|
|
77
93
|
switch (_.toLower(dataType)) {
|
|
78
94
|
case 'batteryinfo':
|
|
79
|
-
|
|
80
|
-
break;
|
|
95
|
+
return await getBatteryInfo.call(this, retries);
|
|
81
96
|
case 'cpuinfo':
|
|
82
|
-
|
|
83
|
-
break;
|
|
97
|
+
return await getCPUInfo.call(this, packageName, retries);
|
|
84
98
|
case 'memoryinfo':
|
|
85
|
-
|
|
86
|
-
break;
|
|
99
|
+
return await getMemoryInfo.call(this, packageName, retries);
|
|
87
100
|
case 'networkinfo':
|
|
88
|
-
|
|
89
|
-
break;
|
|
101
|
+
return await getNetworkTrafficInfo.call(this, retries);
|
|
90
102
|
default:
|
|
91
103
|
throw new Error(
|
|
92
104
|
`No performance data of type '${dataType}' found. ` +
|
|
@@ -97,7 +109,6 @@ export async function getPerformanceData(packageName, dataType, retries = 2) {
|
|
|
97
109
|
)}`,
|
|
98
110
|
);
|
|
99
111
|
}
|
|
100
|
-
return /** @type {any[][]} */ (result);
|
|
101
112
|
}
|
|
102
113
|
|
|
103
114
|
/**
|
|
@@ -118,13 +129,12 @@ export async function getPerformanceData(packageName, dataType, retries = 2) {
|
|
|
118
129
|
* [1478091600, null, null, 2714683, 11821, 1420564, 12650, 0, 3600], [1478095200, null, null, 10079213, 19962, 2487705, 20015, 0, 3600],
|
|
119
130
|
* [1478098800, null, null, 4444433, 10227, 1430356, 10493, 0, 3600]]
|
|
120
131
|
* - cpuinfo: [[user, kernel], [0.9, 1.3]]
|
|
121
|
-
*
|
|
122
|
-
* @this {AndroidDriver}
|
|
123
|
-
* @param {string} packageName The name of the package identifier to fetch the data for
|
|
124
|
-
* @param {import('./types').PerformanceDataType} dataType One of supported subsystem to fetch the data for.
|
|
125
|
-
* @returns {Promise<any[][]>}
|
|
126
132
|
*/
|
|
127
|
-
export async function mobileGetPerformanceData(
|
|
133
|
+
export async function mobileGetPerformanceData(
|
|
134
|
+
this: AndroidDriver,
|
|
135
|
+
packageName: string,
|
|
136
|
+
dataType: PerformanceDataType,
|
|
137
|
+
): Promise<any[][]> {
|
|
128
138
|
return await this.getPerformanceData(packageName, dataType);
|
|
129
139
|
}
|
|
130
140
|
|
|
@@ -136,7 +146,10 @@ export async function mobileGetPerformanceData(packageName, dataType) {
|
|
|
136
146
|
* except 'TOTAL', which skips the second type name
|
|
137
147
|
* !!! valDict gets mutated
|
|
138
148
|
*/
|
|
139
|
-
function parseMeminfoForApi19To29(
|
|
149
|
+
function parseMeminfoForApi19To29(
|
|
150
|
+
entries: string[],
|
|
151
|
+
valDict: Record<string, string | number>,
|
|
152
|
+
): void {
|
|
140
153
|
const [type, subType] = entries;
|
|
141
154
|
if (type === MEMINFO_TITLES.NATIVE && subType === MEMINFO_TITLES.HEAP) {
|
|
142
155
|
[
|
|
@@ -166,7 +179,10 @@ function parseMeminfoForApi19To29(entries, valDict) {
|
|
|
166
179
|
* ['<System Type>', '<Memory Type>', <pss total>, <private dirty>, <private clean>, <swapPss dirty>, <rss total>, <heap size>, <heap alloc>, <heap free>]
|
|
167
180
|
* !!! valDict gets mutated
|
|
168
181
|
*/
|
|
169
|
-
function parseMeminfoForApiAbove29(
|
|
182
|
+
function parseMeminfoForApiAbove29(
|
|
183
|
+
entries: string[],
|
|
184
|
+
valDict: Record<string, string | number>,
|
|
185
|
+
): void {
|
|
170
186
|
const [type, subType] = entries;
|
|
171
187
|
if (type === MEMINFO_TITLES.NATIVE && subType === MEMINFO_TITLES.HEAP) {
|
|
172
188
|
[
|
|
@@ -193,13 +209,28 @@ function parseMeminfoForApiAbove29(entries, valDict) {
|
|
|
193
209
|
}
|
|
194
210
|
|
|
195
211
|
/**
|
|
212
|
+
* Retrieves memory information for the specified application package.
|
|
213
|
+
*
|
|
214
|
+
* The data is parsed from the output of `dumpsys meminfo` command.
|
|
215
|
+
* The output format varies depending on the Android API level:
|
|
216
|
+
* - API 18-29: Contains PSS, private dirty, and heap information
|
|
217
|
+
* - API 30+: Additionally includes RSS information
|
|
196
218
|
*
|
|
197
|
-
* @
|
|
198
|
-
* @param
|
|
199
|
-
* @
|
|
219
|
+
* @param packageName The package name of the application to get memory information for.
|
|
220
|
+
* @param retries The number of retry attempts if data retrieval fails.
|
|
221
|
+
* @returns A two-dimensional array where the first row contains memory metric names
|
|
222
|
+
* (totalPrivateDirty, nativePrivateDirty, dalvikPrivateDirty, eglPrivateDirty,
|
|
223
|
+
* glPrivateDirty, totalPss, nativePss, dalvikPss, eglPss, glPss,
|
|
224
|
+
* nativeHeapAllocatedSize, nativeHeapSize, nativeRss, dalvikRss, totalRss)
|
|
225
|
+
* and the second row contains the corresponding values.
|
|
226
|
+
* @throws {Error} If memory data cannot be retrieved or parsed.
|
|
200
227
|
*/
|
|
201
|
-
export async function getMemoryInfo(
|
|
202
|
-
|
|
228
|
+
export async function getMemoryInfo(
|
|
229
|
+
this: AndroidDriver,
|
|
230
|
+
packageName: string,
|
|
231
|
+
retries: number = 2,
|
|
232
|
+
): Promise<any[][]> {
|
|
233
|
+
return (await retryInterval(retries, RETRY_PAUSE_MS, async () => {
|
|
203
234
|
const cmd = [
|
|
204
235
|
'dumpsys',
|
|
205
236
|
'meminfo',
|
|
@@ -214,7 +245,7 @@ export async function getMemoryInfo(packageName, retries = 2) {
|
|
|
214
245
|
if (!data) {
|
|
215
246
|
throw new Error('No data from dumpsys');
|
|
216
247
|
}
|
|
217
|
-
const valDict = {totalPrivateDirty: ''};
|
|
248
|
+
const valDict: Record<string, string | number> = {totalPrivateDirty: ''};
|
|
218
249
|
const apiLevel = await this.adb.getApiLevel();
|
|
219
250
|
for (const line of data.split('\n')) {
|
|
220
251
|
const entries = line.trim().split(/\s+/).filter(Boolean);
|
|
@@ -231,19 +262,40 @@ export async function getMemoryInfo(packageName, retries = 2) {
|
|
|
231
262
|
}
|
|
232
263
|
|
|
233
264
|
throw new Error(`Unable to parse memory data: '${data}'`);
|
|
234
|
-
});
|
|
265
|
+
})) as any[][];
|
|
235
266
|
}
|
|
236
267
|
|
|
237
268
|
/**
|
|
238
|
-
*
|
|
239
|
-
*
|
|
269
|
+
* Retrieves network traffic statistics from the device.
|
|
270
|
+
*
|
|
271
|
+
* The data is parsed from the output of `dumpsys netstats` command.
|
|
272
|
+
* The output format differs between emulators and real devices:
|
|
273
|
+
* - Emulators: Uses full key names (bucketStart, activeTime, rxBytes, etc.)
|
|
274
|
+
* - Real devices (Android 7.1+): Uses abbreviated keys (st, rb, rp, tb, tp, op)
|
|
275
|
+
*
|
|
276
|
+
* @param retries The number of retry attempts if data retrieval fails.
|
|
277
|
+
* @returns A two-dimensional array where the first row contains network metric names
|
|
278
|
+
* (bucketStart/st, activeTime, rxBytes/rb, rxPackets/rp, txBytes/tb, txPackets/tp,
|
|
279
|
+
* operations/op, bucketDuration) and subsequent rows contain the sampled data
|
|
280
|
+
* for each time bucket.
|
|
281
|
+
* @throws {Error} If network traffic data cannot be retrieved or parsed.
|
|
240
282
|
*/
|
|
241
|
-
export async function getNetworkTrafficInfo(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
283
|
+
export async function getNetworkTrafficInfo(
|
|
284
|
+
this: AndroidDriver,
|
|
285
|
+
retries: number = 2,
|
|
286
|
+
): Promise<any[][]> {
|
|
287
|
+
return (await retryInterval(retries, RETRY_PAUSE_MS, async () => {
|
|
288
|
+
const returnValue: any[][] = [];
|
|
289
|
+
let bucketDuration: string | undefined;
|
|
290
|
+
let bucketStart: string | undefined;
|
|
291
|
+
let activeTime: string | undefined;
|
|
292
|
+
let rxBytes: string | undefined;
|
|
293
|
+
let rxPackets: string | undefined;
|
|
294
|
+
let txBytes: string | undefined;
|
|
295
|
+
let txPackets: string | undefined;
|
|
296
|
+
let operations: string | undefined;
|
|
297
|
+
|
|
298
|
+
const cmd = ['dumpsys', 'netstats'];
|
|
247
299
|
let data = await this.adb.shell(cmd);
|
|
248
300
|
if (!data) throw new Error('No data from dumpsys'); //eslint-disable-line curly
|
|
249
301
|
|
|
@@ -278,12 +330,12 @@ export async function getNetworkTrafficInfo(retries = 2) {
|
|
|
278
330
|
// st=1478095200 rb=10079213 rp=19962 tb=2487705 tp=20015 op=0
|
|
279
331
|
// st=1478098800 rb=4444433 rp=10227 tb=1430356 tp=10493 op=0
|
|
280
332
|
let index = 0;
|
|
281
|
-
|
|
333
|
+
const fromXtstats = data.indexOf('Xt stats:');
|
|
282
334
|
|
|
283
335
|
let start = data.indexOf('Pending bytes:', fromXtstats);
|
|
284
336
|
let delimiter = data.indexOf(':', start + 1);
|
|
285
337
|
let end = data.indexOf('\n', delimiter + 1);
|
|
286
|
-
|
|
338
|
+
const pendingBytes = data.substring(delimiter + 1, end).trim();
|
|
287
339
|
|
|
288
340
|
if (end > delimiter) {
|
|
289
341
|
start = data.indexOf('bucketDuration', end + 1);
|
|
@@ -294,7 +346,7 @@ export async function getNetworkTrafficInfo(retries = 2) {
|
|
|
294
346
|
|
|
295
347
|
if (start >= 0) {
|
|
296
348
|
data = data.substring(end + 1, data.length);
|
|
297
|
-
|
|
349
|
+
const arrayList = data.split('\n');
|
|
298
350
|
|
|
299
351
|
if (arrayList.length > 0) {
|
|
300
352
|
start = -1;
|
|
@@ -304,7 +356,7 @@ export async function getNetworkTrafficInfo(retries = 2) {
|
|
|
304
356
|
|
|
305
357
|
if (start >= 0) {
|
|
306
358
|
index = j;
|
|
307
|
-
returnValue[0] =
|
|
359
|
+
returnValue[0] = [];
|
|
308
360
|
|
|
309
361
|
for (let k = 0; k < NETWORK_KEYS[j].length; ++k) {
|
|
310
362
|
returnValue[0][k] = NETWORK_KEYS[j][k];
|
|
@@ -314,65 +366,65 @@ export async function getNetworkTrafficInfo(retries = 2) {
|
|
|
314
366
|
}
|
|
315
367
|
|
|
316
368
|
let returnIndex = 1;
|
|
317
|
-
for (const
|
|
318
|
-
start =
|
|
369
|
+
for (const dataLine of arrayList) {
|
|
370
|
+
start = dataLine.indexOf(NETWORK_KEYS[index][0]);
|
|
319
371
|
|
|
320
372
|
if (start >= 0) {
|
|
321
|
-
delimiter =
|
|
322
|
-
end =
|
|
323
|
-
bucketStart =
|
|
373
|
+
delimiter = dataLine.indexOf('=', start + 1);
|
|
374
|
+
end = dataLine.indexOf(' ', delimiter + 1);
|
|
375
|
+
bucketStart = dataLine.substring(delimiter + 1, end).trim();
|
|
324
376
|
|
|
325
377
|
if (end > delimiter) {
|
|
326
|
-
start =
|
|
378
|
+
start = dataLine.indexOf(NETWORK_KEYS[index][1], end + 1);
|
|
327
379
|
if (start >= 0) {
|
|
328
|
-
delimiter =
|
|
329
|
-
end =
|
|
330
|
-
activeTime =
|
|
380
|
+
delimiter = dataLine.indexOf('=', start + 1);
|
|
381
|
+
end = dataLine.indexOf(' ', delimiter + 1);
|
|
382
|
+
activeTime = dataLine.substring(delimiter + 1, end).trim();
|
|
331
383
|
}
|
|
332
384
|
}
|
|
333
385
|
|
|
334
386
|
if (end > delimiter) {
|
|
335
|
-
start =
|
|
387
|
+
start = dataLine.indexOf(NETWORK_KEYS[index][2], end + 1);
|
|
336
388
|
if (start >= 0) {
|
|
337
|
-
delimiter =
|
|
338
|
-
end =
|
|
339
|
-
rxBytes =
|
|
389
|
+
delimiter = dataLine.indexOf('=', start + 1);
|
|
390
|
+
end = dataLine.indexOf(' ', delimiter + 1);
|
|
391
|
+
rxBytes = dataLine.substring(delimiter + 1, end).trim();
|
|
340
392
|
}
|
|
341
393
|
}
|
|
342
394
|
|
|
343
395
|
if (end > delimiter) {
|
|
344
|
-
start =
|
|
396
|
+
start = dataLine.indexOf(NETWORK_KEYS[index][3], end + 1);
|
|
345
397
|
if (start >= 0) {
|
|
346
|
-
delimiter =
|
|
347
|
-
end =
|
|
348
|
-
rxPackets =
|
|
398
|
+
delimiter = dataLine.indexOf('=', start + 1);
|
|
399
|
+
end = dataLine.indexOf(' ', delimiter + 1);
|
|
400
|
+
rxPackets = dataLine.substring(delimiter + 1, end).trim();
|
|
349
401
|
}
|
|
350
402
|
}
|
|
351
403
|
|
|
352
404
|
if (end > delimiter) {
|
|
353
|
-
start =
|
|
405
|
+
start = dataLine.indexOf(NETWORK_KEYS[index][4], end + 1);
|
|
354
406
|
if (start >= 0) {
|
|
355
|
-
delimiter =
|
|
356
|
-
end =
|
|
357
|
-
txBytes =
|
|
407
|
+
delimiter = dataLine.indexOf('=', start + 1);
|
|
408
|
+
end = dataLine.indexOf(' ', delimiter + 1);
|
|
409
|
+
txBytes = dataLine.substring(delimiter + 1, end).trim();
|
|
358
410
|
}
|
|
359
411
|
}
|
|
360
412
|
|
|
361
413
|
if (end > delimiter) {
|
|
362
|
-
start =
|
|
414
|
+
start = dataLine.indexOf(NETWORK_KEYS[index][5], end + 1);
|
|
363
415
|
if (start >= 0) {
|
|
364
|
-
delimiter =
|
|
365
|
-
end =
|
|
366
|
-
txPackets =
|
|
416
|
+
delimiter = dataLine.indexOf('=', start + 1);
|
|
417
|
+
end = dataLine.indexOf(' ', delimiter + 1);
|
|
418
|
+
txPackets = dataLine.substring(delimiter + 1, end).trim();
|
|
367
419
|
}
|
|
368
420
|
}
|
|
369
421
|
|
|
370
422
|
if (end > delimiter) {
|
|
371
|
-
start =
|
|
423
|
+
start = dataLine.indexOf(NETWORK_KEYS[index][6], end + 1);
|
|
372
424
|
if (start >= 0) {
|
|
373
|
-
delimiter =
|
|
374
|
-
end =
|
|
375
|
-
operations =
|
|
425
|
+
delimiter = dataLine.indexOf('=', start + 1);
|
|
426
|
+
end = dataLine.length;
|
|
427
|
+
operations = dataLine.substring(delimiter + 1, end).trim();
|
|
376
428
|
}
|
|
377
429
|
}
|
|
378
430
|
returnValue[returnIndex++] = [
|
|
@@ -399,7 +451,7 @@ export async function getNetworkTrafficInfo(retries = 2) {
|
|
|
399
451
|
} else {
|
|
400
452
|
throw new Error(`Unable to parse network traffic data: '${data}'`);
|
|
401
453
|
}
|
|
402
|
-
});
|
|
454
|
+
})) as any[][];
|
|
403
455
|
}
|
|
404
456
|
|
|
405
457
|
/**
|
|
@@ -412,15 +464,18 @@ export async function getNetworkTrafficInfo(retries = 2) {
|
|
|
412
464
|
* from 2023-02-07 12:04:40.556 to 2023-02-07 12:09:40.668. No process information
|
|
413
465
|
* exists in the result if the process was not running during the period.
|
|
414
466
|
*
|
|
415
|
-
* @
|
|
416
|
-
* @param
|
|
417
|
-
* @
|
|
418
|
-
* @returns {Promise<[typeof CPU_KEYS, [user: string, kernel: string]]>} The array of the parsed CPU upsage percentages.
|
|
467
|
+
* @param packageName The package name to get the CPU information.
|
|
468
|
+
* @param retries The number of retry count.
|
|
469
|
+
* @returns The array of the parsed CPU upsage percentages.
|
|
419
470
|
* e.g. ['cpuinfo', ['14.3', '28.2']]
|
|
420
471
|
* '14.3' is usage by the user (%), '28.2' is usage by the kernel (%)
|
|
421
472
|
* @throws {Error} If it failed to parse the result of dumpsys, or no package name exists.
|
|
422
473
|
*/
|
|
423
|
-
export async function getCPUInfo(
|
|
474
|
+
export async function getCPUInfo(
|
|
475
|
+
this: AndroidDriver,
|
|
476
|
+
packageName: string,
|
|
477
|
+
retries: number = 2,
|
|
478
|
+
): Promise<[typeof CPU_KEYS, [user: string, kernel: string]]> {
|
|
424
479
|
// TODO: figure out why this is
|
|
425
480
|
// sometimes, the function of 'adb.shell' fails. when I tested this function on the target of 'Galaxy Note5',
|
|
426
481
|
// adb.shell(dumpsys cpuinfo) returns cpu datas for other application packages, but I can't find the data for packageName.
|
|
@@ -430,12 +485,11 @@ export async function getCPUInfo(packageName, retries = 2) {
|
|
|
430
485
|
// @ts-expect-error retryInterval says it can return `null`, but it doesn't look like it actually can.
|
|
431
486
|
// FIXME: fix this in asyncbox
|
|
432
487
|
return await retryInterval(retries, RETRY_PAUSE_MS, async () => {
|
|
433
|
-
|
|
434
|
-
let output;
|
|
488
|
+
let output: string;
|
|
435
489
|
try {
|
|
436
490
|
output = await this.adb.shell(['dumpsys', 'cpuinfo']);
|
|
437
491
|
} catch (e) {
|
|
438
|
-
const err =
|
|
492
|
+
const err = e as import('teen_process').ExecError;
|
|
439
493
|
if (err.stderr) {
|
|
440
494
|
this.log.info(err.stderr);
|
|
441
495
|
}
|
|
@@ -454,35 +508,40 @@ export async function getCPUInfo(packageName, retries = 2) {
|
|
|
454
508
|
`Unable to parse cpu usage data for '${packageName}'. Check the server log for more details`,
|
|
455
509
|
);
|
|
456
510
|
}
|
|
457
|
-
const user =
|
|
458
|
-
const kernel =
|
|
511
|
+
const user = match[1];
|
|
512
|
+
const kernel = match[2];
|
|
459
513
|
return [CPU_KEYS, [user, kernel]];
|
|
460
514
|
});
|
|
461
515
|
}
|
|
462
516
|
|
|
463
517
|
/**
|
|
464
|
-
*
|
|
465
|
-
*
|
|
518
|
+
* Retrieves battery level information from the device.
|
|
519
|
+
*
|
|
520
|
+
* The data is parsed from the output of `dumpsys battery` command.
|
|
521
|
+
*
|
|
522
|
+
* @param retries The number of retry attempts if data retrieval fails.
|
|
523
|
+
* @returns A two-dimensional array where the first row contains the metric name ['power']
|
|
524
|
+
* and the second row contains the battery level as a string (0-100).
|
|
525
|
+
* @throws {Error} If battery data cannot be retrieved or parsed.
|
|
466
526
|
*/
|
|
467
|
-
export async function getBatteryInfo(
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
527
|
+
export async function getBatteryInfo(
|
|
528
|
+
this: AndroidDriver,
|
|
529
|
+
retries: number = 2,
|
|
530
|
+
): Promise<any[][]> {
|
|
531
|
+
return (await retryInterval(retries, RETRY_PAUSE_MS, async () => {
|
|
532
|
+
const cmd = ['dumpsys', 'battery', '|', 'grep', 'level'];
|
|
533
|
+
const data = await this.adb.shell(cmd);
|
|
471
534
|
if (!data) throw new Error('No data from dumpsys'); //eslint-disable-line curly
|
|
472
535
|
|
|
473
|
-
|
|
536
|
+
const power = parseInt((data.split(':')[1] || '').trim(), 10);
|
|
474
537
|
|
|
475
538
|
if (!Number.isNaN(power)) {
|
|
476
539
|
return [_.clone(BATTERY_KEYS), [power.toString()]];
|
|
477
540
|
} else {
|
|
478
541
|
throw new Error(`Unable to parse battery data: '${data}'`);
|
|
479
542
|
}
|
|
480
|
-
});
|
|
543
|
+
})) as any[][];
|
|
481
544
|
}
|
|
482
545
|
|
|
483
546
|
// #endregion
|
|
484
547
|
|
|
485
|
-
/**
|
|
486
|
-
* @typedef {import('../driver').AndroidDriver} AndroidDriver
|
|
487
|
-
* @typedef {import('appium-adb').ADB} ADB
|
|
488
|
-
*/
|
package/lib/commands/shell.ts
CHANGED
|
@@ -4,6 +4,27 @@ import _ from 'lodash';
|
|
|
4
4
|
import {exec} from 'teen_process';
|
|
5
5
|
import {ADB_SHELL_FEATURE} from '../utils';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Executes a shell command on the device via ADB.
|
|
9
|
+
*
|
|
10
|
+
* This method runs an arbitrary shell command on the Android device and returns
|
|
11
|
+
* the output. The command is executed using `adb shell` with the specified
|
|
12
|
+
* command and arguments.
|
|
13
|
+
*
|
|
14
|
+
* Requirements:
|
|
15
|
+
* - The adb_shell feature must be enabled
|
|
16
|
+
*
|
|
17
|
+
* @param command The shell command to execute (e.g., 'pm', 'dumpsys', 'getprop').
|
|
18
|
+
* @param args Optional array of command arguments.
|
|
19
|
+
* @param timeout The maximum time in milliseconds to wait for command execution.
|
|
20
|
+
* Defaults to 20000ms (20 seconds).
|
|
21
|
+
* @param includeStderr If `true`, returns both stdout and stderr in an object.
|
|
22
|
+
* If `false` or undefined, returns only stdout as a string.
|
|
23
|
+
* @returns If `includeStderr` is `true`, returns `{ stdout: string, stderr: string }`.
|
|
24
|
+
* Otherwise, returns the command output as a string.
|
|
25
|
+
* @throws {errors.InvalidArgumentError} If `command` is not a string.
|
|
26
|
+
* @throws {Error} If the command execution fails or times out.
|
|
27
|
+
*/
|
|
7
28
|
export async function mobileShell<T extends boolean>(
|
|
8
29
|
command: string,
|
|
9
30
|
args: string[] = [],
|