@tapflowio/ios-agent 0.29.0 → 0.30.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.
@@ -3,9 +3,10 @@ import type { AudioFrame } from '@tapflowio/agent-core';
3
3
  * Read the simulator's current media volume (`sim_volume`, 0–100) from its audiosettings.plist and
4
4
  * return it as a 0–1 gain. The Core Audio process tap captures audio *before* the simulator applies
5
5
  * its volume, so the agent multiplies it back in. The plist updates live as the user changes the
6
- * simulator volume. Returns 1 (full) when unreadable — a volume-read failure must never mute audio.
6
+ * simulator volume. Resolves 1 (full) when unreadable — a volume-read failure must never mute audio.
7
+ * Asynchronous because it is polled beside `enumerateSimPids`, on the loop that carries the video.
7
8
  */
8
- export declare function readSimVolume(udid: string): number;
9
+ export declare function readSimVolume(udid: string): Promise<number>;
9
10
  export declare function parseAudioFrames(buf: Buffer): {
10
11
  frames: Buffer[];
11
12
  rest: Buffer;
@@ -1 +1 @@
1
- {"version":3,"file":"AudioCaptureStreamer.d.ts","sourceRoot":"","sources":["../src/AudioCaptureStreamer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AASvD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASlD;AAKD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAShF;AAID,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAKzD;AAED;;;;;;;GAOG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,UAAU,CAA2D;IAC7E,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,IAAI,CAAI;IAChB,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,WAAW,CAAwB;IAE3C,yFAAyF;IACzF,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAazB,OAAO,CAAC,YAAY;IAiBpB;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAKhC,OAAO,CAAC,SAAS;IAOjB,yEAAyE;IACzE,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC;IAOpC,IAAI,IAAI,IAAI;CAOb"}
1
+ {"version":3,"file":"AudioCaptureStreamer.d.ts","sourceRoot":"","sources":["../src/AudioCaptureStreamer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AASvD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa3D;AAKD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAShF;AAID,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAKzD;AAED;;;;;;;GAOG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,UAAU,CAA2D;IAC7E,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,IAAI,CAAI;IAChB,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,WAAW,CAAwB;IAE3C,yFAAyF;IACzF,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAazB,OAAO,CAAC,YAAY;IAiBpB;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAKhC,OAAO,CAAC,SAAS;IAOjB,yEAAyE;IACzE,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC;IAOpC,IAAI,IAAI,IAAI;CAOb"}
@@ -1,6 +1,6 @@
1
1
  import net from 'node:net';
2
2
  import os from 'node:os';
3
- import { execFileSync } from 'node:child_process';
3
+ import { execFile } from 'node:child_process';
4
4
  import { join } from 'node:path';
5
5
  import { createLogger } from '@tapflowio/agent-core';
6
6
  const logger = createLogger('ios-agent:audio');
@@ -11,18 +11,24 @@ const logger = createLogger('ios-agent:audio');
11
11
  * Read the simulator's current media volume (`sim_volume`, 0–100) from its audiosettings.plist and
12
12
  * return it as a 0–1 gain. The Core Audio process tap captures audio *before* the simulator applies
13
13
  * its volume, so the agent multiplies it back in. The plist updates live as the user changes the
14
- * simulator volume. Returns 1 (full) when unreadable — a volume-read failure must never mute audio.
14
+ * simulator volume. Resolves 1 (full) when unreadable — a volume-read failure must never mute audio.
15
+ * Asynchronous because it is polled beside `enumerateSimPids`, on the loop that carries the video.
15
16
  */
16
17
  export function readSimVolume(udid) {
17
18
  const plist = join(os.homedir(), 'Library', 'Developer', 'CoreSimulator', 'Devices', udid, 'data', 'var', 'run', 'simulatoraudio', 'audiosettings.plist');
18
- try {
19
- const json = execFileSync('plutil', ['-convert', 'json', '-o', '-', plist], { encoding: 'utf8' });
20
- const v = JSON.parse(json).sim_volume;
21
- if (typeof v === 'number' && v >= 0)
22
- return Math.min(1, v / 100);
23
- }
24
- catch { /* plist missing / not yet created → full volume */ }
25
- return 1;
19
+ return new Promise((resolve) => {
20
+ execFile('/usr/bin/plutil', ['-convert', 'json', '-o', '-', plist], { encoding: 'utf8', timeout: 2_000, killSignal: 'SIGKILL' }, (err, json) => {
21
+ if (err)
22
+ return resolve(1); // plist missing / not yet created → full volume
23
+ try {
24
+ const v = JSON.parse(json).sim_volume;
25
+ resolve(typeof v === 'number' && v >= 0 ? Math.min(1, v / 100) : 1);
26
+ }
27
+ catch {
28
+ resolve(1);
29
+ }
30
+ });
31
+ });
26
32
  }
27
33
  // Wire format from the audiotap-helper: length-prefixed PCM frames — [u32 BE len][PCM bytes], where
28
34
  // PCM is normalized S16LE / 44100 / Stereo. Mirrors the video helper's length-prefix framing
@@ -1 +1 @@
1
- {"version":3,"file":"AudioCaptureStreamer.js","sourceRoot":"","sources":["../src/AudioCaptureStreamer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AudioCaptureStreamer.js","sourceRoot":"","sources":["../src/AudioCaptureStreamer.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { Device, DeviceAgent, NetworkControlCapability, NetworkStatePayload, UIElement } from '@tapflowio/agent-core';
2
+ import type { LaunchOptions } from '@tapflowio/protocol';
2
3
  export declare const IOS_BUTTON_ALIASES: Record<string, string>;
3
4
  import { type SleepBlocker } from '@tapflowio/agent-core/utils';
4
5
  import { SimctlWrapper } from './SimctlWrapper.js';
@@ -108,6 +109,7 @@ export declare class IOSAgent implements DeviceAgent, NetworkControlCapability {
108
109
  * falling back to nothing would blank a form factor it already had until the next reconnect. */
109
110
  private formFactors;
110
111
  private resourcesTimer;
112
+ private resourcesInFlight;
111
113
  private readonly resources;
112
114
  private _stopping;
113
115
  private _reconnectTimer;
@@ -128,6 +130,9 @@ export declare class IOSAgent implements DeviceAgent, NetworkControlCapability {
128
130
  disconnect(): void;
129
131
  /** `loss` is absent when a reconnect attempt failed: there is no close to describe, only a retry. */
130
132
  private _scheduleReconnect;
133
+ /** Samples off the event loop, then reports. One sample at a time per socket, so a slow one (bounded by its
134
+ * 1 s timeout) is not stacked by the next tick; keyed by socket, so a reconnect is not skipped behind the
135
+ * old socket's sample. Slots and the clock are read after the sample, when the report leaves. */
131
136
  private reportResources;
132
137
  private cleanupDeviceState;
133
138
  private stopAudioCapture;
@@ -316,7 +321,7 @@ export declare class IOSAgent implements DeviceAgent, NetworkControlCapability {
316
321
  */
317
322
  setNetworkOffline(offline: boolean): Promise<NetworkStatePayload>;
318
323
  networkState(): Promise<NetworkStatePayload>;
319
- launchApp(bundleId: string): Promise<void>;
324
+ launchApp(bundleId: string, options?: LaunchOptions): Promise<void>;
320
325
  /** The one booted session, or undefined when there is no unambiguous answer. Callers that can
321
326
  * reasonably do nothing (input) use this; callers that owe the user a result use
322
327
  * `soleDeviceState`, which throws instead. */
@@ -367,7 +372,7 @@ export declare class IOSAgent implements DeviceAgent, NetworkControlCapability {
367
372
  private audioEnabled;
368
373
  private startAudioCapture;
369
374
  private launchWholeSimTap;
370
- private refreshAudioPids;
375
+ private refreshAudio;
371
376
  private pumpAudio;
372
377
  screenshot(): Promise<Buffer>;
373
378
  stream(): ReadableStream<Buffer>;
@@ -1 +1 @@
1
- {"version":3,"file":"IOSAgent.d.ts","sourceRoot":"","sources":["../src/IOSAgent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"IOSAgent.d.ts","sourceRoot":"","sources":["../src/IOSAgent.ts"],"names":[],"mappings":"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"}
package/dist/IOSAgent.js CHANGED
@@ -6,6 +6,7 @@ import { randomUUID } from 'crypto';
6
6
  import { spawn } from 'child_process';
7
7
  import { WebSocket } from 'ws';
8
8
  import { createLogger, PlatformError, ValidationError, bootAbandonMessage, BOOT_NO_SESSION_STATE, SHUTDOWN_NO_SESSION_STATE, downloadBuild } from '@tapflowio/agent-core';
9
+ import { appliedKeys, compactLaunchOptions, launchOptionsProblem } from '@tapflowio/protocol/launch';
9
10
  const logger = createLogger('ios-agent');
10
11
  /** The run reset's pasteboard step, the wait for the clipboard queue included; one step's bound like the others. */
11
12
  const RUN_RESET_PASTEBOARD_TIMEOUT_MS = 10_000;
@@ -16,7 +17,7 @@ const RUN_RESET_PASTEBOARD_TIMEOUT_MS = 10_000;
16
17
  // actually took is per device and per app, and `network:state.available` carries that — the split the
17
18
  // protocol documents. Added last, after the handler and the boot-time arming, because the string on
18
19
  // its own is what puts a control on screen.
19
- const AGENT_CAPABILITIES = ['clipboard', 'full-reset', 'network-control', 'build-download'];
20
+ const AGENT_CAPABILITIES = ['clipboard', 'full-reset', 'network-control', 'build-download', 'launch-options', 'launch-env'];
20
21
  // Human prose for each reason. Not in `@tapflowio/protocol`: that package's main entry must stay
21
22
  // runtime-free so it erases under `import type` and never reaches the dashboard bundle — a lookup
22
23
  // table is a runtime value. The `reason` on the wire is the machine-readable half; this is only what
@@ -158,6 +159,7 @@ export class IOSAgent {
158
159
  * falling back to nothing would blank a form factor it already had until the next reconnect. */
159
160
  formFactors = new Map();
160
161
  resourcesTimer = null;
162
+ resourcesInFlight = null;
161
163
  resources = createResourceSampler();
162
164
  _stopping = false;
163
165
  _reconnectTimer = null;
@@ -301,8 +303,8 @@ export class IOSAgent {
301
303
  }
302
304
  catch { /* ignore malformed */ }
303
305
  });
304
- this.reportResources();
305
- this.resourcesTimer = setInterval(() => this.reportResources(), 5000);
306
+ void this.reportResources();
307
+ this.resourcesTimer = setInterval(() => { void this.reportResources(); }, 5000);
306
308
  this.lastPingAt = null;
307
309
  this.lastSocketError = undefined;
308
310
  ws.on('ping', () => { this.lastPingAt = Date.now(); });
@@ -434,24 +436,41 @@ export class IOSAgent {
434
436
  });
435
437
  }, delay);
436
438
  }
437
- reportResources() {
438
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
439
+ /** Samples off the event loop, then reports. One sample at a time per socket, so a slow one (bounded by its
440
+ * 1 s timeout) is not stacked by the next tick; keyed by socket, so a reconnect is not skipped behind the
441
+ * old socket's sample. Slots and the clock are read after the sample, when the report leaves. */
442
+ async reportResources() {
443
+ const ws = this.ws;
444
+ if (!ws || ws.readyState !== WebSocket.OPEN || this.resourcesInFlight === ws)
439
445
  return;
440
- const bootedCount = Array.from(this.deviceStates.values()).filter((s) => s.streamReader !== null).length;
441
- const slotsTotal = this.deviceStates.size;
442
- const { memUsedMB, memTotalMB } = this.resources.getMemoryUsage();
443
- this.sendOn(this.ws, {
444
- type: 'agent:resources',
445
- resources: {
446
- cpuPercent: this.resources.getCpuPercent(),
447
- memUsedMB,
448
- memTotalMB,
449
- slotsAvailable: Math.max(0, slotsTotal - bootedCount),
450
- slotsTotal,
451
- reportedAt: Date.now(),
452
- memoryPressure: this.resources.getMemoryPressure(),
453
- },
454
- });
446
+ this.resourcesInFlight = ws;
447
+ try {
448
+ const [{ memUsedMB, memTotalMB }, memoryPressure] = await Promise.all([
449
+ this.resources.getMemoryUsage(),
450
+ this.resources.getMemoryPressure(),
451
+ ]);
452
+ // A reconnect while sampling replaced the socket: this report has nowhere to go.
453
+ if (this.ws !== ws || ws.readyState !== WebSocket.OPEN)
454
+ return;
455
+ const bootedCount = Array.from(this.deviceStates.values()).filter((s) => s.streamReader !== null).length;
456
+ const slotsTotal = this.deviceStates.size;
457
+ this.sendOn(ws, {
458
+ type: 'agent:resources',
459
+ resources: {
460
+ cpuPercent: this.resources.getCpuPercent(),
461
+ memUsedMB,
462
+ memTotalMB,
463
+ slotsAvailable: Math.max(0, slotsTotal - bootedCount),
464
+ slotsTotal,
465
+ reportedAt: Date.now(),
466
+ memoryPressure,
467
+ },
468
+ });
469
+ }
470
+ finally {
471
+ if (this.resourcesInFlight === ws)
472
+ this.resourcesInFlight = null;
473
+ }
455
474
  }
456
475
  cleanupDeviceState(state) {
457
476
  // Drop this device out of the filter rule. The rule lives on the host and is keyed only by udid,
@@ -1272,7 +1291,7 @@ export class IOSAgent {
1272
1291
  break;
1273
1292
  }
1274
1293
  case 'app:launch': {
1275
- const { bundleId } = msg.payload;
1294
+ const { bundleId, arguments: args, env } = msg.payload;
1276
1295
  const sessionId = msg.sessionId;
1277
1296
  const { requestId } = msg;
1278
1297
  if (typeof requestId !== 'string' || requestId === '') {
@@ -1287,12 +1306,20 @@ export class IOSAgent {
1287
1306
  respond({ type: 'app:launch-error', message: 'No booted device' });
1288
1307
  break;
1289
1308
  }
1309
+ // Checked again here rather than trusted: the relay checks with the same function, but an agent is the last
1310
+ // door before a command line, and a relay of another version may check less.
1311
+ const problem = launchOptionsProblem({ arguments: args, env });
1312
+ if (problem) {
1313
+ respond({ type: 'app:launch-error', message: problem });
1314
+ break;
1315
+ }
1316
+ const options = compactLaunchOptions({ arguments: args, env });
1290
1317
  // The target is named BEFORE the launch, and the order is the whole point: dyld reads the
1291
1318
  // environment when the process starts, so naming it afterwards arms the next launch and leaves
1292
1319
  // this one unhooked while `available` would still say true.
1293
1320
  this.network.target(launchState.deviceId, bundleId)
1294
1321
  .catch((e) => logger.warn('could not name the network target:', e.message))
1295
- .then(() => this.simctl.launchApp(launchState.deviceId, bundleId))
1322
+ .then(() => this.simctl.launchApp(launchState.deviceId, bundleId, options))
1296
1323
  .then((pid) => {
1297
1324
  // **After the launch, with the pid it returned.** The network control measures how long a
1298
1325
  // started process has gone without reporting its hooks; opening that window before
@@ -1303,7 +1330,7 @@ export class IOSAgent {
1303
1330
  this.lastBundleIds.set(launchState.deviceId, bundleId);
1304
1331
  // Audio: the whole-sim tap's poll picks up the launched app process within one interval;
1305
1332
  // no per-launch helper needed.
1306
- respond({ type: 'app:launch-done' });
1333
+ respond(options ? { type: 'app:launch-done', applied: appliedKeys(options) } : { type: 'app:launch-done' });
1307
1334
  })
1308
1335
  .catch((e) => {
1309
1336
  // The toast gets the reason alone; the full simctl output stays in this log.
@@ -2119,8 +2146,11 @@ export class IOSAgent {
2119
2146
  async networkState() {
2120
2147
  return this.network.state(await this.soleLiveDeviceId());
2121
2148
  }
2122
- async launchApp(bundleId) {
2123
- await this.simctl.launchApp(await this.soleLiveDeviceId(), bundleId);
2149
+ async launchApp(bundleId, options) {
2150
+ const problem = launchOptionsProblem(options ?? {});
2151
+ if (problem)
2152
+ throw new ValidationError(problem);
2153
+ await this.simctl.launchApp(await this.soleLiveDeviceId(), bundleId, compactLaunchOptions(options));
2124
2154
  }
2125
2155
  /** The one booted session, or undefined when there is no unambiguous answer. Callers that can
2126
2156
  * reasonably do nothing (input) use this; callers that owe the user a result use
@@ -2228,7 +2258,7 @@ export class IOSAgent {
2228
2258
  const seq = state.bootSeq;
2229
2259
  const streamer = new AudioCaptureStreamer();
2230
2260
  streamer.listen()
2231
- .then((port) => {
2261
+ .then(async (port) => {
2232
2262
  // A reboot/shutdown/disconnect may have superseded this boot while listen() was binding —
2233
2263
  // discard so we don't leave an orphan helper/poll/server behind the current lifecycle.
2234
2264
  if (seq !== state.bootSeq || streamWs.readyState !== WebSocket.OPEN) {
@@ -2237,21 +2267,37 @@ export class IOSAgent {
2237
2267
  }
2238
2268
  state.audioStreamer = streamer;
2239
2269
  state.audioPort = port;
2240
- state.audioVolume = readSimVolume(udid);
2270
+ // Read before launching, so the first frames carry the sim's volume rather than full.
2271
+ const [pids, volume] = await Promise.all([enumerateSimPids(udid), readSimVolume(udid)]);
2272
+ // A stop or reboot while reading retired this capture: `stopAudioCapture` already stopped `streamer`,
2273
+ // and launching the helper now would tap a device nobody is streaming.
2274
+ if (state.audioStreamer !== streamer)
2275
+ return;
2276
+ // Only the control socket's close tears audio down; a stream socket that closed while reading would
2277
+ // leave a helper and a poll running for nothing until the next reboot.
2278
+ if (streamWs.readyState !== WebSocket.OPEN) {
2279
+ this.stopAudioCapture(state);
2280
+ return;
2281
+ }
2282
+ state.audioVolume = volume;
2241
2283
  void this.pumpAudio(streamWs, streamer.frames(), state);
2242
- this.launchWholeSimTap(state, udid);
2284
+ this.launchWholeSimTap(state, pids);
2285
+ // Started after the launch, so the first poll never races the launch's own pid set. One poll at a
2286
+ // time: `ps` is bounded by its timeout, and a slow one is not stacked by the next tick.
2287
+ let polling = false;
2243
2288
  state.audioPoll = setInterval(() => {
2244
- this.refreshAudioPids(state, udid);
2245
- state.audioVolume = readSimVolume(udid); // track live sim-volume changes
2289
+ if (polling)
2290
+ return;
2291
+ polling = true;
2292
+ void this.refreshAudio(state, udid, streamer).finally(() => { polling = false; });
2246
2293
  }, AUDIO_POLL_MS);
2247
2294
  })
2248
2295
  .catch((e) => logger.warn(`audio capture server failed to start: ${e instanceof Error ? e.message : String(e)}`));
2249
2296
  }
2250
2297
  // Launch the tap helper for the simulator's whole process tree. Swallows errors — audio must never
2251
2298
  // break the launch/video path (e.g. helper build fails, or the user hasn't granted the audio
2252
- // permission). The helper holds the socket open; refreshAudioPids() pushes later updates to it.
2253
- launchWholeSimTap(state, udid) {
2254
- const pids = enumerateSimPids(udid);
2299
+ // permission). The helper holds the socket open; refreshAudio() pushes later updates to it.
2300
+ launchWholeSimTap(state, pids) {
2255
2301
  if (!pids.length) {
2256
2302
  logger.warn('no simulator processes to tap (audio idle until first poll)');
2257
2303
  return;
@@ -2268,18 +2314,21 @@ export class IOSAgent {
2268
2314
  // freshly spawned WebKit WebContent), push the updated set so the helper rebuilds its tap. Dead pids
2269
2315
  // need no rebuild — they resolve to no audio object, so the helper just stops mixing them; we still
2270
2316
  // refresh the baseline so a later reappearance is detected. Rebuilding only on additions keeps
2271
- // short-lived daemon churn from causing constant tap teardown (audio glitches).
2272
- refreshAudioPids(state, udid) {
2273
- if (!state.audioStreamer)
2317
+ // short-lived daemon churn from causing constant tap teardown (audio glitches). Also tracks live sim-volume
2318
+ // changes. Both reads are asynchronous, so the capture may have been retired by the time they land; `streamer`
2319
+ // is the capture this poll belongs to.
2320
+ async refreshAudio(state, udid, streamer) {
2321
+ const [pids, volume] = await Promise.all([enumerateSimPids(udid), readSimVolume(udid)]);
2322
+ if (state.audioStreamer !== streamer)
2274
2323
  return;
2275
- const pids = enumerateSimPids(udid);
2324
+ state.audioVolume = volume;
2276
2325
  if (!pids.length)
2277
2326
  return;
2278
2327
  const prev = state.audioPids;
2279
2328
  const hasNew = !prev || pids.some((p) => !prev.has(p));
2280
2329
  state.audioPids = new Set(pids);
2281
2330
  if (hasNew)
2282
- state.audioStreamer.updatePids(pids);
2331
+ streamer.updatePids(pids);
2283
2332
  }
2284
2333
  // Forward captured PCM to the relay on the shared stream socket via the yielding sender (audio must
2285
2334
  // never inflate the socket buffer enough to trip video's backpressure). Mirrors android-agent.