@react-native-harness/platform-android 1.1.0-rc.4 → 1.2.0-rc.1
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.test.js +170 -6
- package/dist/__tests__/emulator-startup.test.js +1 -0
- package/dist/__tests__/instance.test.js +130 -0
- package/dist/adb-errors.d.ts +16 -0
- package/dist/adb-errors.d.ts.map +1 -0
- package/dist/adb-errors.js +35 -0
- package/dist/adb-id.d.ts.map +1 -1
- package/dist/adb-id.js +3 -0
- package/dist/adb.d.ts +2 -0
- package/dist/adb.d.ts.map +1 -1
- package/dist/adb.js +163 -4
- package/dist/config.d.ts +16 -16
- package/dist/emulator-startup.d.ts.map +1 -1
- package/dist/emulator-startup.js +0 -2
- package/dist/instance.d.ts.map +1 -1
- package/dist/instance.js +25 -2
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/__tests__/adb.test.ts +235 -28
- package/src/__tests__/emulator-startup.test.ts +3 -0
- package/src/__tests__/instance.test.ts +188 -0
- package/src/adb-errors.ts +47 -0
- package/src/adb-id.ts +4 -0
- package/src/adb.ts +232 -10
- package/src/emulator-startup.ts +0 -2
- package/src/instance.ts +30 -2
- package/dist/assertions.d.ts +0 -5
- package/dist/assertions.d.ts.map +0 -1
- package/dist/assertions.js +0 -6
- package/dist/emulator.d.ts +0 -6
- package/dist/emulator.d.ts.map +0 -1
- package/dist/emulator.js +0 -27
- package/dist/reader.d.ts +0 -6
- package/dist/reader.d.ts.map +0 -1
- package/dist/reader.js +0 -57
- package/dist/types.d.ts +0 -381
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -107
package/dist/adb.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { spawn, SubprocessError } from '@react-native-harness/tools';
|
|
1
|
+
import { logger, spawn, SubprocessError } from '@react-native-harness/tools';
|
|
2
2
|
import { spawn as nodeSpawn } from 'node:child_process';
|
|
3
3
|
import { access, rm } from 'node:fs/promises';
|
|
4
|
+
import { getAvdConfigPath, getAvdDirectory, readAvdConfig, } from './avd-config.js';
|
|
4
5
|
import { ensureAndroidEmulatorAvailable, ensureAndroidSdkPackages, getAdbBinaryPath, getAndroidSystemImagePackage, getAvdManagerBinaryPath, getEmulatorBinaryPath, getHostAndroidSystemImageArch, getRequiredAndroidSdkPackages, } from './environment.js';
|
|
5
6
|
import { getEmulatorStartupArgs, } from './emulator-startup.js';
|
|
7
|
+
import { AdbAppNotInstalledError, AdbPermissionGrantError, } from './adb-errors.js';
|
|
6
8
|
const wait = async (ms) => {
|
|
7
9
|
await new Promise((resolve) => {
|
|
8
10
|
setTimeout(resolve, ms);
|
|
@@ -24,9 +26,9 @@ const waitWithSignal = async (ms, signal) => {
|
|
|
24
26
|
}
|
|
25
27
|
await Promise.race([wait(ms), waitForAbort(signal)]);
|
|
26
28
|
};
|
|
27
|
-
const getAvdConfigPath = (name) => `${process.env.ANDROID_AVD_HOME ?? `${process.env.HOME}/.android/avd`}/${name}.avd/config.ini`;
|
|
28
29
|
const EMULATOR_STARTUP_OBSERVATION_TIMEOUT_MS = 5000;
|
|
29
30
|
const EMULATOR_OUTPUT_BUFFER_LIMIT = 16 * 1024;
|
|
31
|
+
const androidAdbLogger = logger.child('android-adb');
|
|
30
32
|
export const emulatorProcess = {
|
|
31
33
|
startDetachedProcess: (file, args) => nodeSpawn(file, args, {
|
|
32
34
|
detached: true,
|
|
@@ -79,6 +81,43 @@ export const getRequiredEmulatorPackages = (apiLevel) => {
|
|
|
79
81
|
export const verifyAndroidEmulatorSdk = async (apiLevel) => {
|
|
80
82
|
await ensureAndroidSdkPackages(getRequiredEmulatorPackages(apiLevel));
|
|
81
83
|
};
|
|
84
|
+
const listAvdProfiles = async () => {
|
|
85
|
+
const { stdout } = await spawn(getAvdManagerBinaryPath(), ['list', 'device']);
|
|
86
|
+
return stdout
|
|
87
|
+
.split('\n')
|
|
88
|
+
.map((line) => line.match(/^id:\s+\d+\s+or\s+"([^"]+)"/i)?.[1]?.trim())
|
|
89
|
+
.filter((profile) => profile != null && profile !== '');
|
|
90
|
+
};
|
|
91
|
+
const ensureAvdProfileAvailable = async (profile) => {
|
|
92
|
+
const availableProfiles = await listAvdProfiles();
|
|
93
|
+
if (availableProfiles.includes(profile)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const availableProfilesList = availableProfiles.length > 0
|
|
97
|
+
? availableProfiles.join(', ')
|
|
98
|
+
: 'None reported by avdmanager.';
|
|
99
|
+
throw new Error(`Android AVD profile "${profile}" is not available on this machine. Available profiles: ${availableProfilesList}`);
|
|
100
|
+
};
|
|
101
|
+
const ensureAvdConfigExists = async (name) => {
|
|
102
|
+
const configPath = getAvdConfigPath(name);
|
|
103
|
+
if ((await readAvdConfig(name)) == null) {
|
|
104
|
+
throw new Error(`Android AVD "${name}" was created, but config.ini was not found at ${configPath}.`);
|
|
105
|
+
}
|
|
106
|
+
return configPath;
|
|
107
|
+
};
|
|
108
|
+
const getAvdIniPath = (name) => {
|
|
109
|
+
const avdHome = process.env.ANDROID_AVD_HOME ?? `${process.env.HOME}/.android/avd`;
|
|
110
|
+
return `${avdHome}/${name}.ini`;
|
|
111
|
+
};
|
|
112
|
+
const ensureAvdIniExists = async ({ name, apiLevel, }) => {
|
|
113
|
+
const iniPath = getAvdIniPath(name);
|
|
114
|
+
const avdDirectory = getAvdDirectory(name);
|
|
115
|
+
await spawn('bash', [
|
|
116
|
+
'-lc',
|
|
117
|
+
`printf '%s\n%s\n%s\n%s\n' 'avd.ini.encoding=UTF-8' 'path=${avdDirectory}' 'path.rel=avd/${name}.avd' 'target=android-${apiLevel}' > "${iniPath}"`,
|
|
118
|
+
]);
|
|
119
|
+
return iniPath;
|
|
120
|
+
};
|
|
82
121
|
export const getStartAppArgs = (bundleId, activityName, options) => {
|
|
83
122
|
const args = [
|
|
84
123
|
'shell',
|
|
@@ -182,6 +221,61 @@ export const getDeviceInfo = async (adbId) => {
|
|
|
182
221
|
const model = await getShellProperty(adbId, 'ro.product.model');
|
|
183
222
|
return { manufacturer, model };
|
|
184
223
|
};
|
|
224
|
+
const getRequestedPermissions = async (adbId, bundleId) => {
|
|
225
|
+
const { stdout } = await spawn(getAdbBinaryPath(), [
|
|
226
|
+
'-s',
|
|
227
|
+
adbId,
|
|
228
|
+
'shell',
|
|
229
|
+
'dumpsys',
|
|
230
|
+
'package',
|
|
231
|
+
bundleId,
|
|
232
|
+
]);
|
|
233
|
+
const requestedPermissions = new Set();
|
|
234
|
+
const lines = stdout.split('\n');
|
|
235
|
+
let inRequestedPermissionsSection = false;
|
|
236
|
+
for (const line of lines) {
|
|
237
|
+
const trimmedLine = line.trim();
|
|
238
|
+
if (trimmedLine === 'requested permissions:') {
|
|
239
|
+
inRequestedPermissionsSection = true;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (!inRequestedPermissionsSection) {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
if (trimmedLine === '') {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (trimmedLine.endsWith(':')) {
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
if (/^[a-zA-Z0-9_.]+$/.test(trimmedLine)) {
|
|
252
|
+
requestedPermissions.add(trimmedLine);
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
return [...requestedPermissions];
|
|
258
|
+
};
|
|
259
|
+
const getDangerousPermissions = async (adbId) => {
|
|
260
|
+
const { stdout } = await spawn(getAdbBinaryPath(), [
|
|
261
|
+
'-s',
|
|
262
|
+
adbId,
|
|
263
|
+
'shell',
|
|
264
|
+
'pm',
|
|
265
|
+
'list',
|
|
266
|
+
'permissions',
|
|
267
|
+
'-g',
|
|
268
|
+
'-d',
|
|
269
|
+
]);
|
|
270
|
+
const dangerousPermissions = new Set();
|
|
271
|
+
for (const match of stdout.matchAll(/permission:([a-zA-Z0-9_.]+)/g)) {
|
|
272
|
+
const permission = match[1]?.trim();
|
|
273
|
+
if (permission) {
|
|
274
|
+
dangerousPermissions.add(permission);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return dangerousPermissions;
|
|
278
|
+
};
|
|
185
279
|
export const isBootCompleted = async (adbId) => {
|
|
186
280
|
try {
|
|
187
281
|
const bootCompleted = await getShellProperty(adbId, 'sys.boot_completed');
|
|
@@ -200,6 +294,9 @@ export const stopEmulator = async (adbId) => {
|
|
|
200
294
|
export const installApp = async (adbId, appPath) => {
|
|
201
295
|
await spawn(getAdbBinaryPath(), ['-s', adbId, 'install', '-r', appPath]);
|
|
202
296
|
};
|
|
297
|
+
export const uninstallApp = async (adbId, bundleId) => {
|
|
298
|
+
await spawn(getAdbBinaryPath(), ['-s', adbId, 'uninstall', bundleId]);
|
|
299
|
+
};
|
|
203
300
|
export const hasAvd = async (name) => {
|
|
204
301
|
const avds = await getAvds();
|
|
205
302
|
return avds.includes(name);
|
|
@@ -207,13 +304,16 @@ export const hasAvd = async (name) => {
|
|
|
207
304
|
export const createAvd = async ({ name, apiLevel, profile, diskSize, heapSize, }) => {
|
|
208
305
|
const systemImagePackage = getAndroidSystemImagePackage(apiLevel, getHostAndroidSystemImageArch());
|
|
209
306
|
await verifyAndroidEmulatorSdk(apiLevel);
|
|
307
|
+
await ensureAvdProfileAvailable(profile);
|
|
210
308
|
await spawn('bash', [
|
|
211
309
|
'-lc',
|
|
212
|
-
`printf 'no\n' | "${getAvdManagerBinaryPath()}" create avd --force --name "${name}" --package "${systemImagePackage}" --device "${profile}"`,
|
|
310
|
+
`printf 'no\n' | "${getAvdManagerBinaryPath()}" create avd --force --name "${name}" --package "${systemImagePackage}" --device "${profile}" -p "${getAvdDirectory(name)}"`,
|
|
213
311
|
]);
|
|
312
|
+
await ensureAvdIniExists({ name, apiLevel });
|
|
313
|
+
const configPath = await ensureAvdConfigExists(name);
|
|
214
314
|
await spawn('bash', [
|
|
215
315
|
'-lc',
|
|
216
|
-
`printf '%s\n%s\n' 'disk.dataPartition.size=${diskSize}' 'vm.heapSize=${heapSize}' >> "${
|
|
316
|
+
`printf '%s\n%s\n' 'disk.dataPartition.size=${diskSize}' 'vm.heapSize=${heapSize}' >> "${configPath}"`,
|
|
217
317
|
]);
|
|
218
318
|
};
|
|
219
319
|
export const deleteAvd = async (name) => {
|
|
@@ -428,3 +528,62 @@ export const getConnectedDevices = async () => {
|
|
|
428
528
|
}
|
|
429
529
|
return devices;
|
|
430
530
|
};
|
|
531
|
+
export const grantPermissions = async (adbId, bundleId) => {
|
|
532
|
+
androidAdbLogger.debug('grantPermissions:start %o', {
|
|
533
|
+
adbId,
|
|
534
|
+
bundleId,
|
|
535
|
+
});
|
|
536
|
+
const isInstalled = await isAppInstalled(adbId, bundleId);
|
|
537
|
+
if (!isInstalled) {
|
|
538
|
+
throw new AdbAppNotInstalledError(bundleId, adbId);
|
|
539
|
+
}
|
|
540
|
+
const [requestedPermissions, dangerousPermissions] = await Promise.all([
|
|
541
|
+
getRequestedPermissions(adbId, bundleId),
|
|
542
|
+
getDangerousPermissions(adbId),
|
|
543
|
+
]);
|
|
544
|
+
const permissions = requestedPermissions.filter((permission) => dangerousPermissions.has(permission));
|
|
545
|
+
androidAdbLogger.debug('grantPermissions:resolved %o', {
|
|
546
|
+
adbId,
|
|
547
|
+
bundleId,
|
|
548
|
+
requestedPermissions,
|
|
549
|
+
permissions,
|
|
550
|
+
});
|
|
551
|
+
if (permissions.length === 0) {
|
|
552
|
+
androidAdbLogger.debug('grantPermissions:skip %o', {
|
|
553
|
+
adbId,
|
|
554
|
+
bundleId,
|
|
555
|
+
});
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
const grantCommands = permissions.map((permission) => [
|
|
559
|
+
'-s',
|
|
560
|
+
adbId,
|
|
561
|
+
'shell',
|
|
562
|
+
'pm',
|
|
563
|
+
'grant',
|
|
564
|
+
bundleId,
|
|
565
|
+
permission,
|
|
566
|
+
]);
|
|
567
|
+
try {
|
|
568
|
+
androidAdbLogger.debug('grantPermissions:commands %o', {
|
|
569
|
+
adbId,
|
|
570
|
+
bundleId,
|
|
571
|
+
grantCommands,
|
|
572
|
+
});
|
|
573
|
+
await Promise.all(grantCommands.map((args) => spawn(getAdbBinaryPath(), args)));
|
|
574
|
+
androidAdbLogger.debug('grantPermissions:success %o', {
|
|
575
|
+
adbId,
|
|
576
|
+
bundleId,
|
|
577
|
+
permissions,
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
catch (error) {
|
|
581
|
+
androidAdbLogger.debug('grantPermissions:error %o', {
|
|
582
|
+
adbId,
|
|
583
|
+
bundleId,
|
|
584
|
+
permissions,
|
|
585
|
+
error,
|
|
586
|
+
});
|
|
587
|
+
throw new AdbPermissionGrantError(bundleId, permissions, adbId);
|
|
588
|
+
}
|
|
589
|
+
};
|
package/dist/config.d.ts
CHANGED
|
@@ -68,8 +68,8 @@ export declare const AndroidEmulatorSchema: z.ZodObject<{
|
|
|
68
68
|
} | undefined;
|
|
69
69
|
}>>;
|
|
70
70
|
}, "strip", z.ZodTypeAny, {
|
|
71
|
-
name: string;
|
|
72
71
|
type: "emulator";
|
|
72
|
+
name: string;
|
|
73
73
|
avd?: {
|
|
74
74
|
apiLevel: number;
|
|
75
75
|
profile: string;
|
|
@@ -80,8 +80,8 @@ export declare const AndroidEmulatorSchema: z.ZodObject<{
|
|
|
80
80
|
} | undefined;
|
|
81
81
|
} | undefined;
|
|
82
82
|
}, {
|
|
83
|
-
name: string;
|
|
84
83
|
type: "emulator";
|
|
84
|
+
name: string;
|
|
85
85
|
avd?: {
|
|
86
86
|
apiLevel: number;
|
|
87
87
|
profile: string;
|
|
@@ -97,13 +97,13 @@ export declare const PhysicalAndroidDeviceSchema: z.ZodObject<{
|
|
|
97
97
|
manufacturer: z.ZodString;
|
|
98
98
|
model: z.ZodString;
|
|
99
99
|
}, "strip", z.ZodTypeAny, {
|
|
100
|
+
type: "physical";
|
|
100
101
|
manufacturer: string;
|
|
101
102
|
model: string;
|
|
102
|
-
type: "physical";
|
|
103
103
|
}, {
|
|
104
|
+
type: "physical";
|
|
104
105
|
manufacturer: string;
|
|
105
106
|
model: string;
|
|
106
|
-
type: "physical";
|
|
107
107
|
}>;
|
|
108
108
|
export declare const AndroidDeviceSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
109
109
|
type: z.ZodLiteral<"emulator">;
|
|
@@ -138,8 +138,8 @@ export declare const AndroidDeviceSchema: z.ZodDiscriminatedUnion<"type", [z.Zod
|
|
|
138
138
|
} | undefined;
|
|
139
139
|
}>>;
|
|
140
140
|
}, "strip", z.ZodTypeAny, {
|
|
141
|
-
name: string;
|
|
142
141
|
type: "emulator";
|
|
142
|
+
name: string;
|
|
143
143
|
avd?: {
|
|
144
144
|
apiLevel: number;
|
|
145
145
|
profile: string;
|
|
@@ -150,8 +150,8 @@ export declare const AndroidDeviceSchema: z.ZodDiscriminatedUnion<"type", [z.Zod
|
|
|
150
150
|
} | undefined;
|
|
151
151
|
} | undefined;
|
|
152
152
|
}, {
|
|
153
|
-
name: string;
|
|
154
153
|
type: "emulator";
|
|
154
|
+
name: string;
|
|
155
155
|
avd?: {
|
|
156
156
|
apiLevel: number;
|
|
157
157
|
profile: string;
|
|
@@ -166,13 +166,13 @@ export declare const AndroidDeviceSchema: z.ZodDiscriminatedUnion<"type", [z.Zod
|
|
|
166
166
|
manufacturer: z.ZodString;
|
|
167
167
|
model: z.ZodString;
|
|
168
168
|
}, "strip", z.ZodTypeAny, {
|
|
169
|
+
type: "physical";
|
|
169
170
|
manufacturer: string;
|
|
170
171
|
model: string;
|
|
171
|
-
type: "physical";
|
|
172
172
|
}, {
|
|
173
|
+
type: "physical";
|
|
173
174
|
manufacturer: string;
|
|
174
175
|
model: string;
|
|
175
|
-
type: "physical";
|
|
176
176
|
}>]>;
|
|
177
177
|
export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
178
178
|
name: z.ZodString;
|
|
@@ -209,8 +209,8 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
209
209
|
} | undefined;
|
|
210
210
|
}>>;
|
|
211
211
|
}, "strip", z.ZodTypeAny, {
|
|
212
|
-
name: string;
|
|
213
212
|
type: "emulator";
|
|
213
|
+
name: string;
|
|
214
214
|
avd?: {
|
|
215
215
|
apiLevel: number;
|
|
216
216
|
profile: string;
|
|
@@ -221,8 +221,8 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
221
221
|
} | undefined;
|
|
222
222
|
} | undefined;
|
|
223
223
|
}, {
|
|
224
|
-
name: string;
|
|
225
224
|
type: "emulator";
|
|
225
|
+
name: string;
|
|
226
226
|
avd?: {
|
|
227
227
|
apiLevel: number;
|
|
228
228
|
profile: string;
|
|
@@ -237,13 +237,13 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
237
237
|
manufacturer: z.ZodString;
|
|
238
238
|
model: z.ZodString;
|
|
239
239
|
}, "strip", z.ZodTypeAny, {
|
|
240
|
+
type: "physical";
|
|
240
241
|
manufacturer: string;
|
|
241
242
|
model: string;
|
|
242
|
-
type: "physical";
|
|
243
243
|
}, {
|
|
244
|
+
type: "physical";
|
|
244
245
|
manufacturer: string;
|
|
245
246
|
model: string;
|
|
246
|
-
type: "physical";
|
|
247
247
|
}>]>;
|
|
248
248
|
bundleId: z.ZodString;
|
|
249
249
|
activityName: z.ZodDefault<z.ZodString>;
|
|
@@ -257,8 +257,8 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
257
257
|
}, "strip", z.ZodTypeAny, {
|
|
258
258
|
name: string;
|
|
259
259
|
device: {
|
|
260
|
-
name: string;
|
|
261
260
|
type: "emulator";
|
|
261
|
+
name: string;
|
|
262
262
|
avd?: {
|
|
263
263
|
apiLevel: number;
|
|
264
264
|
profile: string;
|
|
@@ -269,9 +269,9 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
269
269
|
} | undefined;
|
|
270
270
|
} | undefined;
|
|
271
271
|
} | {
|
|
272
|
+
type: "physical";
|
|
272
273
|
manufacturer: string;
|
|
273
274
|
model: string;
|
|
274
|
-
type: "physical";
|
|
275
275
|
};
|
|
276
276
|
bundleId: string;
|
|
277
277
|
activityName: string;
|
|
@@ -281,8 +281,8 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
281
281
|
}, {
|
|
282
282
|
name: string;
|
|
283
283
|
device: {
|
|
284
|
-
name: string;
|
|
285
284
|
type: "emulator";
|
|
285
|
+
name: string;
|
|
286
286
|
avd?: {
|
|
287
287
|
apiLevel: number;
|
|
288
288
|
profile: string;
|
|
@@ -293,9 +293,9 @@ export declare const AndroidPlatformConfigSchema: z.ZodObject<{
|
|
|
293
293
|
} | undefined;
|
|
294
294
|
} | undefined;
|
|
295
295
|
} | {
|
|
296
|
+
type: "physical";
|
|
296
297
|
manufacturer: string;
|
|
297
298
|
model: string;
|
|
298
|
-
type: "physical";
|
|
299
299
|
};
|
|
300
300
|
bundleId: string;
|
|
301
301
|
activityName?: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emulator-startup.d.ts","sourceRoot":"","sources":["../src/emulator-startup.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GACxB,cAAc,GACd,2BAA2B,GAC3B,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"emulator-startup.d.ts","sourceRoot":"","sources":["../src/emulator-startup.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GACxB,cAAc,GACd,2BAA2B,GAC3B,gBAAgB,CAAC;AAUrB,eAAO,MAAM,sBAAsB,GACjC,MAAM,MAAM,EACZ,MAAM,gBAAgB,KACrB,MAAM,EASR,CAAC"}
|
package/dist/emulator-startup.js
CHANGED
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,EAIL,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;
|
|
1
|
+
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../src/instance.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,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;AAgLrB,eAAO,MAAM,kCAAkC,GAC7C,QAAQ,qBAAqB,EAC7B,eAAe,aAAa,EAC5B,MAAM,0BAA0B,KAC/B,OAAO,CAAC,qBAAqB,CA2I/B,CAAC;AAEF,eAAO,MAAM,wCAAwC,GACnD,QAAQ,qBAAqB,EAC7B,eAAe,aAAa,KAC3B,OAAO,CAAC,qBAAqB,CAsE/B,CAAC"}
|
package/dist/instance.js
CHANGED
|
@@ -29,6 +29,16 @@ const getHarnessAppPath = () => {
|
|
|
29
29
|
}
|
|
30
30
|
return appPath;
|
|
31
31
|
};
|
|
32
|
+
const getOptionalHarnessAppPath = () => {
|
|
33
|
+
const appPath = process.env.HARNESS_APP_PATH;
|
|
34
|
+
if (!appPath) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
if (!fs.existsSync(appPath)) {
|
|
38
|
+
throw new HarnessAppPathError('invalid', appPath);
|
|
39
|
+
}
|
|
40
|
+
return appPath;
|
|
41
|
+
};
|
|
32
42
|
const configureAndroidRuntime = async (adbId, config, harnessConfig) => {
|
|
33
43
|
const metroPort = harnessConfig.metroPort;
|
|
34
44
|
await Promise.all([
|
|
@@ -98,6 +108,7 @@ const prepareCachedAvd = async ({ emulatorConfig, signal, }) => {
|
|
|
98
108
|
export const getAndroidEmulatorPlatformInstance = async (config, harnessConfig, init) => {
|
|
99
109
|
assertAndroidDeviceEmulator(config.device);
|
|
100
110
|
const detectNativeCrashes = harnessConfig.detectNativeCrashes ?? true;
|
|
111
|
+
const permissionsEnabled = harnessConfig.permissions ?? false;
|
|
101
112
|
const emulatorConfig = config.device;
|
|
102
113
|
const emulatorName = emulatorConfig.name;
|
|
103
114
|
const avdConfig = emulatorConfig.avd;
|
|
@@ -141,11 +152,19 @@ export const getAndroidEmulatorPlatformInstance = async (config, harnessConfig,
|
|
|
141
152
|
}
|
|
142
153
|
androidInstanceLogger.debug('waiting for Android emulator %s to finish booting', adbId);
|
|
143
154
|
const isInstalled = await adb.isAppInstalled(adbId, config.bundleId);
|
|
144
|
-
|
|
145
|
-
|
|
155
|
+
const appPath = getOptionalHarnessAppPath();
|
|
156
|
+
if (isInstalled && appPath) {
|
|
157
|
+
await adb.uninstallApp(adbId, config.bundleId);
|
|
146
158
|
await adb.installApp(adbId, appPath);
|
|
147
159
|
}
|
|
160
|
+
else if (!isInstalled) {
|
|
161
|
+
const installPath = appPath ?? getHarnessAppPath();
|
|
162
|
+
await adb.installApp(adbId, installPath);
|
|
163
|
+
}
|
|
148
164
|
const appUid = await configureAndroidRuntime(adbId, config, harnessConfig);
|
|
165
|
+
if (permissionsEnabled) {
|
|
166
|
+
await adb.grantPermissions(adbId, config.bundleId);
|
|
167
|
+
}
|
|
149
168
|
return {
|
|
150
169
|
startApp: async (options) => {
|
|
151
170
|
await adb.startApp(adbId, config.bundleId, config.activityName, options ??
|
|
@@ -187,6 +206,7 @@ export const getAndroidEmulatorPlatformInstance = async (config, harnessConfig,
|
|
|
187
206
|
export const getAndroidPhysicalDevicePlatformInstance = async (config, harnessConfig) => {
|
|
188
207
|
assertAndroidDevicePhysical(config.device);
|
|
189
208
|
const detectNativeCrashes = harnessConfig.detectNativeCrashes ?? true;
|
|
209
|
+
const permissionsEnabled = harnessConfig.permissions ?? false;
|
|
190
210
|
const adbId = await getAdbId(config.device);
|
|
191
211
|
if (!adbId) {
|
|
192
212
|
throw new DeviceNotFoundError(getDeviceName(config.device));
|
|
@@ -196,6 +216,9 @@ export const getAndroidPhysicalDevicePlatformInstance = async (config, harnessCo
|
|
|
196
216
|
throw new AppNotInstalledError(config.bundleId, getDeviceName(config.device));
|
|
197
217
|
}
|
|
198
218
|
const appUid = await configureAndroidRuntime(adbId, config, harnessConfig);
|
|
219
|
+
if (permissionsEnabled) {
|
|
220
|
+
await adb.grantPermissions(adbId, config.bundleId);
|
|
221
|
+
}
|
|
199
222
|
return {
|
|
200
223
|
startApp: async (options) => {
|
|
201
224
|
await adb.startApp(adbId, config.bundleId, config.activityName, options ??
|