@mentra/engine 3.2.1-dev.293 → 3.2.1-dev.294

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.
@@ -4239,8 +4239,8 @@ class LocalMiniappRuntime {
4239
4239
  const enabled = await acsMeetingService.isWifiEnabled()
4240
4240
  return enabled ?? true
4241
4241
  },
4242
- joinScopedNetwork: (ssid, passphrase, gateway) =>
4243
- acsMeetingService.joinScopedNetwork(ssid, passphrase, gateway),
4242
+ joinScopedNetwork: (ssid, passphrase, gateway, report) =>
4243
+ acsMeetingService.joinScopedNetwork(ssid, passphrase, gateway, report),
4244
4244
  leaveScopedNetwork: () => acsMeetingService.leaveScopedNetwork(),
4245
4245
  cancelScopedNetworkJoin: () => acsMeetingService.cancelScopedNetworkJoin(),
4246
4246
  probeGateway: async () => {
@@ -67,6 +67,8 @@ export class ManagedWebRtcRelay implements ManagedRelay {
67
67
  private attemptError: Error | null = null
68
68
  private hotspotTouched = false
69
69
  private nativeTouched = false
70
+ private preparing = false
71
+ private prepareStop: Promise<void> | null = null
70
72
  private glassesTouched = false
71
73
  private release: (() => void) | null = null
72
74
  private listener: {remove(): void} | null = null
@@ -101,6 +103,13 @@ export class ManagedWebRtcRelay implements ManagedRelay {
101
103
 
102
104
  cancel(): void {
103
105
  this.cancelled = true
106
+ if (this.preparing && this.attemptId && !this.prepareStop) {
107
+ // Local Network permission can wait indefinitely. Interrupt this owned prepare
108
+ // before the coordinator's transition lock can reach stop(). Native stop rejects
109
+ // prepare and resolves only after its peers and hotspot join have been released.
110
+ this.prepareStop = this.deps.native.stop(this.attemptId)
111
+ void this.prepareStop.catch(() => undefined) // stop() awaits and reports cleanup failure.
112
+ }
104
113
  }
105
114
 
106
115
  owns(streamId: string): boolean {
@@ -136,16 +145,22 @@ export class ManagedWebRtcRelay implements ManagedRelay {
136
145
  await this.deps.sleep(3_000) // Same beacon/DHCP startup allowance as ACS.
137
146
  this.checkpoint()
138
147
  this.nativeTouched = true
139
- const url = await this.deps.native.prepare({
140
- attemptId: this.attemptId,
141
- ingestUrl: this.options.ingestUrl,
142
- ssid: hotspot.ssid,
143
- password: hotspot.password,
144
- gatewayAddress: hotspot.localIp,
145
- captureAudio,
146
- audioTransport: lc3 ? "ble-lc3" : captureAudio ? "whip" : "none",
147
- bitrate: this.options.video?.bitrate ?? 2_000_000,
148
- })
148
+ this.preparing = true
149
+ let url: string
150
+ try {
151
+ url = await this.deps.native.prepare({
152
+ attemptId: this.attemptId,
153
+ ingestUrl: this.options.ingestUrl,
154
+ ssid: hotspot.ssid,
155
+ password: hotspot.password,
156
+ gatewayAddress: hotspot.localIp,
157
+ captureAudio,
158
+ audioTransport: lc3 ? "ble-lc3" : captureAudio ? "whip" : "none",
159
+ bitrate: this.options.video?.bitrate ?? 2_000_000,
160
+ })
161
+ } finally {
162
+ this.preparing = false
163
+ }
149
164
  this.checkpoint()
150
165
  if (lc3) {
151
166
  const id = this.attemptId
@@ -237,14 +252,15 @@ export class ManagedWebRtcRelay implements ManagedRelay {
237
252
  if (this.stopping) return this.stopping
238
253
  this.listener?.remove()
239
254
  this.listener = null
240
- this.stopping = this.operation
241
- .catch(() => undefined)
255
+ this.stopping = Promise.resolve(this.prepareStop)
256
+ .then(() => this.operation.catch(() => undefined))
242
257
  .then(async () => {
243
258
  await this.cleanupAttempt()
244
259
  this.release?.()
245
260
  this.release = null
246
261
  })
247
262
  .finally(() => {
263
+ this.prepareStop = null
248
264
  this.stopping = null
249
265
  })
250
266
  return this.stopping
@@ -276,7 +292,7 @@ export class ManagedWebRtcRelay implements ManagedRelay {
276
292
  })
277
293
  if (this.nativeTouched && id)
278
294
  await step(async () => {
279
- await this.deps.native.stop(id)
295
+ await (this.prepareStop ?? this.deps.native.stop(id))
280
296
  this.nativeTouched = false
281
297
  })
282
298
  if (this.hotspotTouched)
@@ -1149,7 +1149,7 @@ export function createSoftapCallDeps(args: {
1149
1149
  setHotspotState: (enabled: boolean) => Promise<{state: string; ssid?: string; password?: string; localIp?: string}>
1150
1150
  /** Whether this phone's Wi-Fi radio is on. Optional: only Android hosts can answer it. */
1151
1151
  isWifiEnabled?: () => Promise<boolean>
1152
- joinScopedNetwork: (ssid: string, passphrase: string, gateway?: string) => Promise<string | undefined>
1152
+ joinScopedNetwork: (ssid: string, passphrase: string, gateway?: string, report?: SoftapStepReporter) => Promise<string | undefined>
1153
1153
  leaveScopedNetwork: () => Promise<void>
1154
1154
  cancelScopedNetworkJoin?: () => Promise<void>
1155
1155
  joinMeeting: (
@@ -1275,8 +1275,8 @@ export function createSoftapCallDeps(args: {
1275
1275
  joinScopedNetwork: async (ssid, passphrase, report) => {
1276
1276
  const joinOnce = (nextSsid: string, nextPassphrase: string) =>
1277
1277
  gatewayAddress
1278
- ? subsystems.joinScopedNetwork(nextSsid, nextPassphrase, gatewayAddress)
1279
- : subsystems.joinScopedNetwork(nextSsid, nextPassphrase)
1278
+ ? subsystems.joinScopedNetwork(nextSsid, nextPassphrase, gatewayAddress, report)
1279
+ : subsystems.joinScopedNetwork(nextSsid, nextPassphrase, undefined, report)
1280
1280
  let address: string | undefined
1281
1281
  try {
1282
1282
  address = await joinOnce(ssid, passphrase)