@glassly/bluetooth-sdk 0.1.0-dev.26
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 +563 -0
- package/android/build.gradle +450 -0
- package/android/gradle.properties.example +9 -0
- package/android/lc3Lib/CMakeLists.txt +6 -0
- package/android/lc3Lib/build.gradle +212 -0
- package/android/lc3Lib/proguard-rules.pro +33 -0
- package/android/lc3Lib/src/main/AndroidManifest.xml +2 -0
- package/android/lc3Lib/src/main/cpp/CMakeLists.txt +8 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/CMakeLists.txt +30 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/CMakeLists.txt +7 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.cc +96 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.h +53 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/Makefile.am +6 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h +26 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h.in +26 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/ogg.h +209 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/os_types.h +158 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus.h +981 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_custom.h +342 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_defines.h +799 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_multistream.h +660 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_projection.h +568 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_types.h +166 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.cc +268 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.h +115 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/opus_tools/opus_header.h +59 -0
- package/android/lc3Lib/src/main/cpp/liblc3/CMakeLists.txt +38 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/lc3.h +309 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/lc3_private.h +162 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/rnnoise.h +114 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/CMakeLists.txt +19 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.c +92 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.h +44 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.c +375 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.h +315 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.c +129 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.h +69 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/common.h +148 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.c +70 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.h +43 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/fastmath.h +158 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/lc3.c +702 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.c +893 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.h +111 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_arm.h +506 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_neon.h +281 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/makefile.mk +35 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.c +452 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.h +57 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct_neon.h +296 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/meson.build +46 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.c +61 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.h +57 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.c +880 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.h +103 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.c +904 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.h +119 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.c +3457 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.h +94 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.c +457 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.h +99 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3.cpp +159 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/_kiss_fft_guts.h +182 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/arch.h +261 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.c +279 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.h +59 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/common.h +48 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/compile.sh +3 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/denoise.c +646 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.c +601 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.h +203 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/opus_types.h +159 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.c +526 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.h +149 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.c +178 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.h +69 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.c +11051 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.h +34 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_reader.c +168 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_train.py +66 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/tansig_table.h +45 -0
- package/android/lc3Lib/src/main/java/com/glassly/lc3Lib/Lc3Cpp.java +38 -0
- package/android/lc3Lib/third_party/CMakeLists.txt +23 -0
- package/android/lc3Lib/third_party/CMakeLists_libogg.txt +18 -0
- package/android/lc3Lib/third_party/CMakeLists_libopus.txt +18 -0
- package/android/lc3Lib/third_party/CMakeLists_opus-tools.txt +23 -0
- package/android/lc3Lib/third_party/opus_tools/src/AUTHORS +5 -0
- package/android/lc3Lib/third_party/opus_tools/src/CMakeLists.txt +4 -0
- package/android/lc3Lib/third_party/opus_tools/src/COPYING +371 -0
- package/android/lc3Lib/third_party/opus_tools/src/ChangeLog +3 -0
- package/android/lc3Lib/third_party/opus_tools/src/Makefile.am +42 -0
- package/android/lc3Lib/third_party/opus_tools/src/Makefile.unix +23 -0
- package/android/lc3Lib/third_party/opus_tools/src/NEWS +0 -0
- package/android/lc3Lib/third_party/opus_tools/src/README +0 -0
- package/android/lc3Lib/third_party/opus_tools/src/autogen.sh +115 -0
- package/android/lc3Lib/third_party/opus_tools/src/configure.ac +293 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/arch.h +239 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/audio-in.c +1046 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.c +245 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.h +28 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.c +320 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.h +51 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/lpc.c +157 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/lpc.h +27 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.c +286 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.h +59 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusdec.c +884 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.c +1021 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.h +101 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.c +639 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.h +51 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/os_support.h +167 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/resample.c +1137 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/speex_resampler.h +344 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/stack_alloc.h +115 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.c +125 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.h +62 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.c +223 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.h +60 -0
- package/android/settings.gradle +4 -0
- package/android/silero/LICENSE.md +17 -0
- package/android/silero/build.gradle +50 -0
- package/android/silero/proguard-rules.pro +24 -0
- package/android/silero/src/androidTest/assets/hello.wav +0 -0
- package/android/silero/src/androidTest/java/com/konovalov/vad/silero/VadSileroTest.kt +79 -0
- package/android/silero/src/main/assets/LICENSE +21 -0
- package/android/silero/src/main/assets/silero_vad.onnx +0 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/Vad.kt +160 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/VadSilero.kt +449 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/FrameSize.kt +15 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/Mode.kt +14 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/SampleRate.kt +12 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/utils/AudioUtils.kt +47 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/utils/TensorMap.kt +41 -0
- package/android/silero/src/test/java/com/konovalov/vad/silero/utils/AudioUtilsTest.kt +44 -0
- package/android/src/main/AndroidManifest.xml +42 -0
- package/android/src/main/assets/G2Firmware/README.md +11 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdk.kt +2325 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkAnalytics.kt +216 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDebug.kt +14 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDefaults.kt +7 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkModule.kt +1088 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/Bridge.kt +953 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/DeviceManager.kt +2528 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/DeviceStore.kt +360 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedChangelogCatalog.kt +8 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedReleaseMetadata.kt +11 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/LocalNetworkModule.kt +414 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/ObservableStore.kt +88 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/OtaManifest.kt +191 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/ReleaseChangelog.kt +61 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/ScopedNetworkReadiness.kt +17 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/audio/AudioModels.kt +144 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/camera/CameraModels.kt +486 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/connection/ConnectionModels.kt +78 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/controllers/ControllerManager.kt +158 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/controllers/R1.kt +937 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/debug/BleTraceLogger.kt +165 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/events/BluetoothEvents.kt +178 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/internal/MapParsing.kt +140 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/net/LocalIpv4.kt +57 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServer.kt +304 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/OtaServerModule.kt +120 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistry.java +108 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoUploadServer.kt +622 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/PhotoReceiverModule.kt +156 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/requests/DisplayRequests.kt +56 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/services/Foreground.kt +272 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/services/PhoneMic.kt +1195 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Ar99.java +2653 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuard.kt +49 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapper.kt +27 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1.kt +3878 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizer.kt +38 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2.kt +6428 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassification.kt +49 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwRenderer.kt +1241 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCache.kt +270 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocol.kt +291 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2Flasher.kt +411 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/GlasslyBle.java +43189 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Mach1.kt +1280 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLive.kt +10817 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLiveL2capChannel.kt +274 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisement.kt +54 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraNex.kt +2011 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Nimo.kt +2532 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/SGCManager.kt +470 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Simulated.kt +228 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/Ar99OtaManager.java +566 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaByteUtils.java +18 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCommandConstants.java +35 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCrc32Util.java +13 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaGattTransport.java +11 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaProtocol.java +92 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/speakerid/SpeakerIdEngine.kt +525 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/status/DeviceStatus.kt +669 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/status/RuntimeState.kt +201 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/status/WifiHotspotStatus.kt +189 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/streaming/StreamModels.kt +518 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/stt/STTTools.kt +391 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +518 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/stt/VadGateSpeechPolicy.kt +229 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/tts/TTSTools.kt +248 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/types/DeviceModels.kt +96 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/AES.java +106 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/AudioSessionMonitor.kt +189 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/AvifExifStripper.java +573 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BitmapJavaUtils.java +169 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleJsonCompact.java +496 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadService.java +677 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleWireProtocol.java +108 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/Constants.kt +46 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/G1Text.kt +436 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/HeifExifTagReader.java +199 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleRelayNaming.java +29 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleUploadService.java +77 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900LengthCodec.java +115 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtils.java +827 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunkReassembler.java +228 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunker.java +325 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/NexSGCUtils.kt +698 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitor.kt +348 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/SmartGlassesConnectionState.java +9 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Ar99OpusPcmDecoder.java +398 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/ByteUtilAudioPlayer.java +655 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Lc3Player.java +441 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PCMAudioPlayer.java +431 -0
- package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PcmStreamPlayer.kt +328 -0
- package/android/src/main/res/values/strings.xml +4 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/BluetoothSdkExceptionTest.kt +18 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/OtaManifestDowngradeTest.kt +86 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/OtaStartResponsePolicyTest.kt +30 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/ReleaseChangelogTest.kt +13 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/ScopedNetworkReadinessTest.kt +39 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/StreamStatusEventTest.kt +29 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/camera/PhotoRequestTest.kt +141 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServerTest.kt +82 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistryTest.java +75 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/services/ForegroundServiceTypeTest.kt +69 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/Ar99AdvertisementMatcherTest.java +22 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuardTest.kt +73 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapperTest.kt +67 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/EvenRleTest.kt +63 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizerTest.kt +31 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassificationTest.kt +89 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwRendererTest.kt +344 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCacheTest.kt +200 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocolTest.kt +131 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLiveGattCharacteristicsTest.kt +39 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisementParserTest.kt +133 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/NimoProtocolTest.kt +333 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/AvifExifStripperTest.java +46 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/BinaryMessageChunkerTest.java +84 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/BleJsonCompactTest.java +319 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadServiceTest.java +107 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsEndiannessTest.java +172 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsTest.java +24 -0
- package/android/src/test/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitorTest.kt +45 -0
- package/android/src/test/resources/avif_with_exif.avif +0 -0
- package/app.plugin.js +3 -0
- package/build/BluetoothSdk.types.d.ts +1354 -0
- package/build/BluetoothSdk.types.d.ts.map +1 -0
- package/build/BluetoothSdk.types.js +41 -0
- package/build/BluetoothSdk.types.js.map +1 -0
- package/build/_internal.d.ts +17 -0
- package/build/_internal.d.ts.map +1 -0
- package/build/_internal.js +16 -0
- package/build/_internal.js.map +1 -0
- package/build/_private/BluetoothSdkModule.d.ts +172 -0
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -0
- package/build/_private/BluetoothSdkModule.js +300 -0
- package/build/_private/BluetoothSdkModule.js.map +1 -0
- package/build/_private/LocalNetworkModule.d.ts +38 -0
- package/build/_private/LocalNetworkModule.d.ts.map +1 -0
- package/build/_private/LocalNetworkModule.js +3 -0
- package/build/_private/LocalNetworkModule.js.map +1 -0
- package/build/_private/cameraRequestPayload.d.ts +4 -0
- package/build/_private/cameraRequestPayload.d.ts.map +1 -0
- package/build/_private/cameraRequestPayload.js +32 -0
- package/build/_private/cameraRequestPayload.js.map +1 -0
- package/build/_private/photoRequestPayload.d.ts +6 -0
- package/build/_private/photoRequestPayload.d.ts.map +1 -0
- package/build/_private/photoRequestPayload.js +86 -0
- package/build/_private/photoRequestPayload.js.map +1 -0
- package/build/_private/sdkOtaManifest.d.ts +11 -0
- package/build/_private/sdkOtaManifest.d.ts.map +1 -0
- package/build/_private/sdkOtaManifest.js +15 -0
- package/build/_private/sdkOtaManifest.js.map +1 -0
- package/build/changelogs.d.ts +7 -0
- package/build/changelogs.d.ts.map +1 -0
- package/build/changelogs.js +46 -0
- package/build/changelogs.js.map +1 -0
- package/build/debug.d.ts +3 -0
- package/build/debug.d.ts.map +1 -0
- package/build/debug.js +8 -0
- package/build/debug.js.map +1 -0
- package/build/generated/changelogCatalog.d.ts +9 -0
- package/build/generated/changelogCatalog.d.ts.map +1 -0
- package/build/generated/changelogCatalog.js +12 -0
- package/build/generated/changelogCatalog.js.map +1 -0
- 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 +6 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +171 -0
- package/build/index.js.map +1 -0
- package/build/ota-server/OtaServer.types.d.ts +14 -0
- package/build/ota-server/OtaServer.types.d.ts.map +1 -0
- package/build/ota-server/OtaServer.types.js +2 -0
- package/build/ota-server/OtaServer.types.js.map +1 -0
- package/build/ota-server/OtaServerModule.d.ts +21 -0
- package/build/ota-server/OtaServerModule.d.ts.map +1 -0
- package/build/ota-server/OtaServerModule.js +3 -0
- package/build/ota-server/OtaServerModule.js.map +1 -0
- package/build/ota-server/OtaServerModule.web.d.ts +10 -0
- package/build/ota-server/OtaServerModule.web.d.ts.map +1 -0
- package/build/ota-server/OtaServerModule.web.js +12 -0
- package/build/ota-server/OtaServerModule.web.js.map +1 -0
- package/build/ota-server/index.d.ts +3 -0
- package/build/ota-server/index.d.ts.map +1 -0
- package/build/ota-server/index.js +3 -0
- package/build/ota-server/index.js.map +1 -0
- package/build/ota-transport/index.d.ts +67 -0
- package/build/ota-transport/index.d.ts.map +1 -0
- package/build/ota-transport/index.js +58 -0
- package/build/ota-transport/index.js.map +1 -0
- package/build/photo-receiver/PhotoReceiver.types.d.ts +18 -0
- package/build/photo-receiver/PhotoReceiver.types.d.ts.map +1 -0
- package/build/photo-receiver/PhotoReceiver.types.js +2 -0
- package/build/photo-receiver/PhotoReceiver.types.js.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.d.ts +10 -0
- package/build/photo-receiver/PhotoReceiverModule.d.ts.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.js +3 -0
- package/build/photo-receiver/PhotoReceiverModule.js.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.web.d.ts +10 -0
- package/build/photo-receiver/PhotoReceiverModule.web.d.ts.map +1 -0
- package/build/photo-receiver/PhotoReceiverModule.web.js +12 -0
- package/build/photo-receiver/PhotoReceiverModule.web.js.map +1 -0
- package/build/photo-receiver/index.d.ts +3 -0
- package/build/photo-receiver/index.d.ts.map +1 -0
- package/build/photo-receiver/index.js +3 -0
- package/build/photo-receiver/index.js.map +1 -0
- package/build/react/index.d.ts +5 -0
- package/build/react/index.d.ts.map +1 -0
- package/build/react/index.js +4 -0
- package/build/react/index.js.map +1 -0
- package/build/react/useBluetooth.d.ts +100 -0
- package/build/react/useBluetooth.d.ts.map +1 -0
- package/build/react/useBluetooth.js +167 -0
- package/build/react/useBluetooth.js.map +1 -0
- package/build/react/useBluetoothEvent.d.ts +6 -0
- package/build/react/useBluetoothEvent.d.ts.map +1 -0
- package/build/react/useBluetoothEvent.js +21 -0
- package/build/react/useBluetoothEvent.js.map +1 -0
- package/build/react/useBluetoothScan.d.ts +22 -0
- package/build/react/useBluetoothScan.d.ts.map +1 -0
- package/build/react/useBluetoothScan.js +135 -0
- package/build/react/useBluetoothScan.js.map +1 -0
- package/build/react/useBluetoothStatus.d.ts +16 -0
- package/build/react/useBluetoothStatus.d.ts.map +1 -0
- package/build/react/useBluetoothStatus.js +137 -0
- package/build/react/useBluetoothStatus.js.map +1 -0
- package/build/react/useGlassesConnection.d.ts +29 -0
- package/build/react/useGlassesConnection.d.ts.map +1 -0
- package/build/react/useGlassesConnection.js +153 -0
- package/build/react/useGlassesConnection.js.map +1 -0
- package/build/types/index.d.ts +3 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/index.js +2 -0
- package/build/types/index.js.map +1 -0
- package/expo-module.config.json +14 -0
- package/ios/BackgroundOtaArtifactDownloader.swift +125 -0
- package/ios/BluetoothSdkModule.swift +1034 -0
- package/ios/GlasslyBluetoothSDK.podspec +106 -0
- package/ios/LocalIPv4.swift +150 -0
- package/ios/LocalOtaServer.swift +309 -0
- package/ios/LocalPhotoUploadServer.swift +754 -0
- package/ios/OtaServerModule.swift +147 -0
- package/ios/Packages/CoreObjC/CoreObjC.xcodeproj/project.pbxproj +213 -0
- package/ios/Packages/CoreObjC/PcmConverter.h +22 -0
- package/ios/Packages/CoreObjC/PcmConverter.m +266 -0
- package/ios/Packages/CoreObjC/attdet.c +92 -0
- package/ios/Packages/CoreObjC/attdet.h +44 -0
- package/ios/Packages/CoreObjC/bits.c +375 -0
- package/ios/Packages/CoreObjC/bits.h +315 -0
- package/ios/Packages/CoreObjC/bwdet.c +129 -0
- package/ios/Packages/CoreObjC/bwdet.h +69 -0
- package/ios/Packages/CoreObjC/common.h +151 -0
- package/ios/Packages/CoreObjC/energy.c +70 -0
- package/ios/Packages/CoreObjC/energy.h +43 -0
- package/ios/Packages/CoreObjC/fastmath.h +158 -0
- package/ios/Packages/CoreObjC/include/PcmConverter.h +22 -0
- package/ios/Packages/CoreObjC/lc3.c +704 -0
- package/ios/Packages/CoreObjC/lc3.h +313 -0
- package/ios/Packages/CoreObjC/lc3_cpp.h +283 -0
- package/ios/Packages/CoreObjC/lc3_private.h +163 -0
- package/ios/Packages/CoreObjC/ltpf.c +905 -0
- package/ios/Packages/CoreObjC/ltpf.h +111 -0
- package/ios/Packages/CoreObjC/ltpf_arm.h +506 -0
- package/ios/Packages/CoreObjC/ltpf_neon.h +281 -0
- package/ios/Packages/CoreObjC/makefile.mk +35 -0
- package/ios/Packages/CoreObjC/mdct.c +469 -0
- package/ios/Packages/CoreObjC/mdct.h +57 -0
- package/ios/Packages/CoreObjC/mdct_neon.h +296 -0
- package/ios/Packages/CoreObjC/meson.build +61 -0
- package/ios/Packages/CoreObjC/plc.c +61 -0
- package/ios/Packages/CoreObjC/plc.h +57 -0
- package/ios/Packages/CoreObjC/rnnoise.h +114 -0
- package/ios/Packages/CoreObjC/sns.c +880 -0
- package/ios/Packages/CoreObjC/sns.h +103 -0
- package/ios/Packages/CoreObjC/spec.c +907 -0
- package/ios/Packages/CoreObjC/spec.h +119 -0
- package/ios/Packages/CoreObjC/tables.c +3457 -0
- package/ios/Packages/CoreObjC/tables.h +94 -0
- package/ios/Packages/CoreObjC/tns.c +457 -0
- package/ios/Packages/CoreObjC/tns.h +99 -0
- package/ios/Packages/SherpaOnnx/Model/joiner.onnx +0 -0
- package/ios/Packages/SherpaOnnx/Model/tokens.txt +502 -0
- package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +2383 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +48 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
- package/ios/Packages/libbz2/module.modulemap +5 -0
- package/ios/Packages/libbz2/shim.h +1 -0
- package/ios/PhotoReceiverModule.swift +129 -0
- package/ios/Source/BluetoothSDK.swift +2303 -0
- package/ios/Source/BluetoothSDKDebug.swift +12 -0
- package/ios/Source/BluetoothSdkDefaults.swift +29 -0
- package/ios/Source/Bridge.swift +708 -0
- package/ios/Source/Bridging-Header.h +16 -0
- package/ios/Source/DeviceManager.swift +2109 -0
- package/ios/Source/DeviceStore.swift +336 -0
- package/ios/Source/GeneratedChangelogCatalog.swift +7 -0
- package/ios/Source/GeneratedReleaseMetadata.swift +11 -0
- package/ios/Source/ObservableStore.swift +118 -0
- package/ios/Source/OtaManifest.swift +211 -0
- package/ios/Source/PrivacyInfo.xcprivacy +23 -0
- package/ios/Source/ReleaseChangelog.swift +65 -0
- package/ios/Source/Resources/G2Firmware/README.md +10 -0
- package/ios/Source/audio/AudioModels.swift +178 -0
- package/ios/Source/audio/PcmStreamPlayer.swift +410 -0
- package/ios/Source/camera/CameraModels.swift +866 -0
- package/ios/Source/connection/ScanSession.swift +27 -0
- package/ios/Source/controllers/ControllerManager.swift +184 -0
- package/ios/Source/controllers/R1.swift +829 -0
- package/ios/Source/errors/BluetoothSdkError.swift +19 -0
- package/ios/Source/events/BluetoothEvents.swift +342 -0
- package/ios/Source/internal/BleTraceLogger.swift +192 -0
- package/ios/Source/internal/BluetoothAvailability.swift +78 -0
- package/ios/Source/internal/BluetoothSdkAnalytics.swift +199 -0
- package/ios/Source/internal/ValueParsing.swift +99 -0
- package/ios/Source/requests/DisplayRequests.swift +82 -0
- package/ios/Source/services/PhoneMic.swift +662 -0
- package/ios/Source/sgcs/Ar99.swift +2451 -0
- package/ios/Source/sgcs/Frame.swift +649 -0
- package/ios/Source/sgcs/G1.swift +2554 -0
- package/ios/Source/sgcs/G2.swift +6887 -0
- package/ios/Source/sgcs/G2CfwClassification.swift +43 -0
- package/ios/Source/sgcs/G2CfwRenderer.swift +1279 -0
- package/ios/Source/sgcs/G2CfwTextureCache.swift +233 -0
- package/ios/Source/sgcs/G2FlashProtocol.swift +312 -0
- package/ios/Source/sgcs/G2Flasher.swift +773 -0
- package/ios/Source/sgcs/Mach1.swift +541 -0
- package/ios/Source/sgcs/MentraLive.swift +7011 -0
- package/ios/Source/sgcs/MentraLiveL2capChannel.swift +183 -0
- package/ios/Source/sgcs/MentraLivePairingAdvertisement.swift +64 -0
- package/ios/Source/sgcs/MentraNex.swift +3221 -0
- package/ios/Source/sgcs/Nimo.swift +1886 -0
- package/ios/Source/sgcs/SGCManager.swift +608 -0
- package/ios/Source/sgcs/Simulated.swift +274 -0
- package/ios/Source/sgcs/ar99/ota/Ar99OtaManager.swift +637 -0
- package/ios/Source/sgcs/glassly_ble.pb.swift +4354 -0
- package/ios/Source/speakerid/SpeakerIdEngine.swift +573 -0
- package/ios/Source/status/DeviceStatus.swift +981 -0
- package/ios/Source/status/RuntimeState.swift +359 -0
- package/ios/Source/status/WifiHotspotStatus.swift +345 -0
- package/ios/Source/streaming/StreamModels.swift +693 -0
- package/ios/Source/stt/STTTools.swift +191 -0
- package/ios/Source/stt/SherpaOnnxTranscriber.swift +466 -0
- package/ios/Source/tts/TTSTools.swift +171 -0
- package/ios/Source/types/DeviceModels.swift +177 -0
- package/ios/Source/utils/AudioSessionMonitor.swift +283 -0
- package/ios/Source/utils/BinaryCodec.swift +61 -0
- package/ios/Source/utils/BleJsonCompact.swift +405 -0
- package/ios/Source/utils/BleWireProtocol.swift +92 -0
- package/ios/Source/utils/Constants.swift +78 -0
- package/ios/Source/utils/Enums.swift +95 -0
- package/ios/Source/utils/G1Text.swift +2096 -0
- package/ios/Source/utils/JSCExperiment.swift +241 -0
- package/ios/Source/utils/MemoryMonitor.swift +44 -0
- package/ios/Source/utils/MessageChunkReassembler.swift +190 -0
- package/ios/Source/utils/MessageChunker.swift +294 -0
- package/ios/Source/utils/Models.swift +135 -0
- package/ios/Source/utils/PhoneAudioMonitor.swift +230 -0
- package/ios/Source/utils/TarBz2Extractor.swift +257 -0
- package/ios/Tests/BluetoothSDKTests/G2CfwClassificationTests.swift +78 -0
- package/ios/Tests/BluetoothSDKTests/G2CfwRendererTests.swift +372 -0
- package/ios/Tests/BluetoothSDKTests/G2CfwTextureCacheTests.swift +162 -0
- package/ios/Tests/BluetoothSDKTests/G2FlashProtocolTests.swift +182 -0
- package/ios/Tests/MentraLivePairingAdvertisementTests.swift +160 -0
- package/ios/Tests/ReleaseChangelogTests.swift +13 -0
- package/package.json +129 -0
- package/plugin/build/index.d.ts +10 -0
- package/plugin/build/index.js +12 -0
- package/plugin/build/withAndroid.d.ts +3 -0
- package/plugin/build/withAndroid.js +190 -0
- package/plugin/build/withIos.d.ts +5 -0
- package/plugin/build/withIos.js +108 -0
- package/scripts/inject-ios-sdk-version.mjs +65 -0
- package/scripts/public-ota-api.test.mjs +37 -0
- package/scripts/verify-release-package.mjs +45 -0
- package/scripts/write-release-metadata.mjs +152 -0
- package/scripts/write-release-metadata.test.mjs +37 -0
- package/src/BluetoothSdk.types.ts +1623 -0
- package/src/_internal.ts +16 -0
- package/src/_private/BluetoothSdkModule.ts +684 -0
- package/src/_private/LocalNetworkModule.ts +50 -0
- package/src/_private/cameraRequestPayload.ts +34 -0
- package/src/_private/photoRequestPayload.ts +90 -0
- package/src/_private/sdkOtaManifest.ts +18 -0
- package/src/changelogs.ts +46 -0
- package/src/debug.ts +9 -0
- package/src/generated/changelogCatalog.ts +13 -0
- package/src/generated/releaseMetadata.ts +20 -0
- package/src/index.ts +321 -0
- package/src/ota-server/OtaServer.types.ts +10 -0
- package/src/ota-server/OtaServerModule.ts +23 -0
- package/src/ota-server/OtaServerModule.web.ts +17 -0
- package/src/ota-server/index.ts +2 -0
- package/src/ota-transport/index.ts +116 -0
- package/src/photo-receiver/PhotoReceiver.types.ts +20 -0
- package/src/photo-receiver/PhotoReceiverModule.ts +11 -0
- package/src/photo-receiver/PhotoReceiverModule.web.ts +17 -0
- package/src/photo-receiver/index.ts +2 -0
- package/src/react/index.ts +21 -0
- package/src/react/useBluetooth.ts +309 -0
- package/src/react/useBluetoothEvent.ts +35 -0
- package/src/react/useBluetoothScan.ts +173 -0
- package/src/react/useBluetoothStatus.ts +180 -0
- package/src/react/useGlassesConnection.ts +202 -0
- package/src/types/index.ts +12 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.withAndroidConfiguration = void 0;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
10
|
+
const META_ANALYTICS_DISABLED = "com.glassly.bluetoothsdk.analytics.disabled";
|
|
11
|
+
const STALE_META_POSTHOG_API_KEY = "com.glassly.bluetoothsdk.analytics.posthog_api_key";
|
|
12
|
+
const STALE_META_POSTHOG_HOST = "com.glassly.bluetoothsdk.analytics.posthog_host";
|
|
13
|
+
const ANALYTICS_META_NAMES = [META_ANALYTICS_DISABLED, STALE_META_POSTHOG_API_KEY, STALE_META_POSTHOG_HOST];
|
|
14
|
+
function getBluetoothSdkRoot() {
|
|
15
|
+
return path_1.default.dirname(require.resolve("../../package.json"));
|
|
16
|
+
}
|
|
17
|
+
function toGroovyString(value) {
|
|
18
|
+
return JSON.stringify(value);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Modify settings.gradle to include lc3Lib and silero modules
|
|
22
|
+
*/
|
|
23
|
+
function withSettingsGradleModifications(config) {
|
|
24
|
+
return (0, config_plugins_1.withSettingsGradle)(config, (config) => {
|
|
25
|
+
let settingsGradle = config.modResults.contents;
|
|
26
|
+
const bluetoothSdkRoot = getBluetoothSdkRoot();
|
|
27
|
+
const bluetoothSdkRootExpression = `System.getenv("GLASSLY_BLUETOOTH_SDK_PACKAGE_PATH") ?: ${toGroovyString(bluetoothSdkRoot)}`;
|
|
28
|
+
if (!settingsGradle.includes("project(':glassly-bluetooth-sdk').projectDir")) {
|
|
29
|
+
const bluetoothSdkProjectBlock = `
|
|
30
|
+
if (findProject(':glassly-bluetooth-sdk') != null) {
|
|
31
|
+
project(':glassly-bluetooth-sdk').projectDir = new File(${bluetoothSdkRootExpression}, 'android')
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
const lc3Include = " include ':lc3Lib'";
|
|
35
|
+
settingsGradle = settingsGradle.includes(lc3Include)
|
|
36
|
+
? settingsGradle.replace(lc3Include, `${bluetoothSdkProjectBlock}\n${lc3Include}`)
|
|
37
|
+
: `${settingsGradle}${bluetoothSdkProjectBlock}`;
|
|
38
|
+
}
|
|
39
|
+
if (!settingsGradle.includes("include ':lc3Lib'")) {
|
|
40
|
+
settingsGradle += `
|
|
41
|
+
include ':lc3Lib'
|
|
42
|
+
`;
|
|
43
|
+
}
|
|
44
|
+
if (!settingsGradle.includes("project(':lc3Lib').projectDir")) {
|
|
45
|
+
settingsGradle += `
|
|
46
|
+
project(':lc3Lib').projectDir = new File(${bluetoothSdkRootExpression}, 'android/lc3Lib')
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
if (!settingsGradle.includes("include ':silero'")) {
|
|
50
|
+
settingsGradle += `
|
|
51
|
+
include ':silero'
|
|
52
|
+
`;
|
|
53
|
+
}
|
|
54
|
+
if (!settingsGradle.includes("project(':silero').projectDir")) {
|
|
55
|
+
settingsGradle += `
|
|
56
|
+
project(':silero').projectDir = new File(${bluetoothSdkRootExpression}, 'android/silero')
|
|
57
|
+
`;
|
|
58
|
+
}
|
|
59
|
+
config.modResults.contents = settingsGradle;
|
|
60
|
+
return config;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Modify gradle.properties to add node path for native builds launched outside a shell.
|
|
65
|
+
*/
|
|
66
|
+
function withGradlePropertiesModifications(config) {
|
|
67
|
+
return (0, config_plugins_1.withGradleProperties)(config, (config) => {
|
|
68
|
+
let props = config.modResults;
|
|
69
|
+
// Get node path and add to org.gradle.jvmargs
|
|
70
|
+
try {
|
|
71
|
+
const nodeExecutable = (0, child_process_1.execSync)("which node", { encoding: "utf-8" }).trim();
|
|
72
|
+
// Get parent directory of bin (e.g., /path/to/node/bin/node -> /path/to/node)
|
|
73
|
+
const nodePath = path_1.default.dirname(nodeExecutable);
|
|
74
|
+
// Find existing org.gradle.jvmargs property
|
|
75
|
+
const jvmArgsIndex = props.findIndex((p) => p.type === "property" && p.key === "org.gradle.jvmargs");
|
|
76
|
+
if (jvmArgsIndex !== -1) {
|
|
77
|
+
// Append nodePath to existing jvmargs if not already present
|
|
78
|
+
const jvmArgsProp = props[jvmArgsIndex];
|
|
79
|
+
if (jvmArgsProp?.type === "property" && "value" in jvmArgsProp) {
|
|
80
|
+
const currentValue = jvmArgsProp.value;
|
|
81
|
+
if (!currentValue.includes("-Dorg.gradle.project.nodePath=")) {
|
|
82
|
+
jvmArgsProp.value = `${currentValue} -Dorg.gradle.project.nodePath=${nodePath}`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// Create new jvmargs property with nodePath
|
|
88
|
+
props.push({
|
|
89
|
+
type: "property",
|
|
90
|
+
key: "org.gradle.jvmargs",
|
|
91
|
+
value: `-Dorg.gradle.project.nodePath=${nodePath}`,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.warn("Failed to get node path:", error);
|
|
97
|
+
}
|
|
98
|
+
config.modResults = props;
|
|
99
|
+
return config;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Inject a local Maven repository into the root project's allprojects block so
|
|
104
|
+
* that `:app` (and any other module that transitively pulls our deps) can
|
|
105
|
+
* resolve `com.k2fsa.sherpa.onnx:sherpa-onnx`. The AAR is downloaded at
|
|
106
|
+
* configure-time by bluetooth-sdk's own build.gradle into
|
|
107
|
+
* `android/libs/maven/`; we just need that directory exposed as a maven repo
|
|
108
|
+
* to consumers as well. AGP rejects raw local-.aar deps from library modules,
|
|
109
|
+
* so the Maven layout is the supported workaround.
|
|
110
|
+
*/
|
|
111
|
+
function withSherpaOnnxLocalMavenRepo(config) {
|
|
112
|
+
return (0, config_plugins_1.withProjectBuildGradle)(config, (config) => {
|
|
113
|
+
if (config.modResults.language !== "groovy") {
|
|
114
|
+
return config;
|
|
115
|
+
}
|
|
116
|
+
let contents = config.modResults.contents;
|
|
117
|
+
const fallbackRoot = toGroovyString(getBluetoothSdkRoot());
|
|
118
|
+
const repoDirExpression = `new File(System.getenv("GLASSLY_BLUETOOTH_SDK_PACKAGE_PATH") ?: ${fallbackRoot}, "android/libs/maven")`;
|
|
119
|
+
const marker = "// bluetooth-sdk: sherpa-onnx local maven repo";
|
|
120
|
+
if (contents.includes(marker)) {
|
|
121
|
+
return config;
|
|
122
|
+
}
|
|
123
|
+
const repoBlock = ` maven {\n ${marker}\n url = uri(${repoDirExpression})\n }`;
|
|
124
|
+
const allprojectsMatch = contents.match(/allprojects\s*\{[\s\S]*?repositories\s*\{/);
|
|
125
|
+
if (allprojectsMatch) {
|
|
126
|
+
const insertIdx = allprojectsMatch.index + allprojectsMatch[0].length;
|
|
127
|
+
contents = contents.slice(0, insertIdx) + "\n" + repoBlock + contents.slice(insertIdx);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
// Fallback: append an allprojects block. Older Expo templates that don't
|
|
131
|
+
// emit allprojects {} put repositories in settings.gradle instead — but
|
|
132
|
+
// this codebase's prebuild has historically emitted allprojects, so this
|
|
133
|
+
// branch is just a safety net.
|
|
134
|
+
contents += `\nallprojects {\n repositories {\n${repoBlock}\n }\n}\n`;
|
|
135
|
+
}
|
|
136
|
+
config.modResults.contents = contents;
|
|
137
|
+
return config;
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function resolveAnalyticsProps(props) {
|
|
141
|
+
const analytics = props?.analytics;
|
|
142
|
+
let disabled;
|
|
143
|
+
if (analytics === false) {
|
|
144
|
+
disabled = true;
|
|
145
|
+
}
|
|
146
|
+
else if (analytics === true) {
|
|
147
|
+
disabled = false;
|
|
148
|
+
}
|
|
149
|
+
else if (typeof analytics === "object" && analytics.enabled !== undefined) {
|
|
150
|
+
disabled = !analytics.enabled;
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
disabled,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function upsertMetaData(application, name, value) {
|
|
157
|
+
application["meta-data"] ??= [];
|
|
158
|
+
const existing = application["meta-data"].find((item) => item.$?.["android:name"] === name);
|
|
159
|
+
const entry = existing ?? { $: { "android:name": name } };
|
|
160
|
+
entry.$["android:value"] = value;
|
|
161
|
+
if (!existing) {
|
|
162
|
+
application["meta-data"].push(entry);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function removeMetaData(application, name) {
|
|
166
|
+
application["meta-data"] = (application["meta-data"] ?? []).filter((item) => item.$?.["android:name"] !== name);
|
|
167
|
+
}
|
|
168
|
+
function withAnalyticsManifestMetadata(config, props) {
|
|
169
|
+
return (0, config_plugins_1.withAndroidManifest)(config, (config) => {
|
|
170
|
+
const analytics = resolveAnalyticsProps(props);
|
|
171
|
+
const application = config_plugins_1.AndroidConfig.Manifest.getMainApplicationOrThrow(config.modResults);
|
|
172
|
+
for (const name of ANALYTICS_META_NAMES) {
|
|
173
|
+
removeMetaData(application, name);
|
|
174
|
+
}
|
|
175
|
+
if (analytics.disabled !== undefined) {
|
|
176
|
+
upsertMetaData(application, META_ANALYTICS_DISABLED, analytics.disabled ? "true" : "false");
|
|
177
|
+
}
|
|
178
|
+
return config;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
const withAndroidConfiguration = (config, props) => {
|
|
182
|
+
config = withSettingsGradleModifications(config);
|
|
183
|
+
config = withSherpaOnnxLocalMavenRepo(config);
|
|
184
|
+
config = withAnalyticsManifestMetadata(config, props);
|
|
185
|
+
if (props?.node) {
|
|
186
|
+
config = withGradlePropertiesModifications(config);
|
|
187
|
+
}
|
|
188
|
+
return config;
|
|
189
|
+
};
|
|
190
|
+
exports.withAndroidConfiguration = withAndroidConfiguration;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { IOSConfig, type ConfigPlugin } from "expo/config-plugins";
|
|
2
|
+
import { type BluetoothSdkPluginProps } from "./index";
|
|
3
|
+
export declare const INFO_SDK_VERSION = "BluetoothSdkVersion";
|
|
4
|
+
export declare function applyBluetoothSdkInfoPlist(infoPlist: IOSConfig.InfoPlist, props: BluetoothSdkPluginProps | undefined): IOSConfig.InfoPlist;
|
|
5
|
+
export declare const withIosConfiguration: ConfigPlugin<BluetoothSdkPluginProps>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.withIosConfiguration = exports.INFO_SDK_VERSION = void 0;
|
|
7
|
+
exports.applyBluetoothSdkInfoPlist = applyBluetoothSdkInfoPlist;
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
12
|
+
const BLUETOOTH_SDK_EXPO_ADAPTER_ENV = "GLASSLY_BLUETOOTH_SDK_INCLUDE_EXPO_ADAPTER";
|
|
13
|
+
const BLUETOOTH_SDK_EXPO_ADAPTER_LINE = `ENV['${BLUETOOTH_SDK_EXPO_ADAPTER_ENV}'] ||= '1'`;
|
|
14
|
+
const INFO_ANALYTICS_DISABLED = "BluetoothSdkAnalyticsDisabled";
|
|
15
|
+
exports.INFO_SDK_VERSION = "BluetoothSdkVersion";
|
|
16
|
+
const STALE_INFO_POSTHOG_API_KEY = "BluetoothSdkPostHogApiKey";
|
|
17
|
+
const STALE_INFO_POSTHOG_HOST = "BluetoothSdkPostHogHost";
|
|
18
|
+
const ensureBluetoothSdkExpoAdapterPodEnv = (podfile) => {
|
|
19
|
+
if (podfile.includes(BLUETOOTH_SDK_EXPO_ADAPTER_ENV)) {
|
|
20
|
+
return podfile;
|
|
21
|
+
}
|
|
22
|
+
const insertion = [
|
|
23
|
+
" # Expo apps need the SDK's Expo module adapter so autolinking can register BluetoothSdk.",
|
|
24
|
+
` ${BLUETOOTH_SDK_EXPO_ADAPTER_LINE}`,
|
|
25
|
+
"",
|
|
26
|
+
].join("\n");
|
|
27
|
+
return podfile.replace(/(target\s+['"][^'"]+['"]\s+do\n)/, `$1${insertion}`);
|
|
28
|
+
};
|
|
29
|
+
const withXcodeEnvLocal = (config) => {
|
|
30
|
+
return (0, config_plugins_1.withDangerousMod)(config, [
|
|
31
|
+
"ios",
|
|
32
|
+
async (config) => {
|
|
33
|
+
try {
|
|
34
|
+
// Get node executable path
|
|
35
|
+
const nodeExecutable = (0, child_process_1.execSync)("which node", { encoding: "utf-8" }).trim();
|
|
36
|
+
// Path to .xcode.env.local
|
|
37
|
+
const iosPath = path_1.default.join(config.modRequest.platformProjectRoot);
|
|
38
|
+
const xcodeEnvLocalPath = path_1.default.join(iosPath, ".xcode.env.local");
|
|
39
|
+
// Content to write
|
|
40
|
+
const content = `export NODE_BINARY=${nodeExecutable}\n`;
|
|
41
|
+
// Write or append to .xcode.env.local
|
|
42
|
+
if (fs_1.default.existsSync(xcodeEnvLocalPath)) {
|
|
43
|
+
const existingContent = fs_1.default.readFileSync(xcodeEnvLocalPath, "utf-8");
|
|
44
|
+
if (!existingContent.includes("NODE_BINARY")) {
|
|
45
|
+
fs_1.default.appendFileSync(xcodeEnvLocalPath, content);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
fs_1.default.writeFileSync(xcodeEnvLocalPath, content);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.warn("Failed to create .xcode.env.local:", error);
|
|
54
|
+
}
|
|
55
|
+
return config;
|
|
56
|
+
},
|
|
57
|
+
]);
|
|
58
|
+
};
|
|
59
|
+
function resolveAnalyticsProps(props) {
|
|
60
|
+
const analytics = props?.analytics;
|
|
61
|
+
let disabled;
|
|
62
|
+
if (analytics === false) {
|
|
63
|
+
disabled = true;
|
|
64
|
+
}
|
|
65
|
+
else if (analytics === true) {
|
|
66
|
+
disabled = false;
|
|
67
|
+
}
|
|
68
|
+
else if (typeof analytics === "object" && analytics.enabled !== undefined) {
|
|
69
|
+
disabled = !analytics.enabled;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
disabled,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function applyBluetoothSdkInfoPlist(infoPlist, props) {
|
|
76
|
+
const packageJson = require("../../package.json");
|
|
77
|
+
const sdkVersion = typeof packageJson.version === "string" ? packageJson.version.trim() : "";
|
|
78
|
+
if (!sdkVersion) {
|
|
79
|
+
throw new Error("@glassly/bluetooth-sdk package.json is missing a version");
|
|
80
|
+
}
|
|
81
|
+
const analytics = resolveAnalyticsProps(props);
|
|
82
|
+
delete infoPlist[INFO_ANALYTICS_DISABLED];
|
|
83
|
+
delete infoPlist[STALE_INFO_POSTHOG_API_KEY];
|
|
84
|
+
delete infoPlist[STALE_INFO_POSTHOG_HOST];
|
|
85
|
+
infoPlist[exports.INFO_SDK_VERSION] = sdkVersion;
|
|
86
|
+
if (analytics.disabled !== undefined) {
|
|
87
|
+
infoPlist[INFO_ANALYTICS_DISABLED] = analytics.disabled;
|
|
88
|
+
}
|
|
89
|
+
return infoPlist;
|
|
90
|
+
}
|
|
91
|
+
function withBluetoothSdkInfoPlist(config, props) {
|
|
92
|
+
return (0, config_plugins_1.withInfoPlist)(config, (config) => {
|
|
93
|
+
config.modResults = applyBluetoothSdkInfoPlist(config.modResults, props);
|
|
94
|
+
return config;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
const withIosConfiguration = (config, props) => {
|
|
98
|
+
config = (0, config_plugins_1.withPodfile)(config, (config) => {
|
|
99
|
+
config.modResults.contents = ensureBluetoothSdkExpoAdapterPodEnv(config.modResults.contents);
|
|
100
|
+
return config;
|
|
101
|
+
});
|
|
102
|
+
config = withBluetoothSdkInfoPlist(config, props);
|
|
103
|
+
if (props?.node) {
|
|
104
|
+
config = withXcodeEnvLocal(config);
|
|
105
|
+
}
|
|
106
|
+
return config;
|
|
107
|
+
};
|
|
108
|
+
exports.withIosConfiguration = withIosConfiguration;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs/promises"
|
|
4
|
+
import path from "node:path"
|
|
5
|
+
import { fileURLToPath } from "node:url"
|
|
6
|
+
|
|
7
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
|
|
8
|
+
const packageJsonPath = path.join(packageRoot, "package.json")
|
|
9
|
+
const sourcePath = path.join(packageRoot, "ios/Source/BluetoothSdkDefaults.swift")
|
|
10
|
+
const backupPath = path.join(packageRoot, ".bluetooth-sdk-version-prepack-backup")
|
|
11
|
+
const restore = process.argv.includes("--restore")
|
|
12
|
+
|
|
13
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"))
|
|
14
|
+
const version = packageJson.version
|
|
15
|
+
|
|
16
|
+
if (typeof version !== "string" || version.trim() === "") {
|
|
17
|
+
throw new Error("mobile/modules/bluetooth-sdk/package.json is missing a version")
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const placeholder = 'private static let swiftPackageSdkVersion = "__GLASSLY_BLUETOOTH_SDK_VERSION__"'
|
|
21
|
+
const injectedVersion = `private static let swiftPackageSdkVersion = "${version}"`
|
|
22
|
+
|
|
23
|
+
async function pathExists(filePath) {
|
|
24
|
+
try {
|
|
25
|
+
await fs.access(filePath)
|
|
26
|
+
return true
|
|
27
|
+
} catch {
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (restore) {
|
|
33
|
+
if (!(await pathExists(backupPath))) {
|
|
34
|
+
console.log("No iOS SDK version prepack backup found; nothing to restore.")
|
|
35
|
+
process.exit(0)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
await fs.writeFile(sourcePath, await fs.readFile(backupPath, "utf8"))
|
|
39
|
+
await fs.rm(backupPath)
|
|
40
|
+
console.log("Restored placeholder iOS SDK version after packing.")
|
|
41
|
+
process.exit(0)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (await pathExists(backupPath)) {
|
|
45
|
+
throw new Error("Found an existing iOS SDK version prepack backup. Run `npm run postpack` before packing again.")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const originalSource = await fs.readFile(sourcePath, "utf8")
|
|
49
|
+
let packedSource
|
|
50
|
+
|
|
51
|
+
if (originalSource.includes(placeholder)) {
|
|
52
|
+
packedSource = originalSource.replace(placeholder, injectedVersion)
|
|
53
|
+
} else if (originalSource.includes(injectedVersion)) {
|
|
54
|
+
packedSource = originalSource
|
|
55
|
+
} else {
|
|
56
|
+
throw new Error("BluetoothSdkDefaults.swift does not contain the expected SDK version placeholder.")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
await fs.writeFile(backupPath, originalSource)
|
|
60
|
+
|
|
61
|
+
if (packedSource !== originalSource) {
|
|
62
|
+
await fs.writeFile(sourcePath, packedSource)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log(`Injected iOS SDK version ${version} for npm packaging.`)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import assert from "node:assert/strict"
|
|
2
|
+
import {readFileSync} from "node:fs"
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import test from "node:test"
|
|
5
|
+
import {fileURLToPath} from "node:url"
|
|
6
|
+
|
|
7
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
|
|
8
|
+
|
|
9
|
+
test("publishes the supported OTA transport entrypoint", () => {
|
|
10
|
+
const manifest = JSON.parse(readFileSync(path.join(packageRoot, "package.json"), "utf8"))
|
|
11
|
+
assert.deepEqual(manifest.exports["./ota-transport"], {
|
|
12
|
+
"react-native": "./src/ota-transport/index.ts",
|
|
13
|
+
"types": "./build/ota-transport/index.d.ts",
|
|
14
|
+
"default": "./build/ota-transport/index.js",
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const source = readFileSync(path.join(packageRoot, "src/ota-transport/index.ts"), "utf8")
|
|
18
|
+
assert.match(source, /export const otaLocalNetwork/)
|
|
19
|
+
assert.match(source, /export const otaServer/)
|
|
20
|
+
assert.doesNotMatch(source, /export \{default as Glassly(LocalNetwork|OtaServer)/)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test("keeps restart signals and correlated OTA status on the public root", () => {
|
|
24
|
+
const source = readFileSync(path.join(packageRoot, "src/index.ts"), "utf8")
|
|
25
|
+
for (const required of [
|
|
26
|
+
'"glasses_session_changed"',
|
|
27
|
+
'"mtk_update_complete"',
|
|
28
|
+
"queryOtaStatus",
|
|
29
|
+
"subscribeGlassesStatus",
|
|
30
|
+
"subscribeBluetoothStatus",
|
|
31
|
+
"setSystemTime",
|
|
32
|
+
"ping",
|
|
33
|
+
]) {
|
|
34
|
+
assert.ok(source.includes(required), `missing public OTA primitive: ${required}`)
|
|
35
|
+
}
|
|
36
|
+
assert.match(source, /Unsupported BluetoothSdk event/)
|
|
37
|
+
})
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {readFileSync} from "node:fs"
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
|
|
5
|
+
function option(name, {required = true} = {}) {
|
|
6
|
+
const index = process.argv.indexOf(`--${name}`)
|
|
7
|
+
if (index < 0 || !process.argv[index + 1]) {
|
|
8
|
+
if (required) throw new Error(`Missing --${name}`)
|
|
9
|
+
return undefined
|
|
10
|
+
}
|
|
11
|
+
return process.argv[index + 1]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const packageRoot = path.resolve(option("package-root"))
|
|
15
|
+
const releaseIdentity = option("release-identity")
|
|
16
|
+
// Absent as a pair when the release carries no firmware pin.
|
|
17
|
+
const otaManifestUrl = option("ota-manifest-url", {required: false})
|
|
18
|
+
const otaManifestSha256 = option("ota-manifest-sha256", {required: false})
|
|
19
|
+
const packageJson = JSON.parse(readFileSync(path.join(packageRoot, "package.json"), "utf8"))
|
|
20
|
+
if (packageJson.version !== releaseIdentity) {
|
|
21
|
+
throw new Error(`Packed SDK version ${JSON.stringify(packageJson.version)} does not match ${releaseIdentity}`)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const files = [
|
|
25
|
+
"src/generated/releaseMetadata.ts",
|
|
26
|
+
"build/generated/releaseMetadata.js",
|
|
27
|
+
"android/src/main/java/com/glassly/bluetoothsdk/GeneratedReleaseMetadata.kt",
|
|
28
|
+
"ios/Source/GeneratedReleaseMetadata.swift",
|
|
29
|
+
]
|
|
30
|
+
// A release built without firmware records null OTA coordinates, so assert
|
|
31
|
+
// those were written rather than a stale pin.
|
|
32
|
+
const hasOta = Boolean(otaManifestUrl) || Boolean(otaManifestSha256)
|
|
33
|
+
for (const relativePath of files) {
|
|
34
|
+
const contents = readFileSync(path.join(packageRoot, relativePath), "utf8")
|
|
35
|
+
if (hasOta) {
|
|
36
|
+
if (!contents.includes(otaManifestUrl)) throw new Error(`${relativePath} does not contain the OTA manifest URL`)
|
|
37
|
+
if (!contents.includes(otaManifestSha256))
|
|
38
|
+
throw new Error(`${relativePath} does not contain the OTA manifest SHA-256`)
|
|
39
|
+
} else if (!/OTA_MANIFEST_URL[^\n]*null|otaManifestUrl[^\n]*null/i.test(contents)) {
|
|
40
|
+
throw new Error(`${relativePath} does not record a null OTA manifest URL`)
|
|
41
|
+
}
|
|
42
|
+
if (!contents.includes(releaseIdentity)) throw new Error(`${relativePath} does not contain the release identity`)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log(`Verified packed Bluetooth SDK ${releaseIdentity} metadata across JavaScript, Android, and iOS`)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {mkdirSync, writeFileSync} from "node:fs"
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import {fileURLToPath} from "node:url"
|
|
5
|
+
|
|
6
|
+
const STABLE_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/
|
|
7
|
+
const RELEASE_IDENTITY_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-(?:dev|beta)\.[1-9]\d*)?$/
|
|
8
|
+
const COMMIT_PATTERN = /^[0-9a-f]{40}$/
|
|
9
|
+
const SHA256_PATTERN = /^[0-9a-f]{64}$/
|
|
10
|
+
|
|
11
|
+
function validateHttpsUrl(value) {
|
|
12
|
+
let url
|
|
13
|
+
try {
|
|
14
|
+
url = new URL(value)
|
|
15
|
+
} catch {
|
|
16
|
+
throw new Error(`OTA manifest URL is invalid: ${JSON.stringify(value)}`)
|
|
17
|
+
}
|
|
18
|
+
if (url.protocol !== "https:" || url.username || url.password || url.hash) {
|
|
19
|
+
throw new Error("OTA manifest URL must be credential-free HTTPS without a fragment")
|
|
20
|
+
}
|
|
21
|
+
return url.toString()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function validateReleaseMetadata(input) {
|
|
25
|
+
if (!STABLE_VERSION_PATTERN.test(input.familyBaseVersion)) {
|
|
26
|
+
throw new Error("familyBaseVersion must be a plain X.Y.Z version")
|
|
27
|
+
}
|
|
28
|
+
if (!RELEASE_IDENTITY_PATTERN.test(input.releaseIdentity)) {
|
|
29
|
+
throw new Error("releaseIdentity must be X.Y.Z, X.Y.Z-dev.N, or X.Y.Z-beta.N")
|
|
30
|
+
}
|
|
31
|
+
if (
|
|
32
|
+
input.releaseIdentity !== input.familyBaseVersion &&
|
|
33
|
+
!input.releaseIdentity.startsWith(`${input.familyBaseVersion}-`)
|
|
34
|
+
) {
|
|
35
|
+
throw new Error("releaseIdentity does not belong to familyBaseVersion")
|
|
36
|
+
}
|
|
37
|
+
if (input.releaseSetId !== `glassly-${input.releaseIdentity}`) {
|
|
38
|
+
throw new Error("releaseSetId must be glassly-<releaseIdentity>")
|
|
39
|
+
}
|
|
40
|
+
if (!COMMIT_PATTERN.test(input.sourceCommit)) throw new Error("sourceCommit must be a full lowercase Git SHA")
|
|
41
|
+
// OTA coordinates are both-or-neither: a release without an OTA lane
|
|
42
|
+
// records null coordinates rather than fabricating a manifest.
|
|
43
|
+
const hasOta = input.otaManifestUrl != null || input.otaManifestSha256 != null
|
|
44
|
+
if (hasOta && !SHA256_PATTERN.test(input.otaManifestSha256)) {
|
|
45
|
+
throw new Error("otaManifestSha256 must be a lowercase SHA-256 digest")
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
schemaVersion: 1,
|
|
49
|
+
familyBaseVersion: input.familyBaseVersion,
|
|
50
|
+
releaseIdentity: input.releaseIdentity,
|
|
51
|
+
releaseSetId: input.releaseSetId,
|
|
52
|
+
sourceCommit: input.sourceCommit,
|
|
53
|
+
otaManifestUrl: hasOta ? validateHttpsUrl(input.otaManifestUrl) : null,
|
|
54
|
+
otaManifestSha256: hasOta ? input.otaManifestSha256 : null,
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function swiftString(value) {
|
|
59
|
+
return JSON.stringify(value)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function renderReleaseMetadata(input) {
|
|
63
|
+
const metadata = validateReleaseMetadata(input)
|
|
64
|
+
const typescript = [
|
|
65
|
+
"/** Generated by release CI. Do not edit in a release checkout. */",
|
|
66
|
+
"export interface BluetoothSdkReleaseMetadata {",
|
|
67
|
+
" schemaVersion: 1",
|
|
68
|
+
" familyBaseVersion: string | null",
|
|
69
|
+
" releaseIdentity: string | null",
|
|
70
|
+
" releaseSetId: string | null",
|
|
71
|
+
" sourceCommit: string | null",
|
|
72
|
+
" otaManifestUrl: string | null",
|
|
73
|
+
" otaManifestSha256: string | null",
|
|
74
|
+
"}",
|
|
75
|
+
"",
|
|
76
|
+
`export const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze(${JSON.stringify(
|
|
77
|
+
metadata,
|
|
78
|
+
null,
|
|
79
|
+
2,
|
|
80
|
+
)})`,
|
|
81
|
+
"",
|
|
82
|
+
].join("\n")
|
|
83
|
+
const kotlin = [
|
|
84
|
+
"package com.glassly.bluetoothsdk",
|
|
85
|
+
"",
|
|
86
|
+
"/** Generated by release CI. Do not edit in a release checkout. */",
|
|
87
|
+
"internal object GeneratedReleaseMetadata {",
|
|
88
|
+
` const val FAMILY_BASE_VERSION: String = ${JSON.stringify(metadata.familyBaseVersion)}`,
|
|
89
|
+
` const val RELEASE_IDENTITY: String = ${JSON.stringify(metadata.releaseIdentity)}`,
|
|
90
|
+
` const val RELEASE_SET_ID: String = ${JSON.stringify(metadata.releaseSetId)}`,
|
|
91
|
+
` const val SOURCE_COMMIT: String = ${JSON.stringify(metadata.sourceCommit)}`,
|
|
92
|
+
` const val OTA_MANIFEST_URL: String = ${JSON.stringify(metadata.otaManifestUrl)}`,
|
|
93
|
+
` const val OTA_MANIFEST_SHA256: String = ${JSON.stringify(metadata.otaManifestSha256)}`,
|
|
94
|
+
"}",
|
|
95
|
+
"",
|
|
96
|
+
].join("\n")
|
|
97
|
+
const swift = [
|
|
98
|
+
"import Foundation",
|
|
99
|
+
"",
|
|
100
|
+
"/// Generated by release CI. Do not edit in a release checkout.",
|
|
101
|
+
"enum GeneratedReleaseMetadata {",
|
|
102
|
+
` static let familyBaseVersion = ${swiftString(metadata.familyBaseVersion)}`,
|
|
103
|
+
` static let releaseIdentity = ${swiftString(metadata.releaseIdentity)}`,
|
|
104
|
+
` static let releaseSetId = ${swiftString(metadata.releaseSetId)}`,
|
|
105
|
+
` static let sourceCommit = ${swiftString(metadata.sourceCommit)}`,
|
|
106
|
+
` static let otaManifestUrl = ${swiftString(metadata.otaManifestUrl)}`,
|
|
107
|
+
` static let otaManifestSha256 = ${swiftString(metadata.otaManifestSha256)}`,
|
|
108
|
+
"}",
|
|
109
|
+
"",
|
|
110
|
+
].join("\n")
|
|
111
|
+
return {metadata, typescript, kotlin, swift}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function parseArgs(args) {
|
|
115
|
+
const values = {}
|
|
116
|
+
for (let index = 0; index < args.length; index += 2) {
|
|
117
|
+
const option = args[index]
|
|
118
|
+
const value = args[index + 1]
|
|
119
|
+
if (!option?.startsWith("--") || value === undefined) throw new Error("Expected --name value pairs")
|
|
120
|
+
values[option.slice(2)] = value
|
|
121
|
+
}
|
|
122
|
+
return values
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function main() {
|
|
126
|
+
const args = parseArgs(process.argv.slice(2))
|
|
127
|
+
const required = ["family-base-version", "release-identity", "release-set-id", "source-commit"]
|
|
128
|
+
for (const field of required) if (!args[field]) throw new Error(`Missing --${field}`)
|
|
129
|
+
// --ota-manifest-url/--ota-manifest-sha256 are optional as a pair (absent
|
|
130
|
+
// when the OTA lane is disabled); validateReleaseMetadata enforces the rest.
|
|
131
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
|
|
132
|
+
const rendered = renderReleaseMetadata({
|
|
133
|
+
familyBaseVersion: args["family-base-version"],
|
|
134
|
+
releaseIdentity: args["release-identity"],
|
|
135
|
+
releaseSetId: args["release-set-id"],
|
|
136
|
+
sourceCommit: args["source-commit"],
|
|
137
|
+
otaManifestUrl: args["ota-manifest-url"],
|
|
138
|
+
otaManifestSha256: args["ota-manifest-sha256"],
|
|
139
|
+
})
|
|
140
|
+
const outputs = {
|
|
141
|
+
typescript: path.join(packageRoot, "src/generated/releaseMetadata.ts"),
|
|
142
|
+
kotlin: path.join(packageRoot, "android/src/main/java/com/glassly/bluetoothsdk/GeneratedReleaseMetadata.kt"),
|
|
143
|
+
swift: path.join(packageRoot, "ios/Source/GeneratedReleaseMetadata.swift"),
|
|
144
|
+
}
|
|
145
|
+
for (const [target, file] of Object.entries(outputs)) {
|
|
146
|
+
mkdirSync(path.dirname(file), {recursive: true})
|
|
147
|
+
writeFileSync(file, rendered[target])
|
|
148
|
+
}
|
|
149
|
+
console.log(`Wrote Bluetooth SDK release metadata for ${rendered.metadata.releaseSetId}`)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) main()
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import assert from "node:assert/strict"
|
|
2
|
+
import test from "node:test"
|
|
3
|
+
|
|
4
|
+
import {renderReleaseMetadata, validateReleaseMetadata} from "./write-release-metadata.mjs"
|
|
5
|
+
|
|
6
|
+
const input = {
|
|
7
|
+
familyBaseVersion: "3.1.0",
|
|
8
|
+
releaseIdentity: "3.1.0-beta.57",
|
|
9
|
+
releaseSetId: "glassly-3.1.0-beta.57",
|
|
10
|
+
sourceCommit: "a".repeat(40),
|
|
11
|
+
otaManifestUrl:
|
|
12
|
+
"https://github.com/tetramo-labs/glassly/releases/download/glassly-3.1.0-beta.57/mentra-live-ota-3.1.0-beta.57.json",
|
|
13
|
+
otaManifestSha256: "b".repeat(64),
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
test("renders identical immutable metadata for TypeScript, Kotlin, and Swift", () => {
|
|
17
|
+
const rendered = renderReleaseMetadata(input)
|
|
18
|
+
for (const contents of [rendered.typescript, rendered.kotlin, rendered.swift]) {
|
|
19
|
+
assert.match(contents, /3\.1\.0-beta\.57/)
|
|
20
|
+
assert.match(contents, /mentra-live-ota-3\.1\.0-beta\.57\.json/)
|
|
21
|
+
assert.match(contents, new RegExp("b".repeat(64)))
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test("rejects mutable or cross-family release metadata", () => {
|
|
26
|
+
assert.throws(() => validateReleaseMetadata({...input, releaseIdentity: "3.2.0-beta.57"}), /does not belong/)
|
|
27
|
+
assert.throws(() => validateReleaseMetadata({...input, otaManifestUrl: "http://example.com/version.json"}), /HTTPS/)
|
|
28
|
+
assert.throws(() => validateReleaseMetadata({...input, otaManifestSha256: "short"}), /SHA-256/)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test("records null OTA coordinates when the OTA lane is absent", () => {
|
|
32
|
+
const metadata = validateReleaseMetadata({...input, otaManifestUrl: undefined, otaManifestSha256: undefined})
|
|
33
|
+
assert.equal(metadata.otaManifestUrl, null)
|
|
34
|
+
assert.equal(metadata.otaManifestSha256, null)
|
|
35
|
+
// Both-or-neither: half a coordinate pair is still rejected.
|
|
36
|
+
assert.throws(() => validateReleaseMetadata({...input, otaManifestSha256: undefined}), /SHA-256/)
|
|
37
|
+
})
|