@efffrida/frida-tools 0.0.26 → 0.0.28
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/FridaDevice.d.ts +9 -8
- package/dist/FridaDevice.d.ts.map +1 -1
- package/dist/FridaDevice.js.map +1 -1
- package/dist/FridaDeviceAcquisitionError.d.ts +3 -18
- package/dist/FridaDeviceAcquisitionError.d.ts.map +1 -1
- package/dist/FridaDeviceAcquisitionError.js +2 -13
- package/dist/FridaDeviceAcquisitionError.js.map +1 -1
- package/dist/FridaScript.d.ts +12 -13
- package/dist/FridaScript.d.ts.map +1 -1
- package/dist/FridaScript.js +10 -9
- package/dist/FridaScript.js.map +1 -1
- package/dist/FridaSession.d.ts +21 -7
- package/dist/FridaSession.d.ts.map +1 -1
- package/dist/FridaSession.js.map +1 -1
- package/dist/FridaSessionError.d.ts +1 -16
- package/dist/FridaSessionError.d.ts.map +1 -1
- package/dist/FridaSessionError.js +2 -13
- package/dist/FridaSessionError.js.map +1 -1
- package/dist/internal/compiler.d.ts +2 -0
- package/dist/internal/compiler.d.ts.map +1 -0
- package/dist/internal/compiler.js +82 -0
- package/dist/internal/compiler.js.map +1 -0
- package/dist/internal/device.js +33 -32
- package/dist/internal/device.js.map +1 -1
- package/dist/internal/script.js +56 -105
- package/dist/internal/script.js.map +1 -1
- package/dist/internal/session.js +90 -48
- package/dist/internal/session.js.map +1 -1
- package/package.json +11 -17
- package/src/FridaDevice.ts +11 -10
- package/src/FridaDeviceAcquisitionError.ts +4 -29
- package/src/FridaScript.ts +22 -23
- package/src/FridaSession.ts +25 -7
- package/src/FridaSessionError.ts +2 -24
- package/src/internal/compiler.ts +122 -0
- package/src/internal/device.ts +85 -67
- package/src/internal/script.ts +209 -292
- package/src/internal/session.ts +116 -52
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import * as Cause from "effect/Cause";
|
|
2
|
+
import * as Context from "effect/Context";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Function from "effect/Function";
|
|
5
|
+
import * as Predicate from "effect/Predicate";
|
|
6
|
+
|
|
7
|
+
import * as Frida from "frida";
|
|
8
|
+
|
|
9
|
+
import * as FridaSessionError from "../FridaSessionError.ts";
|
|
10
|
+
|
|
11
|
+
/** @internal */
|
|
12
|
+
export const Compiler: Context.Reference<Frida.Compiler> = Context.Reference<Frida.Compiler>(
|
|
13
|
+
"@efffrida/frida-tools/compiler/default",
|
|
14
|
+
{ defaultValue: () => new Frida.Compiler() }
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
/** @internal */
|
|
18
|
+
export const compile = Function.dual<
|
|
19
|
+
(
|
|
20
|
+
options?: Frida.CompilerOptions | undefined
|
|
21
|
+
) => (path: string) => Effect.Effect<string, FridaSessionError.FridaSessionError, never>,
|
|
22
|
+
(
|
|
23
|
+
path: string,
|
|
24
|
+
options?: Frida.CompilerOptions | undefined
|
|
25
|
+
) => Effect.Effect<string, FridaSessionError.FridaSessionError, never>
|
|
26
|
+
>(
|
|
27
|
+
(arguments_) => Predicate.isString(arguments_[0]),
|
|
28
|
+
(path: string, options?: Frida.CompilerOptions | undefined) =>
|
|
29
|
+
Effect.gen(function* () {
|
|
30
|
+
const compiler = yield* Compiler;
|
|
31
|
+
|
|
32
|
+
// https://github.com/frida/frida-compile/blob/e81ae27369466c69868fc6ee36c0f227bbfe340c/src/cli.ts#L173-L182
|
|
33
|
+
interface Diagnostic {
|
|
34
|
+
category: string;
|
|
35
|
+
code: number;
|
|
36
|
+
text: string;
|
|
37
|
+
file?: {
|
|
38
|
+
path: string;
|
|
39
|
+
line: number;
|
|
40
|
+
character: number;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const formatDiagnostic = (diagnostic: Diagnostic): FridaSessionError.FridaSessionError => {
|
|
45
|
+
const location = diagnostic.file
|
|
46
|
+
? `${diagnostic.file.path}:${diagnostic.file.line}:${diagnostic.file.character}`
|
|
47
|
+
: undefined;
|
|
48
|
+
const message = `TS${diagnostic.code}: ${diagnostic.text}`;
|
|
49
|
+
const cause = location ? `${location} - ${message}` : message;
|
|
50
|
+
return new FridaSessionError.FridaSessionError({ cause, when: "compile" });
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const compileErrors: Array<Diagnostic> = [];
|
|
54
|
+
const cancellable = new Frida.Cancellable();
|
|
55
|
+
|
|
56
|
+
const compilerBuildOptions = {
|
|
57
|
+
externals: options?.externals,
|
|
58
|
+
projectRoot: options?.projectRoot,
|
|
59
|
+
platform: options?.platform ?? Frida.JsPlatform.Gum,
|
|
60
|
+
typeCheck: options?.typeCheck ?? Frida.TypeCheckMode.Full,
|
|
61
|
+
sourceMaps: options?.sourceMaps ?? Frida.SourceMaps.Included,
|
|
62
|
+
compression: options?.compression ?? Frida.JsCompression.None,
|
|
63
|
+
bundleFormat: options?.bundleFormat ?? Frida.BundleFormat.Esm,
|
|
64
|
+
outputFormat: options?.outputFormat ?? Frida.OutputFormat.Unescaped,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return yield* Effect.callback<string, FridaSessionError.FridaSessionError, never>((resume) => {
|
|
68
|
+
const onOutput = (bundle: string) => {
|
|
69
|
+
disconnectAll();
|
|
70
|
+
resume(Effect.succeed(bundle));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const onDiagnostic = (diagnostic: Array<Diagnostic>) => {
|
|
74
|
+
for (const diag of diagnostic) {
|
|
75
|
+
if (diag.category === "error") {
|
|
76
|
+
compileErrors.push(diag);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const onFinished = () => {
|
|
82
|
+
disconnectAll();
|
|
83
|
+
if (compileErrors.length > 0) {
|
|
84
|
+
resume(
|
|
85
|
+
Effect.failCauseSync(() => {
|
|
86
|
+
const [first, ...rest] = compileErrors;
|
|
87
|
+
let cause = Cause.fail(formatDiagnostic(first));
|
|
88
|
+
for (const diag of rest) {
|
|
89
|
+
cause = Cause.combine(cause, Cause.fail(formatDiagnostic(diag)));
|
|
90
|
+
}
|
|
91
|
+
return cause;
|
|
92
|
+
})
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
compiler.output.connect(onOutput);
|
|
98
|
+
compiler.diagnostics.connect(onDiagnostic);
|
|
99
|
+
compiler.finished.connect(onFinished);
|
|
100
|
+
const disconnectAll = () => {
|
|
101
|
+
compiler.output.disconnect(onOutput);
|
|
102
|
+
compiler.diagnostics.disconnect(onDiagnostic);
|
|
103
|
+
compiler.finished.disconnect(onFinished);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
compiler.build(path, compilerBuildOptions, cancellable).catch((cause) => {
|
|
107
|
+
disconnectAll();
|
|
108
|
+
resume(
|
|
109
|
+
new FridaSessionError.FridaSessionError({
|
|
110
|
+
when: "compile",
|
|
111
|
+
cause,
|
|
112
|
+
})
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return Effect.sync(() => {
|
|
117
|
+
disconnectAll();
|
|
118
|
+
cancellable.cancel();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
})
|
|
122
|
+
);
|
package/src/internal/device.ts
CHANGED
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
import type * as
|
|
2
|
-
import type * as ConfigError from "effect/ConfigError";
|
|
1
|
+
import type * as PlatformError from "effect/PlatformError";
|
|
3
2
|
import type * as Scope from "effect/Scope";
|
|
4
3
|
|
|
5
|
-
import * as Command from "@effect/platform/Command";
|
|
6
|
-
import * as PlatformError from "@effect/platform/Error";
|
|
7
|
-
import * as Chunk from "effect/Chunk";
|
|
8
4
|
import * as Config from "effect/Config";
|
|
9
5
|
import * as Context from "effect/Context";
|
|
10
6
|
import * as Effect from "effect/Effect";
|
|
11
7
|
import * as Layer from "effect/Layer";
|
|
12
|
-
import * as
|
|
8
|
+
import * as Path from "effect/Path";
|
|
13
9
|
import * as Predicate from "effect/Predicate";
|
|
14
10
|
import * as Schema from "effect/Schema";
|
|
15
11
|
import * as Stream from "effect/Stream";
|
|
16
12
|
import * as String from "effect/String";
|
|
17
13
|
import * as Tuple from "effect/Tuple";
|
|
18
|
-
import * as
|
|
19
|
-
import * as
|
|
20
|
-
import * as path from "node:path";
|
|
14
|
+
import * as ChildProcess from "effect/unstable/process/ChildProcess";
|
|
15
|
+
import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner";
|
|
21
16
|
|
|
22
17
|
import type * as FridaDevice from "../FridaDevice.ts";
|
|
23
18
|
|
|
19
|
+
import * as Frida from "frida";
|
|
20
|
+
|
|
24
21
|
import * as FridaDeviceAcquisitionError from "../FridaDeviceAcquisitionError.ts";
|
|
25
22
|
|
|
26
23
|
/** @internal */
|
|
@@ -29,7 +26,7 @@ export const FridaDeviceTypeId: FridaDevice.FridaDeviceTypeId = Symbol.for(
|
|
|
29
26
|
) as FridaDevice.FridaDeviceTypeId;
|
|
30
27
|
|
|
31
28
|
/** @internal */
|
|
32
|
-
export const Tag = Context.
|
|
29
|
+
export const Tag = Context.Service<FridaDevice.FridaDevice>("@efffrida/frida-tools/FridaDevice");
|
|
33
30
|
|
|
34
31
|
/** @internal */
|
|
35
32
|
export const isFridaDevice = (u: unknown): u is FridaDevice.FridaDevice => Predicate.hasProperty(u, FridaDeviceTypeId);
|
|
@@ -142,14 +139,15 @@ export const acquireAndroidEmulatorDevice = Effect.fn("acquireAndroidEmulatorDev
|
|
|
142
139
|
| undefined
|
|
143
140
|
): Effect.fn.Return<
|
|
144
141
|
FridaDevice.FridaDevice,
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
PlatformError.PlatformError | FridaDeviceAcquisitionError.FridaDeviceAcquisitionError,
|
|
143
|
+
ChildProcessSpawner.ChildProcessSpawner | Scope.Scope
|
|
147
144
|
> {
|
|
148
145
|
const hidden = options?.hidden ?? false;
|
|
149
146
|
const adbExecutable = options?.adbExecutable ?? "adb";
|
|
150
147
|
const emulatorExecutable = options?.emulatorExecutable ?? "emulator";
|
|
151
148
|
const fridaExecutable = options?.fridaExecutable ?? "/data/local/tmp/frida-server";
|
|
152
149
|
|
|
150
|
+
const net = yield* Effect.promise(() => import("node:net"));
|
|
153
151
|
yield* Effect.annotateCurrentSpan({
|
|
154
152
|
"emulator.name": name,
|
|
155
153
|
"emulator.hidden": hidden,
|
|
@@ -159,7 +157,7 @@ export const acquireAndroidEmulatorDevice = Effect.fn("acquireAndroidEmulatorDev
|
|
|
159
157
|
});
|
|
160
158
|
|
|
161
159
|
const getTwoConsecutiveFreePorts = (startingAt: number = 2000) =>
|
|
162
|
-
Effect.
|
|
160
|
+
Effect.callback<readonly [firstPort: number, secondPort: number], never, never>((resume) => {
|
|
163
161
|
const socket1 = net.createConnection(startingAt);
|
|
164
162
|
const socket2 = net.createConnection(startingAt + 1);
|
|
165
163
|
|
|
@@ -171,12 +169,11 @@ export const acquireAndroidEmulatorDevice = Effect.fn("acquireAndroidEmulatorDev
|
|
|
171
169
|
};
|
|
172
170
|
|
|
173
171
|
const onError = (error: NodeJS.ErrnoException) => {
|
|
174
|
-
|
|
175
|
-
resume(Effect.dieMessage("Failed to get two free consecutive ports"));
|
|
176
|
-
}
|
|
172
|
+
cleanup();
|
|
177
173
|
|
|
178
|
-
if (
|
|
179
|
-
|
|
174
|
+
if (error.code !== "ECONNREFUSED") {
|
|
175
|
+
resume(Effect.die("Failed to get two free consecutive ports"));
|
|
176
|
+
} else if (socket1.connecting === false && socket2.connecting === false) {
|
|
180
177
|
resume(Effect.succeed(Tuple.make(startingAt, startingAt + 1)));
|
|
181
178
|
}
|
|
182
179
|
};
|
|
@@ -193,13 +190,13 @@ export const acquireAndroidEmulatorDevice = Effect.fn("acquireAndroidEmulatorDev
|
|
|
193
190
|
return Effect.sync(() => cleanup());
|
|
194
191
|
});
|
|
195
192
|
|
|
193
|
+
const childProcessSpawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
196
194
|
const filterExitOk = (code: number) => (code === 0 ? Effect.void : Effect.fail(code));
|
|
197
195
|
|
|
198
196
|
const [firstPort, _secondPort] = yield* getTwoConsecutiveFreePorts();
|
|
199
197
|
const emulator = `emulator-${firstPort}`;
|
|
200
198
|
|
|
201
|
-
const emulatorProcess = yield*
|
|
202
|
-
emulatorExecutable,
|
|
199
|
+
const emulatorProcess = yield* ChildProcess.make(emulatorExecutable, [
|
|
203
200
|
`@${name}`,
|
|
204
201
|
"-delay-adb",
|
|
205
202
|
"-read-only",
|
|
@@ -207,12 +204,12 @@ export const acquireAndroidEmulatorDevice = Effect.fn("acquireAndroidEmulatorDev
|
|
|
207
204
|
"-port",
|
|
208
205
|
firstPort.toString(),
|
|
209
206
|
...(hidden ? ["-no-window"] : []),
|
|
210
|
-
...(options?.extraEmulatorArgs ?? [])
|
|
211
|
-
)
|
|
207
|
+
...(options?.extraEmulatorArgs ?? []),
|
|
208
|
+
]);
|
|
212
209
|
|
|
213
210
|
yield* Effect.addFinalizer(() =>
|
|
214
|
-
|
|
215
|
-
|
|
211
|
+
ChildProcess.make(adbExecutable, ["-s", emulator, "emu", "kill"]).pipe(
|
|
212
|
+
childProcessSpawner.exitCode,
|
|
216
213
|
Effect.flatMap(filterExitOk),
|
|
217
214
|
Effect.orDie
|
|
218
215
|
)
|
|
@@ -223,49 +220,64 @@ export const acquireAndroidEmulatorDevice = Effect.fn("acquireAndroidEmulatorDev
|
|
|
223
220
|
String.includes("Boot completed")
|
|
224
221
|
);
|
|
225
222
|
|
|
226
|
-
const decoder = new TextDecoder();
|
|
227
223
|
yield* emulatorProcess.stderr.pipe(Stream.runHead, Effect.forkScoped);
|
|
228
224
|
yield* emulatorProcess.stdout.pipe(
|
|
229
|
-
Stream.
|
|
225
|
+
Stream.decodeText(),
|
|
230
226
|
Stream.splitLines,
|
|
231
227
|
Stream.takeUntil(isBootCompletedPredicate),
|
|
232
228
|
Stream.runDrain
|
|
233
229
|
);
|
|
234
230
|
|
|
235
|
-
yield*
|
|
236
|
-
|
|
231
|
+
yield* ChildProcess.make(adbExecutable, ["-s", emulator, "wait-for-device"]).pipe(
|
|
232
|
+
childProcessSpawner.exitCode,
|
|
237
233
|
Effect.flatMap(filterExitOk),
|
|
238
|
-
Effect.
|
|
234
|
+
Effect.catchIf(
|
|
235
|
+
Predicate.isNumber,
|
|
239
236
|
(code) =>
|
|
240
237
|
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
241
|
-
attempts: 1,
|
|
242
|
-
acquisitionMethod: "android-emulator",
|
|
243
238
|
cause: `ADB wait-for-device failed with exit code ${code}`,
|
|
239
|
+
acquisitionMethod: "android-emulator",
|
|
240
|
+
attempts: 1,
|
|
244
241
|
})
|
|
245
242
|
)
|
|
246
243
|
);
|
|
247
244
|
|
|
248
|
-
yield*
|
|
249
|
-
|
|
245
|
+
yield* ChildProcess.make(adbExecutable, ["-s", emulator, "root"]).pipe(
|
|
246
|
+
childProcessSpawner.exitCode,
|
|
250
247
|
Effect.flatMap(filterExitOk),
|
|
251
|
-
Effect.
|
|
248
|
+
Effect.catchIf(
|
|
249
|
+
Predicate.isNumber,
|
|
252
250
|
(code) =>
|
|
253
251
|
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
254
|
-
attempts: 1,
|
|
255
|
-
acquisitionMethod: "android-emulator",
|
|
256
252
|
cause: `ADB root failed with exit code ${code}`,
|
|
253
|
+
acquisitionMethod: "android-emulator",
|
|
254
|
+
attempts: 1,
|
|
257
255
|
})
|
|
258
256
|
)
|
|
259
257
|
);
|
|
260
258
|
|
|
261
|
-
yield*
|
|
262
|
-
Command.start,
|
|
259
|
+
yield* ChildProcess.make(adbExecutable, ["-s", emulator, "shell", `"${fridaExecutable}"`]).pipe(
|
|
263
260
|
Effect.andThen(Effect.sleep("3 seconds"))
|
|
264
261
|
);
|
|
265
262
|
|
|
266
|
-
const fridaPort = yield*
|
|
267
|
-
|
|
268
|
-
|
|
263
|
+
const fridaPort = yield* ChildProcess.make(adbExecutable, [
|
|
264
|
+
"-s",
|
|
265
|
+
emulator,
|
|
266
|
+
"forward",
|
|
267
|
+
"tcp:0",
|
|
268
|
+
"tcp:27042",
|
|
269
|
+
]).pipe(
|
|
270
|
+
childProcessSpawner.string,
|
|
271
|
+
Effect.flatMap(Schema.decodeEffect(Schema.NumberFromString)),
|
|
272
|
+
Effect.catchTag(
|
|
273
|
+
"SchemaError",
|
|
274
|
+
(cause) =>
|
|
275
|
+
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
276
|
+
acquisitionMethod: "android-emulator",
|
|
277
|
+
attempts: 1,
|
|
278
|
+
cause,
|
|
279
|
+
})
|
|
280
|
+
)
|
|
269
281
|
);
|
|
270
282
|
|
|
271
283
|
const { host: _host, ...remoteDevice } = yield* acquireRemoteDevice(`localhost:${fridaPort}`);
|
|
@@ -275,17 +287,17 @@ export const acquireAndroidEmulatorDevice = Effect.fn("acquireAndroidEmulatorDev
|
|
|
275
287
|
host: `android-emulator://${emulator}`,
|
|
276
288
|
} as const;
|
|
277
289
|
},
|
|
278
|
-
Effect.
|
|
290
|
+
Effect.timeoutOrElse({
|
|
279
291
|
duration: "1 minute",
|
|
280
|
-
|
|
292
|
+
orElse: () =>
|
|
281
293
|
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
282
294
|
cause: "Timeout while acquiring Android emulator device",
|
|
283
295
|
acquisitionMethod: "android-emulator",
|
|
284
296
|
attempts: 1,
|
|
285
297
|
}),
|
|
286
298
|
}),
|
|
287
|
-
Effect.
|
|
288
|
-
|
|
299
|
+
Effect.catchTag(
|
|
300
|
+
"PlatformError",
|
|
289
301
|
(cause) =>
|
|
290
302
|
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
291
303
|
acquisitionMethod: "android-emulator",
|
|
@@ -305,22 +317,28 @@ export const acquireAndroidEmulatorDeviceConfig = (
|
|
|
305
317
|
extraEmulatorArgs?: Array<string> | undefined;
|
|
306
318
|
}
|
|
307
319
|
| undefined
|
|
308
|
-
)
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
})
|
|
320
|
+
): Effect.Effect<
|
|
321
|
+
FridaDevice.FridaDevice,
|
|
322
|
+
FridaDeviceAcquisitionError.FridaDeviceAcquisitionError | Config.ConfigError,
|
|
323
|
+
ChildProcessSpawner.ChildProcessSpawner | Path.Path | Scope.Scope
|
|
324
|
+
> =>
|
|
325
|
+
Effect.flatMap(Path.Path, (path) =>
|
|
326
|
+
Config.string("ANDROID_SDK").pipe(
|
|
327
|
+
Config.map((androidSdk) => ({
|
|
328
|
+
adbExecutable: path.join(androidSdk, "platform-tools", "adb"),
|
|
329
|
+
emulatorExecutable: path.join(androidSdk, "emulator", "emulator"),
|
|
330
|
+
})),
|
|
331
|
+
// TODO: Should this be optional?
|
|
332
|
+
Config.withDefault({
|
|
333
|
+
adbExecutable: "adb",
|
|
334
|
+
emulatorExecutable: "emulator",
|
|
335
|
+
}),
|
|
336
|
+
Effect.flatMap((androidSdk) =>
|
|
337
|
+
acquireAndroidEmulatorDevice(name, {
|
|
338
|
+
...androidSdk,
|
|
339
|
+
...options,
|
|
340
|
+
})
|
|
341
|
+
)
|
|
324
342
|
)
|
|
325
343
|
);
|
|
326
344
|
|
|
@@ -336,7 +354,7 @@ export const layerRemoteDevice = (
|
|
|
336
354
|
address: string,
|
|
337
355
|
options?: Frida.RemoteDeviceOptions | undefined
|
|
338
356
|
): Layer.Layer<FridaDevice.FridaDevice, FridaDeviceAcquisitionError.FridaDeviceAcquisitionError, never> =>
|
|
339
|
-
Layer.
|
|
357
|
+
Layer.effect(Tag, acquireRemoteDevice(address, options));
|
|
340
358
|
|
|
341
359
|
/** @internal */
|
|
342
360
|
export const layerUsbDevice = (
|
|
@@ -359,8 +377,8 @@ export const layerAndroidEmulatorDevice = (
|
|
|
359
377
|
): Layer.Layer<
|
|
360
378
|
FridaDevice.FridaDevice,
|
|
361
379
|
FridaDeviceAcquisitionError.FridaDeviceAcquisitionError,
|
|
362
|
-
|
|
363
|
-
> => Layer.
|
|
380
|
+
ChildProcessSpawner.ChildProcessSpawner
|
|
381
|
+
> => Layer.effect(Tag, acquireAndroidEmulatorDevice(name, options));
|
|
364
382
|
|
|
365
383
|
/** @internal */
|
|
366
384
|
export const layerAndroidEmulatorDeviceConfig = (
|
|
@@ -374,6 +392,6 @@ export const layerAndroidEmulatorDeviceConfig = (
|
|
|
374
392
|
| undefined
|
|
375
393
|
): Layer.Layer<
|
|
376
394
|
FridaDevice.FridaDevice,
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
> => Layer.
|
|
395
|
+
Config.ConfigError | FridaDeviceAcquisitionError.FridaDeviceAcquisitionError,
|
|
396
|
+
ChildProcessSpawner.ChildProcessSpawner | Path.Path
|
|
397
|
+
> => Layer.effect(Tag, acquireAndroidEmulatorDeviceConfig(name, options));
|