@react-native-harness/platform-android 1.3.0 → 1.4.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/dist/__tests__/adb-wait.test.d.ts +2 -0
- package/dist/__tests__/adb-wait.test.d.ts.map +1 -0
- package/dist/__tests__/adb-wait.test.js +69 -0
- package/dist/__tests__/app-session.test.d.ts +2 -0
- package/dist/__tests__/app-session.test.d.ts.map +1 -0
- package/dist/__tests__/app-session.test.js +57 -0
- package/dist/__tests__/avd-config.test.js +58 -0
- package/dist/__tests__/crash-diagnostics.test.d.ts +2 -0
- package/dist/__tests__/crash-diagnostics.test.d.ts.map +1 -0
- package/dist/__tests__/crash-diagnostics.test.js +119 -0
- package/dist/__tests__/crash-reporter.test.d.ts +2 -0
- package/dist/__tests__/crash-reporter.test.d.ts.map +1 -0
- package/dist/__tests__/crash-reporter.test.js +150 -0
- package/dist/__tests__/emulator-startup.test.js +30 -3
- package/dist/__tests__/instance.test.js +139 -24
- package/dist/adb.d.ts +7 -1
- package/dist/adb.d.ts.map +1 -1
- package/dist/adb.js +72 -23
- package/dist/app-session.d.ts +26 -0
- package/dist/app-session.d.ts.map +1 -0
- package/dist/app-session.js +214 -0
- package/dist/avd-config.d.ts +1 -0
- package/dist/avd-config.d.ts.map +1 -1
- package/dist/avd-config.js +11 -0
- package/dist/crash-diagnostics.d.ts +40 -0
- package/dist/crash-diagnostics.d.ts.map +1 -0
- package/dist/crash-diagnostics.js +256 -0
- package/dist/crash-reporter.d.ts +12 -0
- package/dist/crash-reporter.d.ts.map +1 -0
- package/dist/crash-reporter.js +150 -0
- package/dist/emulator-startup.d.ts +23 -0
- package/dist/emulator-startup.d.ts.map +1 -1
- package/dist/emulator-startup.js +58 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/instance.d.ts +1 -1
- package/dist/instance.d.ts.map +1 -1
- package/dist/instance.js +51 -72
- package/dist/runner.d.ts +2 -2
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/__tests__/adb-wait.test.ts +95 -0
- package/src/__tests__/app-session.test.ts +76 -0
- package/src/__tests__/avd-config.test.ts +70 -0
- package/src/__tests__/crash-diagnostics.test.ts +144 -0
- package/src/__tests__/crash-reporter.test.ts +167 -0
- package/src/__tests__/emulator-startup.test.ts +53 -6
- package/src/__tests__/instance.test.ts +226 -84
- package/src/adb.ts +129 -63
- package/src/app-session.ts +316 -0
- package/src/avd-config.ts +17 -0
- package/src/crash-diagnostics.ts +471 -0
- package/src/crash-reporter.ts +263 -0
- package/src/emulator-startup.ts +74 -0
- package/src/index.ts +1 -0
- package/src/instance.ts +84 -105
- package/src/runner.ts +11 -11
- package/test/setup.ts +1 -0
- package/src/app-monitor.ts +0 -577
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { androidCrashParser } from './crash-parser.js';
|
|
2
|
+
import { collectExitInfoArtifact, waitForDropboxArtifacts, getBestDropboxArtifact, } from './crash-diagnostics.js';
|
|
3
|
+
const CRASH_ARTIFACT_SETTLE_DELAY_MS = 100;
|
|
4
|
+
const CRASH_BLOCK_HEADER = '--------- beginning of crash';
|
|
5
|
+
const CRASH_LOG_WINDOW_MS = 5000;
|
|
6
|
+
const findCrashBlockStart = (lines) => {
|
|
7
|
+
let latestCrashHeaderIndex = -1;
|
|
8
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
9
|
+
if (/FATAL EXCEPTION:|Process:\s+.+,\s+PID:|>>>\s+.+\s+<<</i.test(lines[index])) {
|
|
10
|
+
latestCrashHeaderIndex = index;
|
|
11
|
+
break;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const latestBlockHeaderIndex = lines.lastIndexOf(CRASH_BLOCK_HEADER);
|
|
15
|
+
return latestBlockHeaderIndex >= 0
|
|
16
|
+
? latestBlockHeaderIndex
|
|
17
|
+
: latestCrashHeaderIndex;
|
|
18
|
+
};
|
|
19
|
+
const getCrashBlock = (logs, occurredAt) => {
|
|
20
|
+
const nearbyLogs = logs.filter((log) => Math.abs(log.occurredAt - occurredAt) <= CRASH_LOG_WINDOW_MS);
|
|
21
|
+
const lines = nearbyLogs.length > 0
|
|
22
|
+
? nearbyLogs.map((log) => log.line)
|
|
23
|
+
: logs.map((log) => log.line);
|
|
24
|
+
const blockStart = findCrashBlockStart(lines);
|
|
25
|
+
return blockStart >= 0 ? lines.slice(blockStart) : lines;
|
|
26
|
+
};
|
|
27
|
+
const hasUsefulLogcatBlock = (rawLines) => rawLines.some((line) => /FATAL EXCEPTION:|Process:\s+.+,\s+PID:|>>>\s+.+\s+<<</i.test(line));
|
|
28
|
+
const getLogcatCrashDetails = ({ rawLines, bundleId, pid, }) => ({
|
|
29
|
+
...androidCrashParser.parse({
|
|
30
|
+
contents: rawLines.join('\n'),
|
|
31
|
+
bundleId,
|
|
32
|
+
pid,
|
|
33
|
+
}),
|
|
34
|
+
artifactType: 'logcat',
|
|
35
|
+
rawLines,
|
|
36
|
+
});
|
|
37
|
+
const persistLogcatArtifact = ({ details, crashArtifactWriter, testFilePath, }) => {
|
|
38
|
+
if (!crashArtifactWriter || !details.rawLines?.length) {
|
|
39
|
+
return details;
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
...details,
|
|
43
|
+
artifactPath: crashArtifactWriter.persistArtifact({
|
|
44
|
+
artifactKind: 'logcat',
|
|
45
|
+
testFilePath,
|
|
46
|
+
source: {
|
|
47
|
+
kind: 'text',
|
|
48
|
+
fileName: 'logcat.txt',
|
|
49
|
+
text: `${details.rawLines.join('\n')}\n`,
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
const getDropboxFallbackDetails = (artifact) => ({
|
|
55
|
+
...artifact,
|
|
56
|
+
artifactType: artifact.artifactType,
|
|
57
|
+
artifactPath: artifact.artifactPath,
|
|
58
|
+
});
|
|
59
|
+
const getEnrichmentArtifacts = async ({ bundleId, crashArtifactWriter, getDropboxOutput, getExitInfo, minOccurredAt, occurredAt, pid, testFilePath, }) => {
|
|
60
|
+
const dropboxArtifacts = getDropboxOutput
|
|
61
|
+
? await waitForDropboxArtifacts({
|
|
62
|
+
bundleId,
|
|
63
|
+
crashArtifactWriter,
|
|
64
|
+
getDropboxOutput,
|
|
65
|
+
minOccurredAt,
|
|
66
|
+
occurredAt,
|
|
67
|
+
pid,
|
|
68
|
+
testFilePath,
|
|
69
|
+
})
|
|
70
|
+
: [];
|
|
71
|
+
const enrichmentArtifacts = dropboxArtifacts
|
|
72
|
+
.filter((artifact) => artifact.artifactPath !== undefined)
|
|
73
|
+
.map((artifact) => ({
|
|
74
|
+
artifactType: artifact.artifactType,
|
|
75
|
+
artifactPath: artifact.artifactPath,
|
|
76
|
+
}));
|
|
77
|
+
if (getExitInfo) {
|
|
78
|
+
const exitInfoArtifact = await collectExitInfoArtifact({
|
|
79
|
+
bundleId,
|
|
80
|
+
crashArtifactWriter,
|
|
81
|
+
getExitInfo,
|
|
82
|
+
pid,
|
|
83
|
+
testFilePath,
|
|
84
|
+
});
|
|
85
|
+
if (exitInfoArtifact?.artifactPath.startsWith('/')) {
|
|
86
|
+
enrichmentArtifacts.push({
|
|
87
|
+
artifactType: exitInfoArtifact.artifactType,
|
|
88
|
+
artifactPath: exitInfoArtifact.artifactPath,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { dropboxArtifacts, enrichmentArtifacts };
|
|
93
|
+
};
|
|
94
|
+
export const createAndroidCrashReporter = ({ bundleId, crashArtifactWriter, getLogs, getDropboxOutput, getExitInfo, minOccurredAt, }) => ({
|
|
95
|
+
getCrashDetails: async ({ occurredAt, pid, testFilePath, }) => {
|
|
96
|
+
await new Promise((resolve) => setTimeout(resolve, CRASH_ARTIFACT_SETTLE_DELAY_MS));
|
|
97
|
+
const rawLines = getCrashBlock(getLogs(), occurredAt);
|
|
98
|
+
const logcatDetails = rawLines.length > 0
|
|
99
|
+
? getLogcatCrashDetails({ rawLines, bundleId, pid })
|
|
100
|
+
: null;
|
|
101
|
+
let enrichmentArtifacts = [];
|
|
102
|
+
let dropboxArtifacts = [];
|
|
103
|
+
if (getDropboxOutput || getExitInfo) {
|
|
104
|
+
({ dropboxArtifacts, enrichmentArtifacts } =
|
|
105
|
+
await getEnrichmentArtifacts({
|
|
106
|
+
bundleId,
|
|
107
|
+
crashArtifactWriter,
|
|
108
|
+
getDropboxOutput,
|
|
109
|
+
getExitInfo,
|
|
110
|
+
minOccurredAt,
|
|
111
|
+
occurredAt,
|
|
112
|
+
pid,
|
|
113
|
+
testFilePath,
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
if (logcatDetails && hasUsefulLogcatBlock(rawLines)) {
|
|
117
|
+
return {
|
|
118
|
+
...persistLogcatArtifact({
|
|
119
|
+
details: logcatDetails,
|
|
120
|
+
crashArtifactWriter,
|
|
121
|
+
testFilePath,
|
|
122
|
+
}),
|
|
123
|
+
enrichmentArtifacts: enrichmentArtifacts.length > 0 ? enrichmentArtifacts : undefined,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const dropboxFallback = getBestDropboxArtifact(dropboxArtifacts);
|
|
127
|
+
if (dropboxFallback) {
|
|
128
|
+
const primary = getDropboxFallbackDetails(dropboxFallback);
|
|
129
|
+
return {
|
|
130
|
+
...primary,
|
|
131
|
+
enrichmentArtifacts: enrichmentArtifacts.filter((artifact) => artifact.artifactPath !== primary.artifactPath),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
if (logcatDetails) {
|
|
135
|
+
return {
|
|
136
|
+
...persistLogcatArtifact({
|
|
137
|
+
details: logcatDetails,
|
|
138
|
+
crashArtifactWriter,
|
|
139
|
+
testFilePath,
|
|
140
|
+
}),
|
|
141
|
+
enrichmentArtifacts: enrichmentArtifacts.length > 0 ? enrichmentArtifacts : undefined,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return enrichmentArtifacts.length > 0
|
|
145
|
+
? {
|
|
146
|
+
enrichmentArtifacts,
|
|
147
|
+
}
|
|
148
|
+
: null;
|
|
149
|
+
},
|
|
150
|
+
});
|
|
@@ -1,3 +1,26 @@
|
|
|
1
1
|
export type EmulatorBootMode = 'default-boot' | 'clean-snapshot-generation' | 'snapshot-reuse';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the vCPU count baked into an AVD for this runner.
|
|
4
|
+
*
|
|
5
|
+
* AVD snapshots require an identical hardware configuration to load, so all
|
|
6
|
+
* AVD creation, compatibility, and cache-key callers must use this value on
|
|
7
|
+
* the same host.
|
|
8
|
+
*/
|
|
9
|
+
export declare const getEmulatorCpuCores: () => number;
|
|
2
10
|
export declare const getEmulatorStartupArgs: (name: string, mode: EmulatorBootMode) => string[];
|
|
11
|
+
/**
|
|
12
|
+
* Parses the output of `emulator -accel-check` to determine whether
|
|
13
|
+
* hardware acceleration (KVM on Linux, HVF on macOS) is usable. The
|
|
14
|
+
* emulator prints a message containing "is installed and usable" when
|
|
15
|
+
* acceleration is available.
|
|
16
|
+
*/
|
|
17
|
+
export declare const isAccelerationUsable: (accelCheckOutput: string) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Runs `emulator -accel-check` and logs a non-fatal warning when hardware
|
|
20
|
+
* acceleration (KVM/HVF) appears unavailable, in which case the emulator
|
|
21
|
+
* falls back to very slow software emulation. This check must never fail or
|
|
22
|
+
* block emulator startup - any error running it is swallowed and only
|
|
23
|
+
* debug-logged.
|
|
24
|
+
*/
|
|
25
|
+
export declare const warnIfEmulatorAccelerationUnavailable: () => Promise<void>;
|
|
3
26
|
//# sourceMappingURL=emulator-startup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emulator-startup.d.ts","sourceRoot":"","sources":["../src/emulator-startup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"emulator-startup.d.ts","sourceRoot":"","sources":["../src/emulator-startup.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,gBAAgB,GACxB,cAAc,GACd,2BAA2B,GAC3B,gBAAgB,CAAC;AAErB;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,QAAO,MAEtC,CAAC;AAWF,eAAO,MAAM,sBAAsB,GACjC,MAAM,MAAM,EACZ,MAAM,gBAAgB,KACrB,MAAM,EASR,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,kBAAkB,MAAM,KAAG,OAE/D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qCAAqC,QACtC,OAAO,CAAC,IAAI,CA+BrB,CAAC"}
|
package/dist/emulator-startup.js
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
|
+
import { getDeviceCoreBudget, logger, spawn, SubprocessError, } from '@react-native-harness/tools';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import { getEmulatorBinaryPath } from './environment.js';
|
|
4
|
+
const emulatorStartupLogger = logger.child('android-emulator-startup');
|
|
5
|
+
/**
|
|
6
|
+
* Returns the vCPU count baked into an AVD for this runner.
|
|
7
|
+
*
|
|
8
|
+
* AVD snapshots require an identical hardware configuration to load, so all
|
|
9
|
+
* AVD creation, compatibility, and cache-key callers must use this value on
|
|
10
|
+
* the same host.
|
|
11
|
+
*/
|
|
12
|
+
export const getEmulatorCpuCores = () => {
|
|
13
|
+
return getDeviceCoreBudget(os.availableParallelism());
|
|
14
|
+
};
|
|
1
15
|
const COMMON_EMULATOR_ARGS = [
|
|
2
16
|
'-no-window',
|
|
3
17
|
'-gpu',
|
|
4
18
|
'swiftshader_indirect',
|
|
5
19
|
'-noaudio',
|
|
6
20
|
'-no-boot-anim',
|
|
21
|
+
'-no-metrics',
|
|
7
22
|
];
|
|
8
23
|
export const getEmulatorStartupArgs = (name, mode) => {
|
|
9
24
|
const modeArgs = mode === 'clean-snapshot-generation'
|
|
@@ -13,3 +28,46 @@ export const getEmulatorStartupArgs = (name, mode) => {
|
|
|
13
28
|
: ['-no-snapshot-load', '-no-snapshot-save'];
|
|
14
29
|
return [`@${name}`, ...modeArgs, ...COMMON_EMULATOR_ARGS];
|
|
15
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Parses the output of `emulator -accel-check` to determine whether
|
|
33
|
+
* hardware acceleration (KVM on Linux, HVF on macOS) is usable. The
|
|
34
|
+
* emulator prints a message containing "is installed and usable" when
|
|
35
|
+
* acceleration is available.
|
|
36
|
+
*/
|
|
37
|
+
export const isAccelerationUsable = (accelCheckOutput) => {
|
|
38
|
+
return accelCheckOutput.includes('is installed and usable');
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Runs `emulator -accel-check` and logs a non-fatal warning when hardware
|
|
42
|
+
* acceleration (KVM/HVF) appears unavailable, in which case the emulator
|
|
43
|
+
* falls back to very slow software emulation. This check must never fail or
|
|
44
|
+
* block emulator startup - any error running it is swallowed and only
|
|
45
|
+
* debug-logged.
|
|
46
|
+
*/
|
|
47
|
+
export const warnIfEmulatorAccelerationUnavailable = async () => {
|
|
48
|
+
let combinedOutput;
|
|
49
|
+
try {
|
|
50
|
+
const emulatorBinaryPath = getEmulatorBinaryPath();
|
|
51
|
+
const { stdout, stderr } = await spawn(emulatorBinaryPath, [
|
|
52
|
+
'-accel-check',
|
|
53
|
+
]);
|
|
54
|
+
combinedOutput = `${stdout}\n${stderr}`;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error instanceof SubprocessError) {
|
|
58
|
+
// The check itself ran but exited non-zero - this is how
|
|
59
|
+
// `-accel-check` reports that acceleration is unavailable, so treat
|
|
60
|
+
// its output as a normal (non-fatal) result rather than swallowing it.
|
|
61
|
+
combinedOutput = `${error.stdout}\n${error.stderr}`;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Failed to even run the check (e.g. binary missing). This must never
|
|
65
|
+
// fail or block emulator startup.
|
|
66
|
+
emulatorStartupLogger.debug('Failed to run "emulator -accel-check": %o', error);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (!isAccelerationUsable(combinedOutput)) {
|
|
71
|
+
logger.warn('Hardware acceleration (KVM/HVF) appears unavailable for the Android emulator. It will fall back to very slow software emulation.');
|
|
72
|
+
}
|
|
73
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { androidEmulator, physicalAndroidDevice, androidPlatform, } from './fact
|
|
|
2
2
|
export type { AndroidPlatformConfig } from './config.js';
|
|
3
3
|
export { getNormalizedAvdCacheConfig, resolveAvdCachingEnabled, } from './avd-config.js';
|
|
4
4
|
export { getHostAndroidSystemImageArch } from './environment.js';
|
|
5
|
+
export { getEmulatorCpuCores } from './emulator-startup.js';
|
|
5
6
|
export { HarnessAppPathError, HarnessEmulatorConfigError } from './errors.js';
|
|
6
7
|
export { getRunTargets } from './targets.js';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { androidEmulator, physicalAndroidDevice, androidPlatform, } from './factory.js';
|
|
2
2
|
export { getNormalizedAvdCacheConfig, resolveAvdCachingEnabled, } from './avd-config.js';
|
|
3
3
|
export { getHostAndroidSystemImageArch } from './environment.js';
|
|
4
|
+
export { getEmulatorCpuCores } from './emulator-startup.js';
|
|
4
5
|
export { HarnessAppPathError, HarnessEmulatorConfigError } from './errors.js';
|
|
5
6
|
export { getRunTargets } from './targets.js';
|
package/dist/instance.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ import { type HarnessPlatformInitOptions, HarnessPlatformRunner } from '@react-n
|
|
|
2
2
|
import type { Config as HarnessConfig } from '@react-native-harness/config';
|
|
3
3
|
import { AndroidPlatformConfig } from './config.js';
|
|
4
4
|
export declare const getAndroidEmulatorPlatformInstance: (config: AndroidPlatformConfig, harnessConfig: HarnessConfig, init: HarnessPlatformInitOptions) => Promise<HarnessPlatformRunner>;
|
|
5
|
-
export declare const getAndroidPhysicalDevicePlatformInstance: (config: AndroidPlatformConfig, harnessConfig: HarnessConfig) => Promise<HarnessPlatformRunner>;
|
|
5
|
+
export declare const getAndroidPhysicalDevicePlatformInstance: (config: AndroidPlatformConfig, harnessConfig: HarnessConfig, init?: HarnessPlatformInitOptions) => Promise<HarnessPlatformRunner>;
|
|
6
6
|
//# sourceMappingURL=instance.d.ts.map
|
package/dist/instance.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../src/instance.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../src/instance.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAC/B,qBAAqB,EACtB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE5E,OAAO,EACL,qBAAqB,EAGtB,MAAM,aAAa,CAAC;AAyKrB,eAAO,MAAM,kCAAkC,GAC7C,QAAQ,qBAAqB,EAC7B,eAAe,aAAa,EAC5B,MAAM,0BAA0B,KAC/B,OAAO,CAAC,qBAAqB,CAoI/B,CAAC;AAEF,eAAO,MAAM,wCAAwC,GACnD,QAAQ,qBAAqB,EAC7B,eAAe,aAAa,EAC5B,OAAO,0BAA0B,KAChC,OAAO,CAAC,qBAAqB,CA+D/B,CAAC"}
|
package/dist/instance.js
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
import { AppNotInstalledError, DeviceNotFoundError, } from '@react-native-harness/platforms';
|
|
2
|
-
import { logger } from '@react-native-harness/tools';
|
|
2
|
+
import { instrumented, logger, noopDiagnostics } from '@react-native-harness/tools';
|
|
3
3
|
import { assertAndroidDeviceEmulator, assertAndroidDevicePhysical, } from './config.js';
|
|
4
4
|
import { isAvdCompatible, readAvdConfig, resolveAvdCachingEnabled, } from './avd-config.js';
|
|
5
5
|
import { getAdbId } from './adb-id.js';
|
|
6
|
-
import * as
|
|
6
|
+
import * as adbModule from './adb.js';
|
|
7
7
|
import { applyHarnessDebugHttpHost, clearHarnessDebugHttpHost, } from './shared-prefs.js';
|
|
8
8
|
import { getDeviceName } from './utils.js';
|
|
9
|
-
import { createAndroidAppMonitor } from './app-monitor.js';
|
|
10
9
|
import { HarnessAppPathError, HarnessEmulatorConfigError } from './errors.js';
|
|
11
10
|
import { ensureAndroidEmulatorAvailable, ensureAndroidEmulatorEnvironment, getHostAndroidSystemImageArch, } from './environment.js';
|
|
11
|
+
import { warnIfEmulatorAccelerationUnavailable } from './emulator-startup.js';
|
|
12
12
|
import { isInteractive } from '@react-native-harness/tools';
|
|
13
13
|
import fs from 'node:fs';
|
|
14
|
+
import { createAndroidAppSession } from './app-session.js';
|
|
14
15
|
const androidInstanceLogger = logger.child('android-instance');
|
|
15
|
-
const createNoopAppMonitor = () => ({
|
|
16
|
-
start: async () => undefined,
|
|
17
|
-
stop: async () => undefined,
|
|
18
|
-
dispose: async () => undefined,
|
|
19
|
-
addListener: () => undefined,
|
|
20
|
-
removeListener: () => undefined,
|
|
21
|
-
});
|
|
22
16
|
const getHarnessAppPath = () => {
|
|
23
17
|
const appPath = process.env.HARNESS_APP_PATH;
|
|
24
18
|
if (!appPath) {
|
|
@@ -42,23 +36,24 @@ const getOptionalHarnessAppPath = () => {
|
|
|
42
36
|
const configureAndroidRuntime = async (adbId, config, harnessConfig) => {
|
|
43
37
|
const metroPort = harnessConfig.metroPort;
|
|
44
38
|
await Promise.all([
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
adbModule.reversePort(adbId, metroPort),
|
|
40
|
+
adbModule.reversePort(adbId, 8080),
|
|
41
|
+
adbModule.setHideErrorDialogs(adbId, true),
|
|
48
42
|
applyHarnessDebugHttpHost(adbId, config.bundleId, `localhost:${metroPort}`),
|
|
49
43
|
]);
|
|
50
|
-
return
|
|
44
|
+
return adbModule.getAppUid(adbId, config.bundleId);
|
|
51
45
|
};
|
|
52
46
|
const startAndWaitForBoot = async ({ emulatorName, signal, mode, }) => {
|
|
53
47
|
await ensureAndroidEmulatorAvailable();
|
|
54
|
-
await
|
|
55
|
-
|
|
48
|
+
await warnIfEmulatorAccelerationUnavailable();
|
|
49
|
+
await adbModule.startEmulator(emulatorName, mode);
|
|
50
|
+
return adbModule.waitForBoot(emulatorName, signal);
|
|
56
51
|
};
|
|
57
52
|
const recreateAvd = async ({ emulatorConfig, }) => {
|
|
58
53
|
if (!emulatorConfig.avd) {
|
|
59
54
|
throw new HarnessEmulatorConfigError(emulatorConfig.name);
|
|
60
55
|
}
|
|
61
|
-
await
|
|
56
|
+
await adbModule.createAvd({
|
|
62
57
|
name: emulatorConfig.name,
|
|
63
58
|
apiLevel: emulatorConfig.avd.apiLevel,
|
|
64
59
|
profile: emulatorConfig.avd.profile,
|
|
@@ -69,7 +64,7 @@ const recreateAvd = async ({ emulatorConfig, }) => {
|
|
|
69
64
|
const prepareCachedAvd = async ({ emulatorConfig, signal, }) => {
|
|
70
65
|
const emulatorName = emulatorConfig.name;
|
|
71
66
|
const hostArch = getHostAndroidSystemImageArch();
|
|
72
|
-
const hasExistingAvd = await
|
|
67
|
+
const hasExistingAvd = await adbModule.hasAvd(emulatorName);
|
|
73
68
|
const avdConfig = hasExistingAvd ? await readAvdConfig(emulatorName) : null;
|
|
74
69
|
const compatibility = avdConfig == null
|
|
75
70
|
? { compatible: false, reason: 'Missing AVD config.ini.' }
|
|
@@ -84,7 +79,7 @@ const prepareCachedAvd = async ({ emulatorConfig, signal, }) => {
|
|
|
84
79
|
: 'Creating Android emulator %s...', emulatorName);
|
|
85
80
|
if (hasExistingAvd && !compatibility.compatible) {
|
|
86
81
|
androidInstanceLogger.debug('Android AVD %s is not reusable: %s', emulatorName, compatibility.reason);
|
|
87
|
-
await
|
|
82
|
+
await adbModule.deleteAvd(emulatorName);
|
|
88
83
|
}
|
|
89
84
|
await recreateAvd({ emulatorConfig });
|
|
90
85
|
const generationAdbId = await startAndWaitForBoot({
|
|
@@ -93,8 +88,8 @@ const prepareCachedAvd = async ({ emulatorConfig, signal, }) => {
|
|
|
93
88
|
mode: 'clean-snapshot-generation',
|
|
94
89
|
});
|
|
95
90
|
logger.info('Saving Android emulator snapshot for %s...', emulatorName);
|
|
96
|
-
await
|
|
97
|
-
await
|
|
91
|
+
await adbModule.stopEmulator(generationAdbId);
|
|
92
|
+
await adbModule.waitForEmulatorDisconnect(generationAdbId, signal);
|
|
98
93
|
}
|
|
99
94
|
else {
|
|
100
95
|
logger.info('Using cached Android emulator %s...', emulatorName);
|
|
@@ -107,7 +102,7 @@ const prepareCachedAvd = async ({ emulatorConfig, signal, }) => {
|
|
|
107
102
|
};
|
|
108
103
|
export const getAndroidEmulatorPlatformInstance = async (config, harnessConfig, init) => {
|
|
109
104
|
assertAndroidDeviceEmulator(config.device);
|
|
110
|
-
const
|
|
105
|
+
const adb = instrumented(adbModule, 'platform.android.adb', init.diagnostics ?? noopDiagnostics);
|
|
111
106
|
const permissionsEnabled = harnessConfig.permissions ?? false;
|
|
112
107
|
const emulatorConfig = config.device;
|
|
113
108
|
const emulatorName = emulatorConfig.name;
|
|
@@ -166,17 +161,23 @@ export const getAndroidEmulatorPlatformInstance = async (config, harnessConfig,
|
|
|
166
161
|
await adb.grantPermissions(adbId, config.bundleId);
|
|
167
162
|
}
|
|
168
163
|
return {
|
|
169
|
-
|
|
170
|
-
await adb.startApp(adbId, config.bundleId, config.activityName, options ??
|
|
171
|
-
config.appLaunchOptions);
|
|
172
|
-
},
|
|
173
|
-
restartApp: async (options) => {
|
|
174
|
-
await adb.stopApp(adbId, config.bundleId);
|
|
175
|
-
await adb.startApp(adbId, config.bundleId, config.activityName, options ??
|
|
176
|
-
config.appLaunchOptions);
|
|
177
|
-
},
|
|
178
|
-
stopApp: async () => {
|
|
164
|
+
createAppSession: async (options) => {
|
|
179
165
|
await adb.stopApp(adbId, config.bundleId);
|
|
166
|
+
const launchOptions = options ??
|
|
167
|
+
config.appLaunchOptions;
|
|
168
|
+
return await createAndroidAppSession({
|
|
169
|
+
appUid,
|
|
170
|
+
bundleId: config.bundleId,
|
|
171
|
+
startApp: () => adb.startApp(adbId, config.bundleId, config.activityName, launchOptions),
|
|
172
|
+
stopApp: () => adb.stopApp(adbId, config.bundleId),
|
|
173
|
+
getAppPid: () => adb.getAppPid(adbId, config.bundleId),
|
|
174
|
+
getLogcatTimestamp: () => adb.getLogcatTimestamp(adbId),
|
|
175
|
+
startLogcat: (args, options) => adb.startLogcat(adbId, args, options),
|
|
176
|
+
getDropboxOutput: () => adb.getDropboxPrint(adbId),
|
|
177
|
+
getExitInfo: () => adb.getActivityExitInfo(adbId, config.bundleId),
|
|
178
|
+
crashArtifactWriter: init.crashArtifactWriter,
|
|
179
|
+
signal: init.signal,
|
|
180
|
+
});
|
|
180
181
|
},
|
|
181
182
|
dispose: async () => {
|
|
182
183
|
await adb.stopApp(adbId, config.bundleId);
|
|
@@ -187,25 +188,11 @@ export const getAndroidEmulatorPlatformInstance = async (config, harnessConfig,
|
|
|
187
188
|
await adb.stopEmulator(adbId);
|
|
188
189
|
}
|
|
189
190
|
},
|
|
190
|
-
isAppRunning: async () => {
|
|
191
|
-
return await adb.isAppRunning(adbId, config.bundleId);
|
|
192
|
-
},
|
|
193
|
-
createAppMonitor: (options) => {
|
|
194
|
-
if (!detectNativeCrashes) {
|
|
195
|
-
return createNoopAppMonitor();
|
|
196
|
-
}
|
|
197
|
-
return createAndroidAppMonitor({
|
|
198
|
-
adbId,
|
|
199
|
-
bundleId: config.bundleId,
|
|
200
|
-
appUid,
|
|
201
|
-
crashArtifactWriter: options?.crashArtifactWriter,
|
|
202
|
-
});
|
|
203
|
-
},
|
|
204
191
|
};
|
|
205
192
|
};
|
|
206
|
-
export const getAndroidPhysicalDevicePlatformInstance = async (config, harnessConfig) => {
|
|
193
|
+
export const getAndroidPhysicalDevicePlatformInstance = async (config, harnessConfig, init) => {
|
|
207
194
|
assertAndroidDevicePhysical(config.device);
|
|
208
|
-
const
|
|
195
|
+
const adb = instrumented(adbModule, 'platform.android.adb', init?.diagnostics ?? noopDiagnostics);
|
|
209
196
|
const permissionsEnabled = harnessConfig.permissions ?? false;
|
|
210
197
|
const adbId = await getAdbId(config.device);
|
|
211
198
|
if (!adbId) {
|
|
@@ -220,36 +207,28 @@ export const getAndroidPhysicalDevicePlatformInstance = async (config, harnessCo
|
|
|
220
207
|
await adb.grantPermissions(adbId, config.bundleId);
|
|
221
208
|
}
|
|
222
209
|
return {
|
|
223
|
-
|
|
224
|
-
await adb.startApp(adbId, config.bundleId, config.activityName, options ??
|
|
225
|
-
config.appLaunchOptions);
|
|
226
|
-
},
|
|
227
|
-
restartApp: async (options) => {
|
|
228
|
-
await adb.stopApp(adbId, config.bundleId);
|
|
229
|
-
await adb.startApp(adbId, config.bundleId, config.activityName, options ??
|
|
230
|
-
config.appLaunchOptions);
|
|
231
|
-
},
|
|
232
|
-
stopApp: async () => {
|
|
210
|
+
createAppSession: async (options) => {
|
|
233
211
|
await adb.stopApp(adbId, config.bundleId);
|
|
212
|
+
const launchOptions = options ??
|
|
213
|
+
config.appLaunchOptions;
|
|
214
|
+
return await createAndroidAppSession({
|
|
215
|
+
appUid,
|
|
216
|
+
bundleId: config.bundleId,
|
|
217
|
+
startApp: () => adb.startApp(adbId, config.bundleId, config.activityName, launchOptions),
|
|
218
|
+
stopApp: () => adb.stopApp(adbId, config.bundleId),
|
|
219
|
+
getAppPid: () => adb.getAppPid(adbId, config.bundleId),
|
|
220
|
+
getLogcatTimestamp: () => adb.getLogcatTimestamp(adbId),
|
|
221
|
+
startLogcat: (args, options) => adb.startLogcat(adbId, args, options),
|
|
222
|
+
getDropboxOutput: () => adb.getDropboxPrint(adbId),
|
|
223
|
+
getExitInfo: () => adb.getActivityExitInfo(adbId, config.bundleId),
|
|
224
|
+
crashArtifactWriter: init?.crashArtifactWriter,
|
|
225
|
+
signal: init?.signal,
|
|
226
|
+
});
|
|
234
227
|
},
|
|
235
228
|
dispose: async () => {
|
|
236
229
|
await adb.stopApp(adbId, config.bundleId);
|
|
237
230
|
await clearHarnessDebugHttpHost(adbId, config.bundleId);
|
|
238
231
|
await adb.setHideErrorDialogs(adbId, false);
|
|
239
232
|
},
|
|
240
|
-
isAppRunning: async () => {
|
|
241
|
-
return await adb.isAppRunning(adbId, config.bundleId);
|
|
242
|
-
},
|
|
243
|
-
createAppMonitor: (options) => {
|
|
244
|
-
if (!detectNativeCrashes) {
|
|
245
|
-
return createNoopAppMonitor();
|
|
246
|
-
}
|
|
247
|
-
return createAndroidAppMonitor({
|
|
248
|
-
adbId,
|
|
249
|
-
bundleId: config.bundleId,
|
|
250
|
-
appUid,
|
|
251
|
-
crashArtifactWriter: options?.crashArtifactWriter,
|
|
252
|
-
});
|
|
253
|
-
},
|
|
254
233
|
};
|
|
255
234
|
};
|
package/dist/runner.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type HarnessPlatformRunnerFactory } from '@react-native-harness/platforms';
|
|
2
2
|
import type { Config as HarnessConfig } from '@react-native-harness/config';
|
|
3
3
|
import { type AndroidPlatformConfig } from './config.js';
|
|
4
|
-
declare const getAndroidRunner:
|
|
4
|
+
declare const getAndroidRunner: HarnessPlatformRunnerFactory<AndroidPlatformConfig, HarnessConfig>;
|
|
5
5
|
export default getAndroidRunner;
|
|
6
6
|
//# sourceMappingURL=runner.d.ts.map
|
package/dist/runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,KAAK,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,aAAa,CAAC;AAUrB,QAAA,MAAM,gBAAgB,EAAE,4BAA4B,CAClD,qBAAqB,EACrB,aAAa,CAqBd,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
package/dist/runner.js
CHANGED
|
@@ -8,6 +8,6 @@ const getAndroidRunner = async (config, harnessConfig, init) => {
|
|
|
8
8
|
if (isAndroidDeviceEmulator(parsedConfig.device)) {
|
|
9
9
|
return getAndroidEmulatorPlatformInstance(parsedConfig, harnessConfig, init);
|
|
10
10
|
}
|
|
11
|
-
return getAndroidPhysicalDevicePlatformInstance(parsedConfig, harnessConfig);
|
|
11
|
+
return getAndroidPhysicalDevicePlatformInstance(parsedConfig, harnessConfig, init);
|
|
12
12
|
};
|
|
13
13
|
export default getAndroidRunner;
|