Repository: wix/Detox (JavaScript)

Issue:
`headless` not respected by AVDValidator emulator version validator
### What happened?

the `headless` config option is not respected by the emulator version validator (it is respected by other commands however)

Example error observed on ubuntu:
```
09:33:44.784 detox[10068] ERROR: [EXEC_FAIL, #1] ""/usr/local/lib/android/sdk/emulator/emulator" -version " failed with error = ChildProcessError: Command failed: "/usr/local/lib/android/sdk/emulator/emulator" -version 
/usr/local/lib/android/sdk/emulator/qemu/linux-x86_64/qemu-system-x86_64: error while loading shared libraries: libpulse.so.0: cannot open shared object file: No such file or directory
 `"/usr/local/lib/android/sdk/emulator/emulator" -version ` (exited with error code 127) (code=127), stdout and stderr:

0[9](https://github.com/letsbuilders/LbSiteDiary/actions/runs/3091392392/jobs/5012531600#step:8:10):33:44.785 detox[[10](https://github.com/letsbuilders/LbSiteDiary/actions/runs/3091392392/jobs/5012531600#step:8:11)068] ERROR: [EXEC_FAIL, #1] 
09:33:44.785 detox[10068] ERROR: [EXEC_FAIL, #1] /usr/local/lib/android/sdk/emulator/qemu/linux-x86_64/qemu-system-x86_64: error while loading shared libraries: libpulse.so.0: cannot open shared object file: No such file or directory
```

### What was the expected behaviour?

_No response_

### Was it tested on latest Detox?

- [X] I have tested this issue on the latest Detox release and it still reproduces.

### Did your test throw out a timeout?

- [ ] I have followed the instructions under [Identifying which synchronization mechanism causes us to wait too much](https://wix.github.io/Detox/docs/troubleshooting/synchronization#identifying-which-synchronization-mechanism-causes-us-to-wait-too-much).

### Help us reproduce this issue!

_No response_

### In what environment did this happen?

Detox version: 19.12.1
React Native version: N/A 
Node version: 16
Device model: N/A
Android version: N/A
Test-runner (select one): N/A

### Detox logs

<details><summary>Detox logs</summary>

```
paste logs here!
```

</details>

### Device logs

<details><summary>Device logs</summary>

```
paste logs here!
```

</details>

### More data, please!

_No response_


Discussion:
fixed by https://github.com/wix/Detox/pull/3614
Resolved in [Detox v19.12.4](https://github.com/wix/Detox/releases/tag/19.12.4), thanks to @paulrostorp!



Patch:
diff --git a/detox/src/devices/allocation/drivers/android/emulator/AVDValidator.js b/detox/src/devices/allocation/drivers/android/emulator/AVDValidator.js
index 95ad52d0f2..07d57f07e0 100644
--- a/detox/src/devices/allocation/drivers/android/emulator/AVDValidator.js
+++ b/detox/src/devices/allocation/drivers/android/emulator/AVDValidator.js
@@ -12,11 +12,11 @@ class AVDValidator {
     this._emulatorVersionResolver = emulatorVersionResolver;
   }
 
-  async validate(avdName) {
+  async validate(avdName, isHeadless) {
     const avds = await this._avdsResolver.resolve(avdName);
     this._assertAVDs(avds);
     await this._assertAVDMatch(avds, avdName);
-    await this._validateEmulatorVer();
+    await this._validateEmulatorVer(isHeadless);
   }
 
   _assertAVDs(avds) {
@@ -37,8 +37,8 @@ class AVDValidator {
     }
   }
 
-  async _validateEmulatorVer() {
-    const emulatorVersion = await this._emulatorVersionResolver.resolve();
+  async _validateEmulatorVer(isHeadless) {
+    const emulatorVersion = await this._emulatorVersionResolver.resolve(isHeadless);
     if (!emulatorVersion) {
       logger.warn({ event: 'AVD_VALIDATION' }, 'Emulator version detection failed (See previous logs)');
       return;
diff --git a/detox/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js b/detox/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js
index 74272f96e2..ce0bac2caf 100644
--- a/detox/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js
+++ b/detox/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js
@@ -31,7 +31,7 @@ class EmulatorAllocDriver extends AllocationDriverBase {
   async allocate(deviceConfig) {
     const avdName = deviceConfig.device.avdName;
 
-    await this._avdValidator.validate(avdName);
+    await this._avdValidator.validate(avdName, deviceConfig.headless);
     await this._fixAvdConfigIniSkinNameIfNeeded(avdName, deviceConfig.headless);
 
     const allocResult = await this._allocationHelper.allocateDevice(avdName);


Test patch:
diff --git a/detox/src/devices/allocation/drivers/android/emulator/AVDValidator.test.js b/detox/src/devices/allocation/drivers/android/emulator/AVDValidator.test.js
index 6f5c15ea12..127bce7d66 100644
--- a/detox/src/devices/allocation/drivers/android/emulator/AVDValidator.test.js
+++ b/detox/src/devices/allocation/drivers/android/emulator/AVDValidator.test.js
@@ -111,4 +111,13 @@ describe('AVD validator', () => {
       'Emulator version detection failed (See previous logs)'
       );
   });
+
+  it('should run emulator version resolver as headless if required', async () => {
+    givenExpectedAVD();
+    givenProperEmulatorVersion();
+
+    await uut.validate('mock-avd-name', true);
+
+    expect(versionResolver.resolve).toHaveBeenCalledWith(true);
+  });
 });
diff --git a/detox/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.test.js b/detox/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.test.js
index dd927f674d..d17ba5efd1 100644
--- a/detox/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.test.js
+++ b/detox/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.test.js
@@ -156,7 +156,13 @@ describe('Allocation driver for Google emulators', () => {
     it('should pre-validate proper AVD configuration', async () => {
       givenValidAVD();
       await allocDriver.allocate(deviceConfig);
-      expect(avdValidator.validate).toHaveBeenCalledWith(avdName);
+      expect(avdValidator.validate).toHaveBeenCalledWith(avdName, undefined);
+    });
+
+    it('should respect headless avd configuration during AVD validation', async () => {
+      givenValidAVD();
+      await allocDriver.allocate({ ...deviceConfig, headless: true });
+      expect(avdValidator.validate).toHaveBeenCalledWith(avdName, true);
     });
 
     it('should throw if AVD configuration is invalid', async () => {