@xenon-device-management/xenon 1.10.1 → 1.10.2

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/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenon-device-management/xenon",
3
- "version": "1.10.1",
3
+ "version": "1.10.2",
4
4
  "description": "Xenon - Intelligent Mobile Infrastructure. A self-healing device orchestration platform for Appium.",
5
5
  "main": "./lib/src/index.js",
6
6
  "exports": {
@@ -45,8 +45,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
45
45
  return (mod && mod.__esModule) ? mod : { "default": mod };
46
46
  };
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.ScrcpyServerSession = exports.SCRCPY_DEVICE_JAR_PATH = void 0;
48
+ exports.ScrcpyServerSession = exports.SCRCPY_CMDLINE_BUDGET = exports.SCRCPY_DEVICE_JAR_PATH = void 0;
49
49
  exports.buildScrcpyServerArgs = buildScrcpyServerArgs;
50
+ exports.scrcpyCmdlineLength = scrcpyCmdlineLength;
50
51
  exports.scrcpyMaxSizeFromDims = scrcpyMaxSizeFromDims;
51
52
  exports.parseAdbForwardPort = parseAdbForwardPort;
52
53
  const child_process_1 = require("child_process");
@@ -69,6 +70,17 @@ exports.SCRCPY_DEVICE_JAR_PATH = '/data/local/tmp/scrcpy-server-manual.jar';
69
70
  * Arg NAMES verified against the vendored scrcpy 2.7 jar's dex; the version
70
71
  * constant and this argv move together (see scrcpyVersion.ts / vendor/README.md).
71
72
  * No `scid` → the server listens on `localabstract:scrcpy` (per-device namespace).
73
+ *
74
+ * KEEP THIS ARGV SHORT — hard cap enforced below. Samsung's Android 10
75
+ * libstagefright patch (`ACodec::reconfigEncoder4OtherApps`) copies the
76
+ * encoder process's cmdline into a fixed ~256-byte stack buffer; if the
77
+ * app_process command line reaches that length, the copy trips the stack
78
+ * canary and the server dies at MediaCodec configure with
79
+ * `stack corruption detected (-fstack-protector)` (SIGABRT). Verified on
80
+ * SM-G965F/Android 10: identical options stream at ≤248 chars and abort at
81
+ * ≥267 — the abort depends only on total length, never on which options.
82
+ * That is why args that merely restate scrcpy 2.7 defaults (`video=true`,
83
+ * `video_codec=h264`, `cleanup=true`) are omitted rather than spelled out.
72
84
  */
73
85
  function buildScrcpyServerArgs(opts) {
74
86
  return [
@@ -81,8 +93,6 @@ function buildScrcpyServerArgs(opts) {
81
93
  'tunnel_forward=true',
82
94
  'audio=false',
83
95
  'control=false',
84
- 'video=true',
85
- 'video_codec=h264',
86
96
  `max_size=${opts.maxSize}`,
87
97
  'video_bit_rate=4000000',
88
98
  'max_fps=30',
@@ -90,9 +100,19 @@ function buildScrcpyServerArgs(opts) {
90
100
  'send_codec_meta=false',
91
101
  'send_frame_meta=false',
92
102
  'send_dummy_byte=true',
93
- 'cleanup=true',
94
103
  ];
95
104
  }
105
+ /**
106
+ * Samsung's buggy cmdline copy (see buildScrcpyServerArgs doc) aborts at
107
+ * ~256 chars; crash observed at 267, clean at 248. Budget 240 leaves margin
108
+ * for a wider `max_size` while staying safely under the observed floor.
109
+ */
110
+ exports.SCRCPY_CMDLINE_BUDGET = 240;
111
+ /** The on-device `app_process …` cmdline length for a built argv (drops the host-side `shell` + CLASSPATH env prefix). */
112
+ function scrcpyCmdlineLength(argv) {
113
+ const appProcessIdx = argv.indexOf('app_process');
114
+ return argv.slice(appProcessIdx).join(' ').length;
115
+ }
96
116
  /**
97
117
  * scrcpy `max_size` caps the device's LONGER edge (single int, aspect preserved).
98
118
  * Derive it so the SHORTER edge lands near `targetShortEdge` (matches today's
@@ -15,8 +15,6 @@ describe('buildScrcpyServerArgs', () => {
15
15
  'tunnel_forward=true',
16
16
  'audio=false',
17
17
  'control=false',
18
- 'video=true',
19
- 'video_codec=h264',
20
18
  'max_size=1560',
21
19
  'video_bit_rate=4000000',
22
20
  'max_fps=30',
@@ -24,9 +22,22 @@ describe('buildScrcpyServerArgs', () => {
24
22
  'send_codec_meta=false',
25
23
  'send_frame_meta=false',
26
24
  'send_dummy_byte=true',
27
- 'cleanup=true',
28
25
  ]);
29
26
  });
27
+ it('does not restate scrcpy defaults (video/video_codec/cleanup) — every char counts toward the Samsung cap', () => {
28
+ const argv = (0, ScrcpyServerSession_1.buildScrcpyServerArgs)({ version: '2.7', jarDevicePath: ScrcpyServerSession_1.SCRCPY_DEVICE_JAR_PATH, maxSize: 1560 });
29
+ for (const restated of ['video=true', 'video_codec=h264', 'cleanup=true']) {
30
+ (0, chai_1.expect)(argv, `${restated} restates a scrcpy 2.7 default`).to.not.include(restated);
31
+ }
32
+ });
33
+ it(`keeps the on-device cmdline under the ${ScrcpyServerSession_1.SCRCPY_CMDLINE_BUDGET}-char Samsung stack-buffer budget`, () => {
34
+ // Samsung Android 10 libstagefright (ACodec::reconfigEncoder4OtherApps) SIGABRTs
35
+ // when the encoding process's cmdline hits a ~256-byte stack buffer. Observed on
36
+ // SM-G965F: streams at ≤248 chars, aborts at ≥267. Use the widest realistic
37
+ // max_size (5 digits) so this guard covers the worst case.
38
+ const argv = (0, ScrcpyServerSession_1.buildScrcpyServerArgs)({ version: '2.7', jarDevicePath: ScrcpyServerSession_1.SCRCPY_DEVICE_JAR_PATH, maxSize: 99999 });
39
+ (0, chai_1.expect)((0, ScrcpyServerSession_1.scrcpyCmdlineLength)(argv)).to.be.at.most(ScrcpyServerSession_1.SCRCPY_CMDLINE_BUDGET);
40
+ });
30
41
  });
31
42
  describe('scrcpyMaxSizeFromDims', () => {
32
43
  it('caps the LONGER edge so the shorter edge lands near the target', () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenon-device-management/xenon",
3
- "version": "1.10.1",
3
+ "version": "1.10.2",
4
4
  "description": "Xenon - Intelligent Mobile Infrastructure. A self-healing device orchestration platform for Appium.",
5
5
  "main": "./lib/src/index.js",
6
6
  "exports": {