@mentra/engine 0.1.0-dev.0 → 3.1.0-dev.4
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/README.md +55 -18
- package/build/bluetooth-sdk/debug.d.ts +2 -0
- package/build/bluetooth-sdk/debug.d.ts.map +1 -0
- package/build/bluetooth-sdk/debug.js +2 -0
- package/build/bluetooth-sdk/debug.js.map +1 -0
- package/build/bluetooth-sdk/index.d.ts +3 -0
- package/build/bluetooth-sdk/index.d.ts.map +1 -0
- package/build/bluetooth-sdk/index.js +3 -0
- package/build/bluetooth-sdk/index.js.map +1 -0
- package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
- package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
- package/build/bluetooth-sdk/photo-receiver.js +3 -0
- package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
- package/build/bluetooth-sdk/react.d.ts +2 -0
- package/build/bluetooth-sdk/react.d.ts.map +1 -0
- package/build/bluetooth-sdk/react.js +2 -0
- package/build/bluetooth-sdk/react.js.map +1 -0
- package/build/bluetooth-sdk/types.d.ts +2 -0
- package/build/bluetooth-sdk/types.d.ts.map +1 -0
- package/build/bluetooth-sdk/types.js +2 -0
- package/build/bluetooth-sdk/types.js.map +1 -0
- package/build/engine.d.ts +24 -16
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +9 -4
- package/build/engine.js.map +1 -1
- package/build/facades/dev.d.ts +3 -2
- package/build/facades/dev.d.ts.map +1 -1
- package/build/facades/dev.js +18 -12
- package/build/facades/dev.js.map +1 -1
- package/build/facades/display.d.ts +1 -1
- package/build/facades/display.d.ts.map +1 -1
- package/build/facades/display.js +1 -1
- package/build/facades/display.js.map +1 -1
- package/build/facades/gallery.js +1 -1
- package/build/facades/gallery.js.map +1 -1
- package/build/facades/glasses.d.ts +4 -13
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +21 -6
- package/build/facades/glasses.js.map +1 -1
- package/build/facades/glassesSettings.d.ts.map +1 -1
- package/build/facades/glassesSettings.js +1 -0
- package/build/facades/glassesSettings.js.map +1 -1
- package/build/facades/miniapps.d.ts +4 -0
- package/build/facades/miniapps.d.ts.map +1 -1
- package/build/facades/miniapps.js +5 -0
- package/build/facades/miniapps.js.map +1 -1
- package/build/facades/ota.d.ts +14 -16
- package/build/facades/ota.d.ts.map +1 -1
- package/build/facades/ota.js +22 -7
- package/build/facades/ota.js.map +1 -1
- package/build/facades/pairing.d.ts +8 -5
- package/build/facades/pairing.d.ts.map +1 -1
- package/build/facades/pairing.js +12 -10
- package/build/facades/pairing.js.map +1 -1
- package/build/facades/permissions.d.ts +10 -0
- package/build/facades/permissions.d.ts.map +1 -1
- package/build/facades/permissions.js +10 -0
- package/build/facades/permissions.js.map +1 -1
- package/build/facades/phoneNotifications.d.ts +0 -4
- package/build/facades/phoneNotifications.d.ts.map +1 -1
- package/build/facades/phoneNotifications.js +4 -14
- package/build/facades/phoneNotifications.js.map +1 -1
- package/build/facades/speech.d.ts +7 -6
- package/build/facades/speech.d.ts.map +1 -1
- package/build/facades/speech.js +1 -1
- package/build/facades/speech.js.map +1 -1
- package/build/generated/releaseMetadata.d.ts +12 -0
- package/build/generated/releaseMetadata.d.ts.map +1 -0
- package/build/generated/releaseMetadata.js +10 -0
- package/build/generated/releaseMetadata.js.map +1 -0
- package/build/index.d.ts +10 -8
- package/build/index.d.ts.map +1 -1
- package/build/index.js +6 -5
- package/build/index.js.map +1 -1
- package/build/react/MentraLiveOtaFlow.d.ts +38 -0
- package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
- package/build/react/MentraLiveOtaFlow.js +528 -0
- package/build/react/MentraLiveOtaFlow.js.map +1 -0
- package/build/react/index.d.ts +2 -0
- package/build/react/index.d.ts.map +1 -0
- package/build/react/index.js +2 -0
- package/build/react/index.js.map +1 -0
- package/build/react/useEngineSnapshot.d.ts +2 -0
- package/build/react/useEngineSnapshot.d.ts.map +1 -0
- package/build/react/useEngineSnapshot.js +14 -0
- package/build/react/useEngineSnapshot.js.map +1 -0
- package/build/runtime/bootstrap.d.ts +24 -1
- package/build/runtime/bootstrap.d.ts.map +1 -1
- package/build/runtime/bootstrap.js +17 -0
- package/build/runtime/bootstrap.js.map +1 -1
- package/build/runtime/scanQrSeam.d.ts +7 -0
- package/build/runtime/scanQrSeam.d.ts.map +1 -0
- package/build/runtime/scanQrSeam.js +16 -0
- package/build/runtime/scanQrSeam.js.map +1 -0
- package/build/services/AppRegistry.d.ts +41 -57
- package/build/services/AppRegistry.d.ts.map +1 -1
- package/build/services/AppRegistry.js +208 -144
- package/build/services/AppRegistry.js.map +1 -1
- package/build/services/AudioCloudUplink.d.ts +12 -0
- package/build/services/AudioCloudUplink.d.ts.map +1 -1
- package/build/services/AudioCloudUplink.js +22 -1
- package/build/services/AudioCloudUplink.js.map +1 -1
- package/build/services/AudioPlaybackService.d.ts +41 -2
- package/build/services/AudioPlaybackService.d.ts.map +1 -1
- package/build/services/AudioPlaybackService.js +250 -33
- package/build/services/AudioPlaybackService.js.map +1 -1
- package/build/services/BlobStore.d.ts +2 -1
- package/build/services/BlobStore.d.ts.map +1 -1
- package/build/services/BlobStore.js +17 -9
- package/build/services/BlobStore.js.map +1 -1
- package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -1
- package/build/services/CloudAudioSubscriptionSync.js +13 -1
- package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
- package/build/services/CloudClientService.d.ts +15 -0
- package/build/services/CloudClientService.d.ts.map +1 -1
- package/build/services/CloudClientService.js +93 -1
- package/build/services/CloudClientService.js.map +1 -1
- package/build/services/DeviceEventRouter.js +5 -5
- package/build/services/DeviceEventRouter.js.map +1 -1
- package/build/services/ForegroundLocationPermission.d.ts +13 -0
- package/build/services/ForegroundLocationPermission.d.ts.map +1 -0
- package/build/services/ForegroundLocationPermission.js +12 -0
- package/build/services/ForegroundLocationPermission.js.map +1 -0
- package/build/services/GlassesSettingsSync.d.ts.map +1 -1
- package/build/services/GlassesSettingsSync.js +9 -3
- package/build/services/GlassesSettingsSync.js.map +1 -1
- package/build/services/GlassesStatusProjection.d.ts +2 -1
- package/build/services/GlassesStatusProjection.d.ts.map +1 -1
- package/build/services/GlassesStatusProjection.js +15 -8
- package/build/services/GlassesStatusProjection.js.map +1 -1
- package/build/services/HotspotOtaTransport.d.ts +29 -0
- package/build/services/HotspotOtaTransport.d.ts.map +1 -0
- package/build/services/HotspotOtaTransport.js +146 -0
- package/build/services/HotspotOtaTransport.js.map +1 -0
- package/build/services/HotspotShutdown.d.ts +17 -0
- package/build/services/HotspotShutdown.d.ts.map +1 -0
- package/build/services/HotspotShutdown.js +29 -0
- package/build/services/HotspotShutdown.js.map +1 -0
- package/build/services/LocalDisplayManager.d.ts +15 -0
- package/build/services/LocalDisplayManager.d.ts.map +1 -1
- package/build/services/LocalDisplayManager.js +106 -20
- package/build/services/LocalDisplayManager.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +74 -2
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +785 -291
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/LocalMiniappStorage.d.ts +32 -0
- package/build/services/LocalMiniappStorage.d.ts.map +1 -0
- package/build/services/LocalMiniappStorage.js +66 -0
- package/build/services/LocalMiniappStorage.js.map +1 -0
- package/build/services/LocalMiniappUserIdentity.d.ts +20 -0
- package/build/services/LocalMiniappUserIdentity.d.ts.map +1 -0
- package/build/services/LocalMiniappUserIdentity.js +43 -0
- package/build/services/LocalMiniappUserIdentity.js.map +1 -0
- package/build/services/LocalSttFallbackCoordinator.d.ts +9 -6
- package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.js +18 -12
- package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
- package/build/services/MicStateCoordinator.d.ts +42 -1
- package/build/services/MicStateCoordinator.d.ts.map +1 -1
- package/build/services/MicStateCoordinator.js +141 -3
- package/build/services/MicStateCoordinator.js.map +1 -1
- package/build/services/MiniappLauncher.d.ts.map +1 -1
- package/build/services/MiniappLauncher.js +23 -3
- package/build/services/MiniappLauncher.js.map +1 -1
- package/build/services/MiniappLiveness.d.ts +12 -0
- package/build/services/MiniappLiveness.d.ts.map +1 -0
- package/build/services/MiniappLiveness.js +16 -0
- package/build/services/MiniappLiveness.js.map +1 -0
- package/build/services/NativeHttpResponse.d.ts +3 -0
- package/build/services/NativeHttpResponse.d.ts.map +1 -0
- package/build/services/NativeHttpResponse.js +6 -0
- package/build/services/NativeHttpResponse.js.map +1 -0
- package/build/services/OtaArtifactDownloader.d.ts +65 -0
- package/build/services/OtaArtifactDownloader.d.ts.map +1 -0
- package/build/services/OtaArtifactDownloader.js +226 -0
- package/build/services/OtaArtifactDownloader.js.map +1 -0
- package/build/services/OtaAutoChain.d.ts +34 -0
- package/build/services/OtaAutoChain.d.ts.map +1 -0
- package/build/services/OtaAutoChain.js +83 -0
- package/build/services/OtaAutoChain.js.map +1 -0
- package/build/services/OtaErrorMapping.d.ts +18 -0
- package/build/services/OtaErrorMapping.d.ts.map +1 -0
- package/build/services/OtaErrorMapping.js +63 -0
- package/build/services/OtaErrorMapping.js.map +1 -0
- package/build/services/OtaInstallCoordinator.d.ts +95 -15
- package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
- package/build/services/OtaInstallCoordinator.js +577 -130
- package/build/services/OtaInstallCoordinator.js.map +1 -1
- package/build/services/OtaService.d.ts.map +1 -1
- package/build/services/OtaService.js +8 -1
- package/build/services/OtaService.js.map +1 -1
- package/build/services/OtaUpdateCheckService.d.ts +39 -4
- package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
- package/build/services/OtaUpdateCheckService.js +138 -22
- package/build/services/OtaUpdateCheckService.js.map +1 -1
- package/build/services/PhoneCalendarHelpers.d.ts +32 -0
- package/build/services/PhoneCalendarHelpers.d.ts.map +1 -0
- package/build/services/PhoneCalendarHelpers.js +157 -0
- package/build/services/PhoneCalendarHelpers.js.map +1 -0
- package/build/services/PhoneCalendarService.d.ts +5 -0
- package/build/services/PhoneCalendarService.d.ts.map +1 -0
- package/build/services/PhoneCalendarService.js +45 -0
- package/build/services/PhoneCalendarService.js.map +1 -0
- package/build/services/PhoneCameraFovCoordinator.d.ts +30 -0
- package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -0
- package/build/services/PhoneCameraFovCoordinator.js +194 -0
- package/build/services/PhoneCameraFovCoordinator.js.map +1 -0
- package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
- package/build/services/PhoneNotificationsSync.js +12 -10
- package/build/services/PhoneNotificationsSync.js.map +1 -1
- package/build/services/PhonePhotoCoordinator.d.ts +26 -2
- package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
- package/build/services/PhonePhotoCoordinator.js +79 -9
- package/build/services/PhonePhotoCoordinator.js.map +1 -1
- package/build/services/PhoneStreamCoordinator.d.ts +8 -1
- package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
- package/build/services/PhoneStreamCoordinator.js +125 -13
- package/build/services/PhoneStreamCoordinator.js.map +1 -1
- package/build/services/PhoneVideoCoordinator.d.ts +2 -0
- package/build/services/PhoneVideoCoordinator.d.ts.map +1 -1
- package/build/services/PhoneVideoCoordinator.js +10 -0
- package/build/services/PhoneVideoCoordinator.js.map +1 -1
- package/build/services/SceneRenderer.d.ts.map +1 -1
- package/build/services/SceneRenderer.js +15 -0
- package/build/services/SceneRenderer.js.map +1 -1
- package/build/services/SentenceTtsPipeline.d.ts +31 -0
- package/build/services/SentenceTtsPipeline.d.ts.map +1 -0
- package/build/services/SentenceTtsPipeline.js +67 -0
- package/build/services/SentenceTtsPipeline.js.map +1 -0
- package/build/services/SupportProfileSync.d.ts +22 -0
- package/build/services/SupportProfileSync.d.ts.map +1 -0
- package/build/services/SupportProfileSync.js +213 -0
- package/build/services/SupportProfileSync.js.map +1 -0
- package/build/services/TranscriptionRouting.d.ts +12 -0
- package/build/services/TranscriptionRouting.d.ts.map +1 -0
- package/build/services/TranscriptionRouting.js +24 -0
- package/build/services/TranscriptionRouting.js.map +1 -0
- package/build/services/TtsTextSanitizer.d.ts +5 -0
- package/build/services/TtsTextSanitizer.d.ts.map +1 -0
- package/build/services/TtsTextSanitizer.js +61 -0
- package/build/services/TtsTextSanitizer.js.map +1 -0
- package/build/services/WifiAdbRequest.d.ts +17 -0
- package/build/services/WifiAdbRequest.d.ts.map +1 -0
- package/build/services/WifiAdbRequest.js +35 -0
- package/build/services/WifiAdbRequest.js.map +1 -0
- package/build/services/asg/asgCameraApi.d.ts +43 -0
- package/build/services/asg/asgCameraApi.d.ts.map +1 -1
- package/build/services/asg/asgCameraApi.js +509 -26
- package/build/services/asg/asgCameraApi.js.map +1 -1
- package/build/services/asg/cameraRollExportCoordinator.d.ts +60 -0
- package/build/services/asg/cameraRollExportCoordinator.d.ts.map +1 -0
- package/build/services/asg/cameraRollExportCoordinator.js +618 -0
- package/build/services/asg/cameraRollExportCoordinator.js.map +1 -0
- package/build/services/asg/cameraRollExportLedger.d.ts +44 -0
- package/build/services/asg/cameraRollExportLedger.d.ts.map +1 -0
- package/build/services/asg/cameraRollExportLedger.js +78 -0
- package/build/services/asg/cameraRollExportLedger.js.map +1 -0
- package/build/services/asg/galleryNotices.d.ts +1 -1
- package/build/services/asg/galleryNotices.d.ts.map +1 -1
- package/build/services/asg/galleryNotices.js.map +1 -1
- package/build/services/asg/galleryPathMigration.d.ts +3 -0
- package/build/services/asg/galleryPathMigration.d.ts.map +1 -0
- package/build/services/asg/galleryPathMigration.js +26 -0
- package/build/services/asg/galleryPathMigration.js.map +1 -0
- package/build/services/asg/gallerySettingsService.d.ts +1 -0
- package/build/services/asg/gallerySettingsService.d.ts.map +1 -1
- package/build/services/asg/gallerySettingsService.js +2 -0
- package/build/services/asg/gallerySettingsService.js.map +1 -1
- package/build/services/asg/gallerySyncService.d.ts.map +1 -1
- package/build/services/asg/gallerySyncService.js +162 -56
- package/build/services/asg/gallerySyncService.js.map +1 -1
- package/build/services/asg/galleryTransferLedger.d.ts +58 -0
- package/build/services/asg/galleryTransferLedger.d.ts.map +1 -0
- package/build/services/asg/galleryTransferLedger.js +225 -0
- package/build/services/asg/galleryTransferLedger.js.map +1 -0
- package/build/services/asg/localNetworkTransport.d.ts +15 -0
- package/build/services/asg/localNetworkTransport.d.ts.map +1 -0
- package/build/services/asg/localNetworkTransport.js +144 -0
- package/build/services/asg/localNetworkTransport.js.map +1 -0
- package/build/services/asg/localStorageService.d.ts +18 -0
- package/build/services/asg/localStorageService.d.ts.map +1 -1
- package/build/services/asg/localStorageService.js +168 -19
- package/build/services/asg/localStorageService.js.map +1 -1
- package/build/services/asg/mediaProcessingQueue.d.ts +10 -0
- package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -1
- package/build/services/asg/mediaProcessingQueue.js +193 -62
- package/build/services/asg/mediaProcessingQueue.js.map +1 -1
- package/build/services/audioPlaybackAssets.d.ts +8 -0
- package/build/services/audioPlaybackAssets.d.ts.map +1 -0
- package/build/services/audioPlaybackAssets.js +7 -0
- package/build/services/audioPlaybackAssets.js.map +1 -0
- package/build/services/gallerySyncClock.js +1 -1
- package/build/services/gallerySyncClock.js.map +1 -1
- package/build/services/glassesClockSync.d.ts.map +1 -1
- package/build/services/glassesClockSync.js +6 -2
- package/build/services/glassesClockSync.js.map +1 -1
- package/build/services/manifestActions.d.ts +7 -0
- package/build/services/manifestActions.d.ts.map +1 -0
- package/build/services/manifestActions.js +25 -0
- package/build/services/manifestActions.js.map +1 -0
- package/build/services/otaDisplayState.d.ts +23 -12
- package/build/services/otaDisplayState.d.ts.map +1 -1
- package/build/services/otaDisplayState.js +36 -14
- package/build/services/otaDisplayState.js.map +1 -1
- package/build/services/otaInstallPolicy.d.ts +16 -4
- package/build/services/otaInstallPolicy.d.ts.map +1 -1
- package/build/services/otaInstallPolicy.js +24 -3
- package/build/services/otaInstallPolicy.js.map +1 -1
- package/build/services/otaLegacyMapping.d.ts +1 -1
- package/build/services/otaLegacyMapping.d.ts.map +1 -1
- package/build/services/otaLegacyMapping.js.map +1 -1
- package/build/services/otaManifestPolicy.d.ts +14 -0
- package/build/services/otaManifestPolicy.d.ts.map +1 -0
- package/build/services/otaManifestPolicy.js +19 -0
- package/build/services/otaManifestPolicy.js.map +1 -0
- package/build/services/otaManifestUrl.d.ts +3 -0
- package/build/services/otaManifestUrl.d.ts.map +1 -0
- package/build/services/otaManifestUrl.js +38 -0
- package/build/services/otaManifestUrl.js.map +1 -0
- package/build/services/slimStreamStatus.d.ts +11 -0
- package/build/services/slimStreamStatus.d.ts.map +1 -1
- package/build/services/slimStreamStatus.js +14 -4
- package/build/services/slimStreamStatus.js.map +1 -1
- package/build/stores/apps.d.ts.map +1 -1
- package/build/stores/apps.js +11 -0
- package/build/stores/apps.js.map +1 -1
- package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
- package/build/stores/bluetoothSettingKeys.js +2 -0
- package/build/stores/bluetoothSettingKeys.js.map +1 -1
- package/build/stores/gallerySync.d.ts +2 -0
- package/build/stores/gallerySync.d.ts.map +1 -1
- package/build/stores/gallerySync.js +2 -0
- package/build/stores/gallerySync.js.map +1 -1
- package/build/stores/glasses.d.ts.map +1 -1
- package/build/stores/glasses.js +3 -0
- package/build/stores/glasses.js.map +1 -1
- package/build/stores/settings.d.ts +17 -0
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +157 -17
- package/build/stores/settings.js.map +1 -1
- package/build/types/applet.d.ts +2 -0
- package/build/types/applet.d.ts.map +1 -1
- package/build/types/applet.js.map +1 -1
- package/build/types/asg.d.ts +7 -0
- package/build/types/asg.d.ts.map +1 -1
- package/build/types/asg.js.map +1 -1
- package/build/types/enums.d.ts +2 -25
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +2 -27
- package/build/types/enums.js.map +1 -1
- package/build/types/hardware.d.ts +4 -13
- package/build/types/hardware.d.ts.map +1 -1
- package/build/types/hardware.js +15 -3
- package/build/types/hardware.js.map +1 -1
- package/build/types/index.d.ts +2 -6
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js +2 -6
- package/build/types/index.js.map +1 -1
- package/build/utils/configuredDevHost.d.ts +6 -0
- package/build/utils/configuredDevHost.d.ts.map +1 -0
- package/build/utils/configuredDevHost.js +19 -0
- package/build/utils/configuredDevHost.js.map +1 -0
- package/build/utils/devMiniappLaunch.d.ts +19 -8
- package/build/utils/devMiniappLaunch.d.ts.map +1 -1
- package/build/utils/devMiniappLaunch.js +144 -21
- package/build/utils/devMiniappLaunch.js.map +1 -1
- package/build/utils/diagnosticContext.d.ts.map +1 -1
- package/build/utils/diagnosticContext.js +15 -17
- package/build/utils/diagnosticContext.js.map +1 -1
- package/build/utils/hardware/hardware.d.ts.map +1 -1
- package/build/utils/hardware/hardware.js +7 -3
- package/build/utils/hardware/hardware.js.map +1 -1
- package/build/utils/miniappDiagnostics.d.ts +64 -0
- package/build/utils/miniappDiagnostics.d.ts.map +1 -0
- package/build/utils/miniappDiagnostics.js +173 -0
- package/build/utils/miniappDiagnostics.js.map +1 -0
- package/build/utils/permissions/MediaLibraryPermissions.d.ts +11 -0
- package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -1
- package/build/utils/permissions/MediaLibraryPermissions.js +27 -4
- package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -1
- package/build/utils/timers/timers.d.ts.map +1 -1
- package/build/utils/timers/timers.js +55 -18
- package/build/utils/timers/timers.js.map +1 -1
- package/package.json +59 -31
- package/src/assets/silence.wav +0 -0
- package/src/bluetooth-sdk/debug.ts +1 -0
- package/src/bluetooth-sdk/index.ts +2 -0
- package/src/bluetooth-sdk/photo-receiver.ts +2 -0
- package/src/bluetooth-sdk/react.ts +1 -0
- package/src/bluetooth-sdk/types.ts +1 -0
- package/src/engine.ts +9 -4
- package/src/facades/dev.ts +17 -12
- package/src/facades/display.ts +1 -1
- package/src/facades/gallery.ts +1 -1
- package/src/facades/glasses.ts +20 -7
- package/src/facades/glassesSettings.ts +5 -0
- package/src/facades/miniapps.ts +7 -0
- package/src/facades/ota.ts +23 -8
- package/src/facades/pairing.ts +15 -11
- package/src/facades/permissions.ts +14 -0
- package/src/facades/phoneNotifications.ts +4 -13
- package/src/facades/speech.ts +21 -7
- package/src/generated/releaseMetadata.ts +20 -0
- package/src/index.ts +39 -13
- package/src/react/MentraLiveOtaFlow.tsx +856 -0
- package/src/react/index.ts +7 -0
- package/src/react/useEngineSnapshot.ts +16 -0
- package/src/runtime/bootstrap.ts +33 -1
- package/src/runtime/scanQrSeam.ts +20 -0
- package/src/services/AppRegistry.ts +240 -149
- package/src/services/AudioCloudUplink.ts +23 -1
- package/src/services/AudioPlaybackService.ts +287 -38
- package/src/services/BlobStore.ts +22 -9
- package/src/services/CloudAudioSubscriptionSync.ts +13 -1
- package/src/services/CloudClientService.ts +96 -1
- package/src/services/DeviceEventRouter.ts +5 -5
- package/src/services/ForegroundLocationPermission.ts +24 -0
- package/src/services/GlassesSettingsSync.ts +9 -3
- package/src/services/GlassesStatusProjection.ts +16 -8
- package/src/services/HotspotOtaTransport.ts +184 -0
- package/src/services/HotspotShutdown.ts +41 -0
- package/src/services/LocalDisplayManager.ts +112 -21
- package/src/services/LocalMiniappRuntime.ts +967 -346
- package/src/services/LocalMiniappStorage.ts +82 -0
- package/src/services/LocalMiniappUserIdentity.ts +46 -0
- package/src/services/LocalSttFallbackCoordinator.ts +19 -12
- package/src/services/MicStateCoordinator.ts +169 -4
- package/src/services/MiniappLauncher.ts +30 -3
- package/src/services/MiniappLiveness.ts +24 -0
- package/src/services/NativeHttpResponse.ts +6 -0
- package/src/services/OtaArtifactDownloader.ts +312 -0
- package/src/services/OtaAutoChain.ts +106 -0
- package/src/services/OtaErrorMapping.ts +80 -0
- package/src/services/OtaInstallCoordinator.ts +649 -144
- package/src/services/OtaService.ts +11 -5
- package/src/services/OtaUpdateCheckService.ts +181 -21
- package/src/services/PhoneCalendarHelpers.ts +212 -0
- package/src/services/PhoneCalendarService.ts +65 -0
- package/src/services/PhoneCameraFovCoordinator.ts +210 -0
- package/src/services/PhoneNotificationsSync.ts +12 -10
- package/src/services/PhonePhotoCoordinator.ts +116 -18
- package/src/services/PhoneStreamCoordinator.ts +139 -25
- package/src/services/PhoneVideoCoordinator.ts +11 -0
- package/src/services/SceneRenderer.ts +16 -0
- package/src/services/SentenceTtsPipeline.ts +106 -0
- package/src/services/SupportProfileSync.ts +218 -0
- package/src/services/TranscriptionRouting.ts +37 -0
- package/src/services/TtsTextSanitizer.ts +66 -0
- package/src/services/WifiAdbRequest.ts +53 -0
- package/src/services/asg/asgCameraApi.ts +615 -33
- package/src/services/asg/cameraRollExportCoordinator.ts +627 -0
- package/src/services/asg/cameraRollExportLedger.ts +122 -0
- package/src/services/asg/galleryNotices.ts +1 -0
- package/src/services/asg/galleryPathMigration.ts +22 -0
- package/src/services/asg/gallerySettingsService.ts +3 -0
- package/src/services/asg/gallerySyncService.ts +184 -73
- package/src/services/asg/galleryTransferLedger.ts +312 -0
- package/src/services/asg/localNetworkTransport.ts +169 -0
- package/src/services/asg/localStorageService.ts +179 -24
- package/src/services/asg/mediaProcessingQueue.ts +209 -62
- package/src/services/audioPlaybackAssets.ts +8 -0
- package/src/services/gallerySyncClock.ts +1 -1
- package/src/services/glassesClockSync.ts +6 -2
- package/src/services/manifestActions.ts +30 -0
- package/src/services/otaDisplayState.ts +58 -17
- package/src/services/otaInstallPolicy.ts +30 -4
- package/src/services/otaLegacyMapping.ts +1 -1
- package/src/services/otaManifestPolicy.ts +42 -0
- package/src/services/otaManifestUrl.ts +44 -0
- package/src/services/slimStreamStatus.ts +16 -5
- package/src/stores/apps.ts +12 -0
- package/src/stores/bluetoothSettingKeys.ts +2 -0
- package/src/stores/gallerySync.ts +4 -0
- package/src/stores/glasses.ts +3 -0
- package/src/stores/settings.ts +179 -18
- package/src/types/applet.ts +2 -0
- package/src/types/asg.ts +7 -0
- package/src/types/enums.ts +3 -28
- package/src/types/hardware.ts +20 -13
- package/src/types/index.ts +2 -6
- package/src/utils/configuredDevHost.ts +17 -0
- package/src/utils/devMiniappLaunch.ts +151 -23
- package/src/utils/diagnosticContext.ts +17 -17
- package/src/utils/hardware/hardware.ts +7 -9
- package/src/utils/miniappDiagnostics.ts +226 -0
- package/src/utils/permissions/MediaLibraryPermissions.ts +35 -4
- package/src/utils/timers/timers.ts +57 -21
- package/build/devtools.d.ts +0 -11
- package/build/devtools.d.ts.map +0 -1
- package/build/devtools.js +0 -13
- package/build/devtools.js.map +0 -1
- package/build/internal.d.ts +0 -66
- package/build/internal.d.ts.map +0 -1
- package/build/internal.js +0 -89
- package/build/internal.js.map +0 -1
- package/build/services/asgOtaVersionUrl.d.ts +0 -2
- package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
- package/build/services/asgOtaVersionUrl.js +0 -36
- package/build/services/asgOtaVersionUrl.js.map +0 -1
- package/src/devtools.ts +0 -13
- package/src/internal.ts +0 -158
- package/src/services/asgOtaVersionUrl.ts +0 -41
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import * as RNFS from "@dr.pogodin/react-native-fs"
|
|
2
|
+
import type {OtaCheckCurrentGlassesResult, VersionJson} from "./OtaUpdateCheckService"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Phone-side artifact staging for hotspot-served OTA (OS-1676).
|
|
6
|
+
*
|
|
7
|
+
* When the glasses have no WiFi, the phone downloads the OTA artifacts itself (over
|
|
8
|
+
* whatever network it is on — the user's tap on "update" is the consent) and serves them
|
|
9
|
+
* to the glasses via the LocalOtaServer over the glasses' hotspot. This module owns:
|
|
10
|
+
*
|
|
11
|
+
* - planning which artifacts the pending update actually needs (from the raw manifest the
|
|
12
|
+
* update check fetched, so the glasses re-parse byte-identical version data),
|
|
13
|
+
* - downloading them with .part staging and sha256 verification, keyed on disk by hash so
|
|
14
|
+
* retries and the post-APK continuation reuse verified files,
|
|
15
|
+
* - rewriting the manifest's URL fields to point at the phone server, and
|
|
16
|
+
* - cleanup once the update completes or the manifest moves on.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export type OtaArtifactKind = "apk" | "mtk" | "bes"
|
|
20
|
+
|
|
21
|
+
export interface OtaArtifactPlanEntry {
|
|
22
|
+
kind: OtaArtifactKind
|
|
23
|
+
/** URL this artifact is fetched from, exactly as it appears in the raw manifest. */
|
|
24
|
+
url: string
|
|
25
|
+
/** Required content hash from the manifest. */
|
|
26
|
+
sha256: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface PreparedOtaArtifact extends OtaArtifactPlanEntry {
|
|
30
|
+
filePath: string
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface OtaArtifactDownloadProgress {
|
|
34
|
+
kind: OtaArtifactKind
|
|
35
|
+
/** 0-based index of the artifact being downloaded. */
|
|
36
|
+
index: number
|
|
37
|
+
totalCount: number
|
|
38
|
+
/** Percent of the current artifact, 0-100 (0 when the server sent no length). */
|
|
39
|
+
artifactPercent: number
|
|
40
|
+
bytesWritten: number
|
|
41
|
+
contentLength: number
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class OtaArtifactError extends Error {
|
|
45
|
+
constructor(
|
|
46
|
+
public readonly code: "artifact_download_failed" | "artifact_verify_failed" | "manifest_invalid",
|
|
47
|
+
message: string,
|
|
48
|
+
) {
|
|
49
|
+
super(message)
|
|
50
|
+
this.name = "OtaArtifactError"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const ASG_PACKAGE = "com.mentra.asg_client"
|
|
55
|
+
|
|
56
|
+
export function otaArtifactsDirectory(): string {
|
|
57
|
+
return `${RNFS.DocumentDirectoryPath}/ota_artifacts`
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Derive the artifact list the pending update needs from a completed check.
|
|
62
|
+
* Works off the raw manifest body (not the normalized check fields) so the URLs and
|
|
63
|
+
* hashes match exactly what the glasses will re-parse.
|
|
64
|
+
*/
|
|
65
|
+
export function planArtifacts(result: OtaCheckCurrentGlassesResult): OtaArtifactPlanEntry[] {
|
|
66
|
+
if (!result.manifestBody) {
|
|
67
|
+
throw new OtaArtifactError("manifest_invalid", "Check result carries no manifest body")
|
|
68
|
+
}
|
|
69
|
+
let manifest: VersionJson
|
|
70
|
+
try {
|
|
71
|
+
manifest = JSON.parse(result.manifestBody)
|
|
72
|
+
} catch {
|
|
73
|
+
throw new OtaArtifactError("manifest_invalid", "Manifest body is not valid JSON")
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const entries: OtaArtifactPlanEntry[] = []
|
|
77
|
+
|
|
78
|
+
if (result.updates.includes("apk")) {
|
|
79
|
+
const app = manifest.apps?.[ASG_PACKAGE] as unknown as Record<string, unknown> | undefined
|
|
80
|
+
const url = typeof app?.apkUrl === "string" ? app.apkUrl : null
|
|
81
|
+
if (!url) {
|
|
82
|
+
throw new OtaArtifactError("manifest_invalid", "Manifest has no apkUrl for the pending APK update")
|
|
83
|
+
}
|
|
84
|
+
entries.push({
|
|
85
|
+
kind: "apk",
|
|
86
|
+
url,
|
|
87
|
+
sha256: requireSha256(app, "APK"),
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (result.updates.includes("mtk") && result.mtkPatch) {
|
|
92
|
+
const raw = (manifest.mtk_patches ?? []).find(
|
|
93
|
+
(patch) => firmwareUrl(patch) === firmwareUrl(result.mtkPatch!),
|
|
94
|
+
) as unknown as Record<string, unknown> | undefined
|
|
95
|
+
const url = firmwareUrl(raw) ?? firmwareUrl(result.mtkPatch)
|
|
96
|
+
if (!url) {
|
|
97
|
+
throw new OtaArtifactError("manifest_invalid", "Manifest has no URL for the pending MTK patch")
|
|
98
|
+
}
|
|
99
|
+
entries.push({
|
|
100
|
+
kind: "mtk",
|
|
101
|
+
url,
|
|
102
|
+
sha256: requireSha256(raw, "MTK"),
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (result.updates.includes("bes") && manifest.bes_firmware) {
|
|
107
|
+
const raw = manifest.bes_firmware as unknown as Record<string, unknown>
|
|
108
|
+
const url = firmwareUrl(raw)
|
|
109
|
+
if (!url) {
|
|
110
|
+
throw new OtaArtifactError("manifest_invalid", "Manifest has no URL for the pending BES firmware")
|
|
111
|
+
}
|
|
112
|
+
entries.push({
|
|
113
|
+
kind: "bes",
|
|
114
|
+
url,
|
|
115
|
+
sha256: requireSha256(raw, "BES"),
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return entries
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Download every planned artifact into the on-disk hash-keyed store, reusing files that
|
|
124
|
+
* already verify. Sequential on purpose: progress is legible and the hotspot window that
|
|
125
|
+
* follows is the slow part, not phone-side parallelism.
|
|
126
|
+
*/
|
|
127
|
+
export async function prepareArtifacts(
|
|
128
|
+
plan: OtaArtifactPlanEntry[],
|
|
129
|
+
onProgress?: (progress: OtaArtifactDownloadProgress) => void,
|
|
130
|
+
nativeDownload?: (
|
|
131
|
+
entry: OtaArtifactPlanEntry,
|
|
132
|
+
destination: string,
|
|
133
|
+
onProgress?: (bytesWritten: number, contentLength: number) => void,
|
|
134
|
+
) => Promise<{statusCode: number}>,
|
|
135
|
+
): Promise<PreparedOtaArtifact[]> {
|
|
136
|
+
const directory = otaArtifactsDirectory()
|
|
137
|
+
await RNFS.mkdir(directory, {NSURLIsExcludedFromBackupKey: true})
|
|
138
|
+
|
|
139
|
+
const prepared: PreparedOtaArtifact[] = []
|
|
140
|
+
for (let index = 0; index < plan.length; index++) {
|
|
141
|
+
const entry = plan[index]
|
|
142
|
+
|
|
143
|
+
const cachedPath = `${directory}/${entry.sha256}`
|
|
144
|
+
if (await RNFS.exists(cachedPath)) {
|
|
145
|
+
const cachedHash = (await RNFS.hash(cachedPath, "sha256")).toLowerCase()
|
|
146
|
+
if (cachedHash === entry.sha256) {
|
|
147
|
+
prepared.push({...entry, filePath: cachedPath})
|
|
148
|
+
continue
|
|
149
|
+
}
|
|
150
|
+
await safeUnlink(cachedPath)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const partPath = `${directory}/download-${index}.part`
|
|
154
|
+
await safeUnlink(partPath)
|
|
155
|
+
try {
|
|
156
|
+
const reportProgress = (bytesWritten: number, contentLength: number) => {
|
|
157
|
+
onProgress?.({
|
|
158
|
+
kind: entry.kind,
|
|
159
|
+
index,
|
|
160
|
+
totalCount: plan.length,
|
|
161
|
+
artifactPercent: contentLength > 0 ? Math.round((bytesWritten / contentLength) * 100) : 0,
|
|
162
|
+
bytesWritten,
|
|
163
|
+
contentLength,
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
const downloadResult = nativeDownload
|
|
167
|
+
? await nativeDownload(entry, partPath, reportProgress)
|
|
168
|
+
: await RNFS.downloadFile({
|
|
169
|
+
fromUrl: entry.url,
|
|
170
|
+
toFile: partPath,
|
|
171
|
+
connectionTimeout: 30_000,
|
|
172
|
+
readTimeout: 30_000,
|
|
173
|
+
progressDivider: 5,
|
|
174
|
+
progress: (res: RNFS.DownloadProgressCallbackResultT) => {
|
|
175
|
+
reportProgress(res.bytesWritten, res.contentLength)
|
|
176
|
+
},
|
|
177
|
+
}).promise
|
|
178
|
+
if (downloadResult.statusCode !== 200) {
|
|
179
|
+
throw new OtaArtifactError(
|
|
180
|
+
"artifact_download_failed",
|
|
181
|
+
`Download of ${entry.kind} artifact failed with HTTP ${downloadResult.statusCode}`,
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const actualSha256 = (await RNFS.hash(partPath, "sha256")).toLowerCase()
|
|
186
|
+
if (actualSha256 !== entry.sha256) {
|
|
187
|
+
throw new OtaArtifactError(
|
|
188
|
+
"artifact_verify_failed",
|
|
189
|
+
`${entry.kind} artifact hash mismatch: expected ${entry.sha256}, got ${actualSha256}`,
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const finalPath = `${directory}/${entry.sha256}`
|
|
194
|
+
await safeUnlink(finalPath)
|
|
195
|
+
await RNFS.moveFile(partPath, finalPath)
|
|
196
|
+
prepared.push({...entry, filePath: finalPath})
|
|
197
|
+
} catch (error) {
|
|
198
|
+
await safeUnlink(partPath)
|
|
199
|
+
if (error instanceof OtaArtifactError) {
|
|
200
|
+
throw error
|
|
201
|
+
}
|
|
202
|
+
throw new OtaArtifactError(
|
|
203
|
+
"artifact_download_failed",
|
|
204
|
+
`Download of ${entry.kind} artifact failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return prepared
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Point the manifest's artifact URLs at the phone server, leaving every other field
|
|
213
|
+
* semantically identical to what the update check saw. Entries we host get
|
|
214
|
+
* `<baseUrl>/artifacts/<sha256>`; entries the update does not need keep their CDN URLs.
|
|
215
|
+
* Only URL fields change: target versions, sizes, and manifest hashes remain untouched.
|
|
216
|
+
*/
|
|
217
|
+
export function rewriteManifestForLocalServer(
|
|
218
|
+
manifestBody: string,
|
|
219
|
+
artifacts: PreparedOtaArtifact[],
|
|
220
|
+
baseUrl: string,
|
|
221
|
+
): string {
|
|
222
|
+
let manifest: VersionJson
|
|
223
|
+
try {
|
|
224
|
+
manifest = JSON.parse(manifestBody)
|
|
225
|
+
} catch {
|
|
226
|
+
throw new OtaArtifactError("manifest_invalid", "Manifest body is not valid JSON")
|
|
227
|
+
}
|
|
228
|
+
const byUrl = new Map(artifacts.map((artifact) => [artifact.url, artifact]))
|
|
229
|
+
const localUrl = (artifact: PreparedOtaArtifact) => `${baseUrl}/artifacts/${artifact.sha256}`
|
|
230
|
+
|
|
231
|
+
for (const app of Object.values(manifest.apps ?? {})) {
|
|
232
|
+
const record = app as unknown as Record<string, unknown>
|
|
233
|
+
const artifact = typeof record.apkUrl === "string" ? byUrl.get(record.apkUrl) : undefined
|
|
234
|
+
if (artifact) {
|
|
235
|
+
record.apkUrl = localUrl(artifact)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
for (const patch of manifest.mtk_patches ?? []) {
|
|
240
|
+
rewriteFirmwareEntry(patch as unknown as Record<string, unknown>, byUrl, localUrl)
|
|
241
|
+
}
|
|
242
|
+
if (manifest.bes_firmware) {
|
|
243
|
+
rewriteFirmwareEntry(manifest.bes_firmware as unknown as Record<string, unknown>, byUrl, localUrl)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return JSON.stringify(manifest)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Delete every stored artifact whose hash is not in `keepSha256s` (plus stray .part files). */
|
|
250
|
+
export async function cleanupArtifacts(keepSha256s: string[] = []): Promise<void> {
|
|
251
|
+
const directory = otaArtifactsDirectory()
|
|
252
|
+
if (!(await RNFS.exists(directory))) {
|
|
253
|
+
return
|
|
254
|
+
}
|
|
255
|
+
const keep = new Set(keepSha256s.map((sha) => sha.toLowerCase()))
|
|
256
|
+
const items = await RNFS.readDir(directory)
|
|
257
|
+
for (const item of items) {
|
|
258
|
+
if (!item.isFile()) continue
|
|
259
|
+
if (keep.has(item.name.toLowerCase())) continue
|
|
260
|
+
await safeUnlink(item.path)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function rewriteFirmwareEntry(
|
|
265
|
+
entry: Record<string, unknown>,
|
|
266
|
+
byUrl: Map<string, PreparedOtaArtifact>,
|
|
267
|
+
localUrl: (artifact: PreparedOtaArtifact) => string,
|
|
268
|
+
): void {
|
|
269
|
+
const url = firmwareUrl(entry)
|
|
270
|
+
const artifact = url ? byUrl.get(url) : undefined
|
|
271
|
+
if (!artifact) {
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
entry.url = localUrl(artifact)
|
|
275
|
+
// Overwrite the legacy key too when present, so no glasses build can prefer a stale
|
|
276
|
+
// CDN URL over the local one.
|
|
277
|
+
if (typeof entry.firmwareUrl === "string") {
|
|
278
|
+
entry.firmwareUrl = localUrl(artifact)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function firmwareUrl(entry: unknown): string | null {
|
|
283
|
+
if (!entry || typeof entry !== "object") {
|
|
284
|
+
return null
|
|
285
|
+
}
|
|
286
|
+
const record = entry as Record<string, unknown>
|
|
287
|
+
if (typeof record.url === "string" && record.url.length > 0) {
|
|
288
|
+
return record.url
|
|
289
|
+
}
|
|
290
|
+
if (typeof record.firmwareUrl === "string" && record.firmwareUrl.length > 0) {
|
|
291
|
+
return record.firmwareUrl
|
|
292
|
+
}
|
|
293
|
+
return null
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function requireSha256(entry: Record<string, unknown> | undefined, label: string): string {
|
|
297
|
+
const sha256 = typeof entry?.sha256 === "string" ? entry.sha256.trim().toLowerCase() : ""
|
|
298
|
+
if (!/^[a-f0-9]{64}$/.test(sha256)) {
|
|
299
|
+
throw new OtaArtifactError("manifest_invalid", `${label} artifact has no valid manifest sha256`)
|
|
300
|
+
}
|
|
301
|
+
return sha256
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
async function safeUnlink(path: string): Promise<void> {
|
|
305
|
+
try {
|
|
306
|
+
if (await RNFS.exists(path)) {
|
|
307
|
+
await RNFS.unlink(path)
|
|
308
|
+
}
|
|
309
|
+
} catch {
|
|
310
|
+
// Best-effort: a leftover file only wastes space and is cleaned up next run.
|
|
311
|
+
}
|
|
312
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type {OtaCheckCurrentGlassesResult} from "./OtaUpdateCheckService"
|
|
2
|
+
|
|
3
|
+
export const MAX_OTA_AUTO_CHAIN_PASSES = 8
|
|
4
|
+
export const OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS = 120_000
|
|
5
|
+
|
|
6
|
+
type OtaAutoChainSession = {
|
|
7
|
+
approvedDowngrade: boolean
|
|
8
|
+
passCount: number
|
|
9
|
+
reconnectDeadline: number | null
|
|
10
|
+
seenFingerprints: Set<string>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type OtaAutoChainAdvanceResult =
|
|
14
|
+
| {advance: true; passCount: number}
|
|
15
|
+
| {advance: false; reason: "inactive" | "duplicate" | "max_passes" | "downgrade_not_approved"}
|
|
16
|
+
|
|
17
|
+
let session: OtaAutoChainSession | null = null
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Identify the exact update offer that produced one OTA pass. Including the
|
|
21
|
+
* observed versions and manifest body lets a changed manifest advance while a
|
|
22
|
+
* stale post-install version_info response is rejected as a duplicate.
|
|
23
|
+
*/
|
|
24
|
+
export function otaAutoChainFingerprint(result: OtaCheckCurrentGlassesResult): string {
|
|
25
|
+
return JSON.stringify({
|
|
26
|
+
manifestUrl: result.manifestUrl ?? "",
|
|
27
|
+
manifestBody: result.manifestBody ?? "",
|
|
28
|
+
buildNumber: result.buildNumber ?? "",
|
|
29
|
+
mtkFirmwareVersion: result.mtkFirmwareVersion ?? "",
|
|
30
|
+
besFirmwareVersion: result.besFirmwareVersion ?? "",
|
|
31
|
+
updates: result.updates,
|
|
32
|
+
targetBuildNumber: result.updateInfo?.versionCode ?? result.latestVersionInfo?.versionCode ?? 0,
|
|
33
|
+
targetBesVersion: result.besVersion ?? "",
|
|
34
|
+
mtkPatch: result.mtkPatch
|
|
35
|
+
? {
|
|
36
|
+
startFirmware: result.mtkPatch.start_firmware,
|
|
37
|
+
endFirmware: result.mtkPatch.end_firmware,
|
|
38
|
+
url: result.mtkPatch.url,
|
|
39
|
+
}
|
|
40
|
+
: null,
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Start a chain after the user explicitly approves its first update pass. */
|
|
45
|
+
export function beginOtaAutoChain(initialFingerprint: string, approvedDowngrade: boolean): void {
|
|
46
|
+
session = {
|
|
47
|
+
approvedDowngrade,
|
|
48
|
+
passCount: 1,
|
|
49
|
+
reconnectDeadline: null,
|
|
50
|
+
seenFingerprints: new Set([initialFingerprint]),
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function isOtaAutoChainActive(): boolean {
|
|
55
|
+
return session !== null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** End the current chain. Safe to call when no chain is active. */
|
|
59
|
+
export function stopOtaAutoChain(): void {
|
|
60
|
+
session = null
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Start (or continue) the bounded wait for glasses that are rebooting between
|
|
65
|
+
* passes. Re-renders must not extend the original deadline indefinitely.
|
|
66
|
+
*/
|
|
67
|
+
export function otaAutoChainReconnectWaitRemaining(now = performance.now()): number | null {
|
|
68
|
+
if (!session) return null
|
|
69
|
+
|
|
70
|
+
session.reconnectDeadline ??= now + OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS
|
|
71
|
+
return Math.max(0, session.reconnectDeadline - now)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** A successful reconnect allows a future pass to establish a fresh wait. */
|
|
75
|
+
export function clearOtaAutoChainReconnectWait(): void {
|
|
76
|
+
if (session) session.reconnectDeadline = null
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Admit the next pass of an active chain. Repeated offers, unexpectedly
|
|
81
|
+
* destructive downgrades, and runaway chains fail closed and end automation.
|
|
82
|
+
*/
|
|
83
|
+
export function tryAdvanceOtaAutoChain(fingerprint: string, isDowngrade: boolean): OtaAutoChainAdvanceResult {
|
|
84
|
+
if (!session) {
|
|
85
|
+
return {advance: false, reason: "inactive"}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (isDowngrade && !session.approvedDowngrade) {
|
|
89
|
+
stopOtaAutoChain()
|
|
90
|
+
return {advance: false, reason: "downgrade_not_approved"}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (session.seenFingerprints.has(fingerprint)) {
|
|
94
|
+
stopOtaAutoChain()
|
|
95
|
+
return {advance: false, reason: "duplicate"}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (session.passCount >= MAX_OTA_AUTO_CHAIN_PASSES) {
|
|
99
|
+
stopOtaAutoChain()
|
|
100
|
+
return {advance: false, reason: "max_passes"}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
session.seenFingerprints.add(fingerprint)
|
|
104
|
+
session.passCount += 1
|
|
105
|
+
return {advance: true, passCount: session.passCount}
|
|
106
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type {OtaProgress, OtaStatus} from "../facades/ota"
|
|
2
|
+
|
|
3
|
+
export const BES_INSTALL_RESTART_MESSAGE =
|
|
4
|
+
"Restart your glasses to safely exit firmware update mode before trying again"
|
|
5
|
+
|
|
6
|
+
function isDownloadPhaseSnapshot(
|
|
7
|
+
otaStatus: OtaStatus | null | undefined,
|
|
8
|
+
otaProgress: OtaProgress | null | undefined,
|
|
9
|
+
): boolean {
|
|
10
|
+
if (otaStatus?.phase === "download") {
|
|
11
|
+
return true
|
|
12
|
+
}
|
|
13
|
+
if (otaProgress?.stage === "download") {
|
|
14
|
+
return true
|
|
15
|
+
}
|
|
16
|
+
return false
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Offer Change WiFi whenever the OTA flow failed while the glasses were in the
|
|
21
|
+
* download step (any download failure — network, SSL, size cap, verify, etc.).
|
|
22
|
+
*
|
|
23
|
+
* Also covers phone-side watchdog failures that fire while the store still shows
|
|
24
|
+
* an active download phase (stall / global timeout mid-download).
|
|
25
|
+
*/
|
|
26
|
+
export function shouldShowChangeWifiForOtaDownloadFailure(
|
|
27
|
+
otaStatus: OtaStatus | null | undefined,
|
|
28
|
+
otaProgress: OtaProgress | null | undefined,
|
|
29
|
+
localErrorMessage: string,
|
|
30
|
+
): boolean {
|
|
31
|
+
if (otaStatus?.status === "failed" && otaStatus.phase === "download") {
|
|
32
|
+
return true
|
|
33
|
+
}
|
|
34
|
+
if (otaProgress?.status === "FAILED" && otaProgress.stage === "download") {
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
if (localErrorMessage && isDownloadPhaseSnapshot(otaStatus, otaProgress)) {
|
|
38
|
+
return true
|
|
39
|
+
}
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function getOtaErrorMessage(error?: string): string {
|
|
44
|
+
switch (error) {
|
|
45
|
+
case "no_internet":
|
|
46
|
+
return "Glasses WiFi has no internet connection"
|
|
47
|
+
case "clock_skew":
|
|
48
|
+
return "Glasses clock is wrong — syncing time from your phone, then retrying update check"
|
|
49
|
+
case "ssl_error":
|
|
50
|
+
return "Secure connection failed — try a different WiFi network"
|
|
51
|
+
case "download_failed":
|
|
52
|
+
return "Download failed — check glasses WiFi connection"
|
|
53
|
+
case "firmware_too_large":
|
|
54
|
+
return "Firmware file is unexpectedly large — please contact support"
|
|
55
|
+
case "firmware_verify_failed":
|
|
56
|
+
return "Firmware verification failed — please try again or contact support"
|
|
57
|
+
case "apk_verify_failed":
|
|
58
|
+
return "Update verification failed — please try again or contact support"
|
|
59
|
+
case "install_failed":
|
|
60
|
+
return "Install failed — please try again"
|
|
61
|
+
default:
|
|
62
|
+
return error || "Update failed"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Once a BES install has started, any failure conservatively requires a glasses restart. This
|
|
68
|
+
* avoids adding a BES-specific error code to the wire protocol and, more importantly, never offers
|
|
69
|
+
* an unsafe retry when a generic failure or silence may mean BES entered its raw OTA parser.
|
|
70
|
+
*/
|
|
71
|
+
export function shouldRequireGlassesRebootForBesFailure(
|
|
72
|
+
otaStatus: OtaStatus | null | undefined,
|
|
73
|
+
_otaProgress: OtaProgress | null | undefined,
|
|
74
|
+
localErrorMessage: string,
|
|
75
|
+
): boolean {
|
|
76
|
+
if (otaStatus?.stepType !== "bes" || otaStatus.phase !== "install") {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
return otaStatus.status === "failed" || Boolean(localErrorMessage)
|
|
80
|
+
}
|