@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.
Files changed (548) hide show
  1. package/README.md +563 -0
  2. package/android/build.gradle +450 -0
  3. package/android/gradle.properties.example +9 -0
  4. package/android/lc3Lib/CMakeLists.txt +6 -0
  5. package/android/lc3Lib/build.gradle +212 -0
  6. package/android/lc3Lib/proguard-rules.pro +33 -0
  7. package/android/lc3Lib/src/main/AndroidManifest.xml +2 -0
  8. package/android/lc3Lib/src/main/cpp/CMakeLists.txt +8 -0
  9. package/android/lc3Lib/src/main/cpp/google_opus_stuff/CMakeLists.txt +30 -0
  10. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/CMakeLists.txt +7 -0
  11. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.cc +96 -0
  12. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.h +53 -0
  13. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/Makefile.am +6 -0
  14. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h +26 -0
  15. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h.in +26 -0
  16. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/ogg.h +209 -0
  17. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/os_types.h +158 -0
  18. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus.h +981 -0
  19. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_custom.h +342 -0
  20. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_defines.h +799 -0
  21. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_multistream.h +660 -0
  22. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_projection.h +568 -0
  23. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_types.h +166 -0
  24. package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.cc +268 -0
  25. package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.h +115 -0
  26. package/android/lc3Lib/src/main/cpp/google_opus_stuff/opus_tools/opus_header.h +59 -0
  27. package/android/lc3Lib/src/main/cpp/liblc3/CMakeLists.txt +38 -0
  28. package/android/lc3Lib/src/main/cpp/liblc3/include/lc3.h +309 -0
  29. package/android/lc3Lib/src/main/cpp/liblc3/include/lc3_private.h +162 -0
  30. package/android/lc3Lib/src/main/cpp/liblc3/include/rnnoise.h +114 -0
  31. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/CMakeLists.txt +19 -0
  32. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.c +92 -0
  33. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.h +44 -0
  34. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.c +375 -0
  35. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.h +315 -0
  36. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.c +129 -0
  37. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.h +69 -0
  38. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/common.h +148 -0
  39. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.c +70 -0
  40. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.h +43 -0
  41. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/fastmath.h +158 -0
  42. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/lc3.c +702 -0
  43. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.c +893 -0
  44. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.h +111 -0
  45. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_arm.h +506 -0
  46. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_neon.h +281 -0
  47. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/makefile.mk +35 -0
  48. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.c +452 -0
  49. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.h +57 -0
  50. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct_neon.h +296 -0
  51. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/meson.build +46 -0
  52. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.c +61 -0
  53. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.h +57 -0
  54. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.c +880 -0
  55. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.h +103 -0
  56. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.c +904 -0
  57. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.h +119 -0
  58. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.c +3457 -0
  59. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.h +94 -0
  60. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.c +457 -0
  61. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.h +99 -0
  62. package/android/lc3Lib/src/main/cpp/liblc3/liblc3.cpp +159 -0
  63. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/_kiss_fft_guts.h +182 -0
  64. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/arch.h +261 -0
  65. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.c +279 -0
  66. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.h +59 -0
  67. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/common.h +48 -0
  68. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/compile.sh +3 -0
  69. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/denoise.c +646 -0
  70. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.c +601 -0
  71. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.h +203 -0
  72. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/opus_types.h +159 -0
  73. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.c +526 -0
  74. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.h +149 -0
  75. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.c +178 -0
  76. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.h +69 -0
  77. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.c +11051 -0
  78. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.h +34 -0
  79. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_reader.c +168 -0
  80. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_train.py +66 -0
  81. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/tansig_table.h +45 -0
  82. package/android/lc3Lib/src/main/java/com/glassly/lc3Lib/Lc3Cpp.java +38 -0
  83. package/android/lc3Lib/third_party/CMakeLists.txt +23 -0
  84. package/android/lc3Lib/third_party/CMakeLists_libogg.txt +18 -0
  85. package/android/lc3Lib/third_party/CMakeLists_libopus.txt +18 -0
  86. package/android/lc3Lib/third_party/CMakeLists_opus-tools.txt +23 -0
  87. package/android/lc3Lib/third_party/opus_tools/src/AUTHORS +5 -0
  88. package/android/lc3Lib/third_party/opus_tools/src/CMakeLists.txt +4 -0
  89. package/android/lc3Lib/third_party/opus_tools/src/COPYING +371 -0
  90. package/android/lc3Lib/third_party/opus_tools/src/ChangeLog +3 -0
  91. package/android/lc3Lib/third_party/opus_tools/src/Makefile.am +42 -0
  92. package/android/lc3Lib/third_party/opus_tools/src/Makefile.unix +23 -0
  93. package/android/lc3Lib/third_party/opus_tools/src/NEWS +0 -0
  94. package/android/lc3Lib/third_party/opus_tools/src/README +0 -0
  95. package/android/lc3Lib/third_party/opus_tools/src/autogen.sh +115 -0
  96. package/android/lc3Lib/third_party/opus_tools/src/configure.ac +293 -0
  97. package/android/lc3Lib/third_party/opus_tools/src/src/arch.h +239 -0
  98. package/android/lc3Lib/third_party/opus_tools/src/src/audio-in.c +1046 -0
  99. package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.c +245 -0
  100. package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.h +28 -0
  101. package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.c +320 -0
  102. package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.h +51 -0
  103. package/android/lc3Lib/third_party/opus_tools/src/src/lpc.c +157 -0
  104. package/android/lc3Lib/third_party/opus_tools/src/src/lpc.h +27 -0
  105. package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.c +286 -0
  106. package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.h +59 -0
  107. package/android/lc3Lib/third_party/opus_tools/src/src/opusdec.c +884 -0
  108. package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.c +1021 -0
  109. package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.h +101 -0
  110. package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.c +639 -0
  111. package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.h +51 -0
  112. package/android/lc3Lib/third_party/opus_tools/src/src/os_support.h +167 -0
  113. package/android/lc3Lib/third_party/opus_tools/src/src/resample.c +1137 -0
  114. package/android/lc3Lib/third_party/opus_tools/src/src/speex_resampler.h +344 -0
  115. package/android/lc3Lib/third_party/opus_tools/src/src/stack_alloc.h +115 -0
  116. package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.c +125 -0
  117. package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.h +62 -0
  118. package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.c +223 -0
  119. package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.h +60 -0
  120. package/android/settings.gradle +4 -0
  121. package/android/silero/LICENSE.md +17 -0
  122. package/android/silero/build.gradle +50 -0
  123. package/android/silero/proguard-rules.pro +24 -0
  124. package/android/silero/src/androidTest/assets/hello.wav +0 -0
  125. package/android/silero/src/androidTest/java/com/konovalov/vad/silero/VadSileroTest.kt +79 -0
  126. package/android/silero/src/main/assets/LICENSE +21 -0
  127. package/android/silero/src/main/assets/silero_vad.onnx +0 -0
  128. package/android/silero/src/main/java/com/konovalov/vad/silero/Vad.kt +160 -0
  129. package/android/silero/src/main/java/com/konovalov/vad/silero/VadSilero.kt +449 -0
  130. package/android/silero/src/main/java/com/konovalov/vad/silero/config/FrameSize.kt +15 -0
  131. package/android/silero/src/main/java/com/konovalov/vad/silero/config/Mode.kt +14 -0
  132. package/android/silero/src/main/java/com/konovalov/vad/silero/config/SampleRate.kt +12 -0
  133. package/android/silero/src/main/java/com/konovalov/vad/silero/utils/AudioUtils.kt +47 -0
  134. package/android/silero/src/main/java/com/konovalov/vad/silero/utils/TensorMap.kt +41 -0
  135. package/android/silero/src/test/java/com/konovalov/vad/silero/utils/AudioUtilsTest.kt +44 -0
  136. package/android/src/main/AndroidManifest.xml +42 -0
  137. package/android/src/main/assets/G2Firmware/README.md +11 -0
  138. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdk.kt +2325 -0
  139. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkAnalytics.kt +216 -0
  140. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDebug.kt +14 -0
  141. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkDefaults.kt +7 -0
  142. package/android/src/main/java/com/glassly/bluetoothsdk/BluetoothSdkModule.kt +1088 -0
  143. package/android/src/main/java/com/glassly/bluetoothsdk/Bridge.kt +953 -0
  144. package/android/src/main/java/com/glassly/bluetoothsdk/DeviceManager.kt +2528 -0
  145. package/android/src/main/java/com/glassly/bluetoothsdk/DeviceStore.kt +360 -0
  146. package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedChangelogCatalog.kt +8 -0
  147. package/android/src/main/java/com/glassly/bluetoothsdk/GeneratedReleaseMetadata.kt +11 -0
  148. package/android/src/main/java/com/glassly/bluetoothsdk/LocalNetworkModule.kt +414 -0
  149. package/android/src/main/java/com/glassly/bluetoothsdk/ObservableStore.kt +88 -0
  150. package/android/src/main/java/com/glassly/bluetoothsdk/OtaManifest.kt +191 -0
  151. package/android/src/main/java/com/glassly/bluetoothsdk/ReleaseChangelog.kt +61 -0
  152. package/android/src/main/java/com/glassly/bluetoothsdk/ScopedNetworkReadiness.kt +17 -0
  153. package/android/src/main/java/com/glassly/bluetoothsdk/audio/AudioModels.kt +144 -0
  154. package/android/src/main/java/com/glassly/bluetoothsdk/camera/CameraModels.kt +486 -0
  155. package/android/src/main/java/com/glassly/bluetoothsdk/connection/ConnectionModels.kt +78 -0
  156. package/android/src/main/java/com/glassly/bluetoothsdk/controllers/ControllerManager.kt +158 -0
  157. package/android/src/main/java/com/glassly/bluetoothsdk/controllers/R1.kt +937 -0
  158. package/android/src/main/java/com/glassly/bluetoothsdk/debug/BleTraceLogger.kt +165 -0
  159. package/android/src/main/java/com/glassly/bluetoothsdk/events/BluetoothEvents.kt +178 -0
  160. package/android/src/main/java/com/glassly/bluetoothsdk/internal/MapParsing.kt +140 -0
  161. package/android/src/main/java/com/glassly/bluetoothsdk/net/LocalIpv4.kt +57 -0
  162. package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServer.kt +304 -0
  163. package/android/src/main/java/com/glassly/bluetoothsdk/otaserver/OtaServerModule.kt +120 -0
  164. package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistry.java +108 -0
  165. package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoUploadServer.kt +622 -0
  166. package/android/src/main/java/com/glassly/bluetoothsdk/photoreceiver/PhotoReceiverModule.kt +156 -0
  167. package/android/src/main/java/com/glassly/bluetoothsdk/requests/DisplayRequests.kt +56 -0
  168. package/android/src/main/java/com/glassly/bluetoothsdk/services/Foreground.kt +272 -0
  169. package/android/src/main/java/com/glassly/bluetoothsdk/services/PhoneMic.kt +1195 -0
  170. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Ar99.java +2653 -0
  171. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuard.kt +49 -0
  172. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapper.kt +27 -0
  173. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1.kt +3878 -0
  174. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizer.kt +38 -0
  175. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2.kt +6428 -0
  176. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassification.kt +49 -0
  177. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwRenderer.kt +1241 -0
  178. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCache.kt +270 -0
  179. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocol.kt +291 -0
  180. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/G2Flasher.kt +411 -0
  181. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/GlasslyBle.java +43189 -0
  182. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Mach1.kt +1280 -0
  183. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLive.kt +10817 -0
  184. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLiveL2capChannel.kt +274 -0
  185. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisement.kt +54 -0
  186. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/MentraNex.kt +2011 -0
  187. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Nimo.kt +2532 -0
  188. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/SGCManager.kt +470 -0
  189. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/Simulated.kt +228 -0
  190. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/Ar99OtaManager.java +566 -0
  191. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaByteUtils.java +18 -0
  192. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCommandConstants.java +35 -0
  193. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaCrc32Util.java +13 -0
  194. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaGattTransport.java +11 -0
  195. package/android/src/main/java/com/glassly/bluetoothsdk/sgcs/ar99/ota/OtaProtocol.java +92 -0
  196. package/android/src/main/java/com/glassly/bluetoothsdk/speakerid/SpeakerIdEngine.kt +525 -0
  197. package/android/src/main/java/com/glassly/bluetoothsdk/status/DeviceStatus.kt +669 -0
  198. package/android/src/main/java/com/glassly/bluetoothsdk/status/RuntimeState.kt +201 -0
  199. package/android/src/main/java/com/glassly/bluetoothsdk/status/WifiHotspotStatus.kt +189 -0
  200. package/android/src/main/java/com/glassly/bluetoothsdk/streaming/StreamModels.kt +518 -0
  201. package/android/src/main/java/com/glassly/bluetoothsdk/stt/STTTools.kt +391 -0
  202. package/android/src/main/java/com/glassly/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +518 -0
  203. package/android/src/main/java/com/glassly/bluetoothsdk/stt/VadGateSpeechPolicy.kt +229 -0
  204. package/android/src/main/java/com/glassly/bluetoothsdk/tts/TTSTools.kt +248 -0
  205. package/android/src/main/java/com/glassly/bluetoothsdk/types/DeviceModels.kt +96 -0
  206. package/android/src/main/java/com/glassly/bluetoothsdk/utils/AES.java +106 -0
  207. package/android/src/main/java/com/glassly/bluetoothsdk/utils/AudioSessionMonitor.kt +189 -0
  208. package/android/src/main/java/com/glassly/bluetoothsdk/utils/AvifExifStripper.java +573 -0
  209. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BitmapJavaUtils.java +169 -0
  210. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleJsonCompact.java +496 -0
  211. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadService.java +677 -0
  212. package/android/src/main/java/com/glassly/bluetoothsdk/utils/BleWireProtocol.java +108 -0
  213. package/android/src/main/java/com/glassly/bluetoothsdk/utils/Constants.kt +46 -0
  214. package/android/src/main/java/com/glassly/bluetoothsdk/utils/G1Text.kt +436 -0
  215. package/android/src/main/java/com/glassly/bluetoothsdk/utils/HeifExifTagReader.java +199 -0
  216. package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleRelayNaming.java +29 -0
  217. package/android/src/main/java/com/glassly/bluetoothsdk/utils/IncidentLogBleUploadService.java +77 -0
  218. package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900LengthCodec.java +115 -0
  219. package/android/src/main/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtils.java +827 -0
  220. package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunkReassembler.java +228 -0
  221. package/android/src/main/java/com/glassly/bluetoothsdk/utils/MessageChunker.java +325 -0
  222. package/android/src/main/java/com/glassly/bluetoothsdk/utils/NexSGCUtils.kt +698 -0
  223. package/android/src/main/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitor.kt +348 -0
  224. package/android/src/main/java/com/glassly/bluetoothsdk/utils/SmartGlassesConnectionState.java +9 -0
  225. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Ar99OpusPcmDecoder.java +398 -0
  226. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/ByteUtilAudioPlayer.java +655 -0
  227. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/Lc3Player.java +441 -0
  228. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PCMAudioPlayer.java +431 -0
  229. package/android/src/main/java/com/glassly/bluetoothsdk/utils/audio/PcmStreamPlayer.kt +328 -0
  230. package/android/src/main/res/values/strings.xml +4 -0
  231. package/android/src/test/java/com/glassly/bluetoothsdk/BluetoothSdkExceptionTest.kt +18 -0
  232. package/android/src/test/java/com/glassly/bluetoothsdk/OtaManifestDowngradeTest.kt +86 -0
  233. package/android/src/test/java/com/glassly/bluetoothsdk/OtaStartResponsePolicyTest.kt +30 -0
  234. package/android/src/test/java/com/glassly/bluetoothsdk/ReleaseChangelogTest.kt +13 -0
  235. package/android/src/test/java/com/glassly/bluetoothsdk/ScopedNetworkReadinessTest.kt +39 -0
  236. package/android/src/test/java/com/glassly/bluetoothsdk/StreamStatusEventTest.kt +29 -0
  237. package/android/src/test/java/com/glassly/bluetoothsdk/camera/PhotoRequestTest.kt +141 -0
  238. package/android/src/test/java/com/glassly/bluetoothsdk/otaserver/LocalOtaServerTest.kt +82 -0
  239. package/android/src/test/java/com/glassly/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistryTest.java +75 -0
  240. package/android/src/test/java/com/glassly/bluetoothsdk/services/ForegroundServiceTypeTest.kt +69 -0
  241. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/Ar99AdvertisementMatcherTest.java +22 -0
  242. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaHeartbeatGuardTest.kt +73 -0
  243. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/BesOtaProgressMapperTest.kt +67 -0
  244. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/EvenRleTest.kt +63 -0
  245. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G1TextSanitizerTest.kt +31 -0
  246. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwClassificationTest.kt +89 -0
  247. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwRendererTest.kt +344 -0
  248. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2CfwTextureCacheTest.kt +200 -0
  249. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/G2FlashProtocolTest.kt +131 -0
  250. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLiveGattCharacteristicsTest.kt +39 -0
  251. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/MentraLivePairingAdvertisementParserTest.kt +133 -0
  252. package/android/src/test/java/com/glassly/bluetoothsdk/sgcs/NimoProtocolTest.kt +333 -0
  253. package/android/src/test/java/com/glassly/bluetoothsdk/utils/AvifExifStripperTest.java +46 -0
  254. package/android/src/test/java/com/glassly/bluetoothsdk/utils/BinaryMessageChunkerTest.java +84 -0
  255. package/android/src/test/java/com/glassly/bluetoothsdk/utils/BleJsonCompactTest.java +319 -0
  256. package/android/src/test/java/com/glassly/bluetoothsdk/utils/BlePhotoUploadServiceTest.java +107 -0
  257. package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsEndiannessTest.java +172 -0
  258. package/android/src/test/java/com/glassly/bluetoothsdk/utils/K900ProtocolUtilsTest.java +24 -0
  259. package/android/src/test/java/com/glassly/bluetoothsdk/utils/PhoneAudioMonitorTest.kt +45 -0
  260. package/android/src/test/resources/avif_with_exif.avif +0 -0
  261. package/app.plugin.js +3 -0
  262. package/build/BluetoothSdk.types.d.ts +1354 -0
  263. package/build/BluetoothSdk.types.d.ts.map +1 -0
  264. package/build/BluetoothSdk.types.js +41 -0
  265. package/build/BluetoothSdk.types.js.map +1 -0
  266. package/build/_internal.d.ts +17 -0
  267. package/build/_internal.d.ts.map +1 -0
  268. package/build/_internal.js +16 -0
  269. package/build/_internal.js.map +1 -0
  270. package/build/_private/BluetoothSdkModule.d.ts +172 -0
  271. package/build/_private/BluetoothSdkModule.d.ts.map +1 -0
  272. package/build/_private/BluetoothSdkModule.js +300 -0
  273. package/build/_private/BluetoothSdkModule.js.map +1 -0
  274. package/build/_private/LocalNetworkModule.d.ts +38 -0
  275. package/build/_private/LocalNetworkModule.d.ts.map +1 -0
  276. package/build/_private/LocalNetworkModule.js +3 -0
  277. package/build/_private/LocalNetworkModule.js.map +1 -0
  278. package/build/_private/cameraRequestPayload.d.ts +4 -0
  279. package/build/_private/cameraRequestPayload.d.ts.map +1 -0
  280. package/build/_private/cameraRequestPayload.js +32 -0
  281. package/build/_private/cameraRequestPayload.js.map +1 -0
  282. package/build/_private/photoRequestPayload.d.ts +6 -0
  283. package/build/_private/photoRequestPayload.d.ts.map +1 -0
  284. package/build/_private/photoRequestPayload.js +86 -0
  285. package/build/_private/photoRequestPayload.js.map +1 -0
  286. package/build/_private/sdkOtaManifest.d.ts +11 -0
  287. package/build/_private/sdkOtaManifest.d.ts.map +1 -0
  288. package/build/_private/sdkOtaManifest.js +15 -0
  289. package/build/_private/sdkOtaManifest.js.map +1 -0
  290. package/build/changelogs.d.ts +7 -0
  291. package/build/changelogs.d.ts.map +1 -0
  292. package/build/changelogs.js +46 -0
  293. package/build/changelogs.js.map +1 -0
  294. package/build/debug.d.ts +3 -0
  295. package/build/debug.d.ts.map +1 -0
  296. package/build/debug.js +8 -0
  297. package/build/debug.js.map +1 -0
  298. package/build/generated/changelogCatalog.d.ts +9 -0
  299. package/build/generated/changelogCatalog.d.ts.map +1 -0
  300. package/build/generated/changelogCatalog.js +12 -0
  301. package/build/generated/changelogCatalog.js.map +1 -0
  302. package/build/generated/releaseMetadata.d.ts +12 -0
  303. package/build/generated/releaseMetadata.d.ts.map +1 -0
  304. package/build/generated/releaseMetadata.js +10 -0
  305. package/build/generated/releaseMetadata.js.map +1 -0
  306. package/build/index.d.ts +6 -0
  307. package/build/index.d.ts.map +1 -0
  308. package/build/index.js +171 -0
  309. package/build/index.js.map +1 -0
  310. package/build/ota-server/OtaServer.types.d.ts +14 -0
  311. package/build/ota-server/OtaServer.types.d.ts.map +1 -0
  312. package/build/ota-server/OtaServer.types.js +2 -0
  313. package/build/ota-server/OtaServer.types.js.map +1 -0
  314. package/build/ota-server/OtaServerModule.d.ts +21 -0
  315. package/build/ota-server/OtaServerModule.d.ts.map +1 -0
  316. package/build/ota-server/OtaServerModule.js +3 -0
  317. package/build/ota-server/OtaServerModule.js.map +1 -0
  318. package/build/ota-server/OtaServerModule.web.d.ts +10 -0
  319. package/build/ota-server/OtaServerModule.web.d.ts.map +1 -0
  320. package/build/ota-server/OtaServerModule.web.js +12 -0
  321. package/build/ota-server/OtaServerModule.web.js.map +1 -0
  322. package/build/ota-server/index.d.ts +3 -0
  323. package/build/ota-server/index.d.ts.map +1 -0
  324. package/build/ota-server/index.js +3 -0
  325. package/build/ota-server/index.js.map +1 -0
  326. package/build/ota-transport/index.d.ts +67 -0
  327. package/build/ota-transport/index.d.ts.map +1 -0
  328. package/build/ota-transport/index.js +58 -0
  329. package/build/ota-transport/index.js.map +1 -0
  330. package/build/photo-receiver/PhotoReceiver.types.d.ts +18 -0
  331. package/build/photo-receiver/PhotoReceiver.types.d.ts.map +1 -0
  332. package/build/photo-receiver/PhotoReceiver.types.js +2 -0
  333. package/build/photo-receiver/PhotoReceiver.types.js.map +1 -0
  334. package/build/photo-receiver/PhotoReceiverModule.d.ts +10 -0
  335. package/build/photo-receiver/PhotoReceiverModule.d.ts.map +1 -0
  336. package/build/photo-receiver/PhotoReceiverModule.js +3 -0
  337. package/build/photo-receiver/PhotoReceiverModule.js.map +1 -0
  338. package/build/photo-receiver/PhotoReceiverModule.web.d.ts +10 -0
  339. package/build/photo-receiver/PhotoReceiverModule.web.d.ts.map +1 -0
  340. package/build/photo-receiver/PhotoReceiverModule.web.js +12 -0
  341. package/build/photo-receiver/PhotoReceiverModule.web.js.map +1 -0
  342. package/build/photo-receiver/index.d.ts +3 -0
  343. package/build/photo-receiver/index.d.ts.map +1 -0
  344. package/build/photo-receiver/index.js +3 -0
  345. package/build/photo-receiver/index.js.map +1 -0
  346. package/build/react/index.d.ts +5 -0
  347. package/build/react/index.d.ts.map +1 -0
  348. package/build/react/index.js +4 -0
  349. package/build/react/index.js.map +1 -0
  350. package/build/react/useBluetooth.d.ts +100 -0
  351. package/build/react/useBluetooth.d.ts.map +1 -0
  352. package/build/react/useBluetooth.js +167 -0
  353. package/build/react/useBluetooth.js.map +1 -0
  354. package/build/react/useBluetoothEvent.d.ts +6 -0
  355. package/build/react/useBluetoothEvent.d.ts.map +1 -0
  356. package/build/react/useBluetoothEvent.js +21 -0
  357. package/build/react/useBluetoothEvent.js.map +1 -0
  358. package/build/react/useBluetoothScan.d.ts +22 -0
  359. package/build/react/useBluetoothScan.d.ts.map +1 -0
  360. package/build/react/useBluetoothScan.js +135 -0
  361. package/build/react/useBluetoothScan.js.map +1 -0
  362. package/build/react/useBluetoothStatus.d.ts +16 -0
  363. package/build/react/useBluetoothStatus.d.ts.map +1 -0
  364. package/build/react/useBluetoothStatus.js +137 -0
  365. package/build/react/useBluetoothStatus.js.map +1 -0
  366. package/build/react/useGlassesConnection.d.ts +29 -0
  367. package/build/react/useGlassesConnection.d.ts.map +1 -0
  368. package/build/react/useGlassesConnection.js +153 -0
  369. package/build/react/useGlassesConnection.js.map +1 -0
  370. package/build/types/index.d.ts +3 -0
  371. package/build/types/index.d.ts.map +1 -0
  372. package/build/types/index.js +2 -0
  373. package/build/types/index.js.map +1 -0
  374. package/expo-module.config.json +14 -0
  375. package/ios/BackgroundOtaArtifactDownloader.swift +125 -0
  376. package/ios/BluetoothSdkModule.swift +1034 -0
  377. package/ios/GlasslyBluetoothSDK.podspec +106 -0
  378. package/ios/LocalIPv4.swift +150 -0
  379. package/ios/LocalOtaServer.swift +309 -0
  380. package/ios/LocalPhotoUploadServer.swift +754 -0
  381. package/ios/OtaServerModule.swift +147 -0
  382. package/ios/Packages/CoreObjC/CoreObjC.xcodeproj/project.pbxproj +213 -0
  383. package/ios/Packages/CoreObjC/PcmConverter.h +22 -0
  384. package/ios/Packages/CoreObjC/PcmConverter.m +266 -0
  385. package/ios/Packages/CoreObjC/attdet.c +92 -0
  386. package/ios/Packages/CoreObjC/attdet.h +44 -0
  387. package/ios/Packages/CoreObjC/bits.c +375 -0
  388. package/ios/Packages/CoreObjC/bits.h +315 -0
  389. package/ios/Packages/CoreObjC/bwdet.c +129 -0
  390. package/ios/Packages/CoreObjC/bwdet.h +69 -0
  391. package/ios/Packages/CoreObjC/common.h +151 -0
  392. package/ios/Packages/CoreObjC/energy.c +70 -0
  393. package/ios/Packages/CoreObjC/energy.h +43 -0
  394. package/ios/Packages/CoreObjC/fastmath.h +158 -0
  395. package/ios/Packages/CoreObjC/include/PcmConverter.h +22 -0
  396. package/ios/Packages/CoreObjC/lc3.c +704 -0
  397. package/ios/Packages/CoreObjC/lc3.h +313 -0
  398. package/ios/Packages/CoreObjC/lc3_cpp.h +283 -0
  399. package/ios/Packages/CoreObjC/lc3_private.h +163 -0
  400. package/ios/Packages/CoreObjC/ltpf.c +905 -0
  401. package/ios/Packages/CoreObjC/ltpf.h +111 -0
  402. package/ios/Packages/CoreObjC/ltpf_arm.h +506 -0
  403. package/ios/Packages/CoreObjC/ltpf_neon.h +281 -0
  404. package/ios/Packages/CoreObjC/makefile.mk +35 -0
  405. package/ios/Packages/CoreObjC/mdct.c +469 -0
  406. package/ios/Packages/CoreObjC/mdct.h +57 -0
  407. package/ios/Packages/CoreObjC/mdct_neon.h +296 -0
  408. package/ios/Packages/CoreObjC/meson.build +61 -0
  409. package/ios/Packages/CoreObjC/plc.c +61 -0
  410. package/ios/Packages/CoreObjC/plc.h +57 -0
  411. package/ios/Packages/CoreObjC/rnnoise.h +114 -0
  412. package/ios/Packages/CoreObjC/sns.c +880 -0
  413. package/ios/Packages/CoreObjC/sns.h +103 -0
  414. package/ios/Packages/CoreObjC/spec.c +907 -0
  415. package/ios/Packages/CoreObjC/spec.h +119 -0
  416. package/ios/Packages/CoreObjC/tables.c +3457 -0
  417. package/ios/Packages/CoreObjC/tables.h +94 -0
  418. package/ios/Packages/CoreObjC/tns.c +457 -0
  419. package/ios/Packages/CoreObjC/tns.h +99 -0
  420. package/ios/Packages/SherpaOnnx/Model/joiner.onnx +0 -0
  421. package/ios/Packages/SherpaOnnx/Model/tokens.txt +502 -0
  422. package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +2383 -0
  423. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +48 -0
  424. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
  425. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
  426. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
  427. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/c-api.h +4689 -0
  428. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/cxx-api.h +2036 -0
  429. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
  430. package/ios/Packages/libbz2/module.modulemap +5 -0
  431. package/ios/Packages/libbz2/shim.h +1 -0
  432. package/ios/PhotoReceiverModule.swift +129 -0
  433. package/ios/Source/BluetoothSDK.swift +2303 -0
  434. package/ios/Source/BluetoothSDKDebug.swift +12 -0
  435. package/ios/Source/BluetoothSdkDefaults.swift +29 -0
  436. package/ios/Source/Bridge.swift +708 -0
  437. package/ios/Source/Bridging-Header.h +16 -0
  438. package/ios/Source/DeviceManager.swift +2109 -0
  439. package/ios/Source/DeviceStore.swift +336 -0
  440. package/ios/Source/GeneratedChangelogCatalog.swift +7 -0
  441. package/ios/Source/GeneratedReleaseMetadata.swift +11 -0
  442. package/ios/Source/ObservableStore.swift +118 -0
  443. package/ios/Source/OtaManifest.swift +211 -0
  444. package/ios/Source/PrivacyInfo.xcprivacy +23 -0
  445. package/ios/Source/ReleaseChangelog.swift +65 -0
  446. package/ios/Source/Resources/G2Firmware/README.md +10 -0
  447. package/ios/Source/audio/AudioModels.swift +178 -0
  448. package/ios/Source/audio/PcmStreamPlayer.swift +410 -0
  449. package/ios/Source/camera/CameraModels.swift +866 -0
  450. package/ios/Source/connection/ScanSession.swift +27 -0
  451. package/ios/Source/controllers/ControllerManager.swift +184 -0
  452. package/ios/Source/controllers/R1.swift +829 -0
  453. package/ios/Source/errors/BluetoothSdkError.swift +19 -0
  454. package/ios/Source/events/BluetoothEvents.swift +342 -0
  455. package/ios/Source/internal/BleTraceLogger.swift +192 -0
  456. package/ios/Source/internal/BluetoothAvailability.swift +78 -0
  457. package/ios/Source/internal/BluetoothSdkAnalytics.swift +199 -0
  458. package/ios/Source/internal/ValueParsing.swift +99 -0
  459. package/ios/Source/requests/DisplayRequests.swift +82 -0
  460. package/ios/Source/services/PhoneMic.swift +662 -0
  461. package/ios/Source/sgcs/Ar99.swift +2451 -0
  462. package/ios/Source/sgcs/Frame.swift +649 -0
  463. package/ios/Source/sgcs/G1.swift +2554 -0
  464. package/ios/Source/sgcs/G2.swift +6887 -0
  465. package/ios/Source/sgcs/G2CfwClassification.swift +43 -0
  466. package/ios/Source/sgcs/G2CfwRenderer.swift +1279 -0
  467. package/ios/Source/sgcs/G2CfwTextureCache.swift +233 -0
  468. package/ios/Source/sgcs/G2FlashProtocol.swift +312 -0
  469. package/ios/Source/sgcs/G2Flasher.swift +773 -0
  470. package/ios/Source/sgcs/Mach1.swift +541 -0
  471. package/ios/Source/sgcs/MentraLive.swift +7011 -0
  472. package/ios/Source/sgcs/MentraLiveL2capChannel.swift +183 -0
  473. package/ios/Source/sgcs/MentraLivePairingAdvertisement.swift +64 -0
  474. package/ios/Source/sgcs/MentraNex.swift +3221 -0
  475. package/ios/Source/sgcs/Nimo.swift +1886 -0
  476. package/ios/Source/sgcs/SGCManager.swift +608 -0
  477. package/ios/Source/sgcs/Simulated.swift +274 -0
  478. package/ios/Source/sgcs/ar99/ota/Ar99OtaManager.swift +637 -0
  479. package/ios/Source/sgcs/glassly_ble.pb.swift +4354 -0
  480. package/ios/Source/speakerid/SpeakerIdEngine.swift +573 -0
  481. package/ios/Source/status/DeviceStatus.swift +981 -0
  482. package/ios/Source/status/RuntimeState.swift +359 -0
  483. package/ios/Source/status/WifiHotspotStatus.swift +345 -0
  484. package/ios/Source/streaming/StreamModels.swift +693 -0
  485. package/ios/Source/stt/STTTools.swift +191 -0
  486. package/ios/Source/stt/SherpaOnnxTranscriber.swift +466 -0
  487. package/ios/Source/tts/TTSTools.swift +171 -0
  488. package/ios/Source/types/DeviceModels.swift +177 -0
  489. package/ios/Source/utils/AudioSessionMonitor.swift +283 -0
  490. package/ios/Source/utils/BinaryCodec.swift +61 -0
  491. package/ios/Source/utils/BleJsonCompact.swift +405 -0
  492. package/ios/Source/utils/BleWireProtocol.swift +92 -0
  493. package/ios/Source/utils/Constants.swift +78 -0
  494. package/ios/Source/utils/Enums.swift +95 -0
  495. package/ios/Source/utils/G1Text.swift +2096 -0
  496. package/ios/Source/utils/JSCExperiment.swift +241 -0
  497. package/ios/Source/utils/MemoryMonitor.swift +44 -0
  498. package/ios/Source/utils/MessageChunkReassembler.swift +190 -0
  499. package/ios/Source/utils/MessageChunker.swift +294 -0
  500. package/ios/Source/utils/Models.swift +135 -0
  501. package/ios/Source/utils/PhoneAudioMonitor.swift +230 -0
  502. package/ios/Source/utils/TarBz2Extractor.swift +257 -0
  503. package/ios/Tests/BluetoothSDKTests/G2CfwClassificationTests.swift +78 -0
  504. package/ios/Tests/BluetoothSDKTests/G2CfwRendererTests.swift +372 -0
  505. package/ios/Tests/BluetoothSDKTests/G2CfwTextureCacheTests.swift +162 -0
  506. package/ios/Tests/BluetoothSDKTests/G2FlashProtocolTests.swift +182 -0
  507. package/ios/Tests/MentraLivePairingAdvertisementTests.swift +160 -0
  508. package/ios/Tests/ReleaseChangelogTests.swift +13 -0
  509. package/package.json +129 -0
  510. package/plugin/build/index.d.ts +10 -0
  511. package/plugin/build/index.js +12 -0
  512. package/plugin/build/withAndroid.d.ts +3 -0
  513. package/plugin/build/withAndroid.js +190 -0
  514. package/plugin/build/withIos.d.ts +5 -0
  515. package/plugin/build/withIos.js +108 -0
  516. package/scripts/inject-ios-sdk-version.mjs +65 -0
  517. package/scripts/public-ota-api.test.mjs +37 -0
  518. package/scripts/verify-release-package.mjs +45 -0
  519. package/scripts/write-release-metadata.mjs +152 -0
  520. package/scripts/write-release-metadata.test.mjs +37 -0
  521. package/src/BluetoothSdk.types.ts +1623 -0
  522. package/src/_internal.ts +16 -0
  523. package/src/_private/BluetoothSdkModule.ts +684 -0
  524. package/src/_private/LocalNetworkModule.ts +50 -0
  525. package/src/_private/cameraRequestPayload.ts +34 -0
  526. package/src/_private/photoRequestPayload.ts +90 -0
  527. package/src/_private/sdkOtaManifest.ts +18 -0
  528. package/src/changelogs.ts +46 -0
  529. package/src/debug.ts +9 -0
  530. package/src/generated/changelogCatalog.ts +13 -0
  531. package/src/generated/releaseMetadata.ts +20 -0
  532. package/src/index.ts +321 -0
  533. package/src/ota-server/OtaServer.types.ts +10 -0
  534. package/src/ota-server/OtaServerModule.ts +23 -0
  535. package/src/ota-server/OtaServerModule.web.ts +17 -0
  536. package/src/ota-server/index.ts +2 -0
  537. package/src/ota-transport/index.ts +116 -0
  538. package/src/photo-receiver/PhotoReceiver.types.ts +20 -0
  539. package/src/photo-receiver/PhotoReceiverModule.ts +11 -0
  540. package/src/photo-receiver/PhotoReceiverModule.web.ts +17 -0
  541. package/src/photo-receiver/index.ts +2 -0
  542. package/src/react/index.ts +21 -0
  543. package/src/react/useBluetooth.ts +309 -0
  544. package/src/react/useBluetoothEvent.ts +35 -0
  545. package/src/react/useBluetoothScan.ts +173 -0
  546. package/src/react/useBluetoothStatus.ts +180 -0
  547. package/src/react/useGlassesConnection.ts +202 -0
  548. package/src/types/index.ts +12 -0
@@ -0,0 +1,827 @@
1
+ package com.glassly.bluetoothsdk.utils;
2
+
3
+ import android.content.BroadcastReceiver;
4
+ import android.content.Context;
5
+ import android.content.Intent;
6
+ import android.content.IntentFilter;
7
+ import android.content.pm.PackageManager;
8
+ import android.util.Log;
9
+ import android.os.Build;
10
+
11
+ import org.json.JSONException;
12
+ import org.json.JSONObject;
13
+ import java.nio.charset.StandardCharsets;
14
+
15
+ /**
16
+ * Utility class for K900 BES2700 protocol formatting.
17
+ * Used for communication between AugmentOS Core and ASG Client.
18
+ */
19
+ public class K900ProtocolUtils {
20
+
21
+ // Protocol constants
22
+ public static final byte[] CMD_START_CODE = new byte[]{0x23, 0x23}; // ##
23
+ public static final byte[] CMD_END_CODE = new byte[]{0x24, 0x24}; // $$
24
+ public static final byte CMD_TYPE_STRING = 0x30; // String/JSON type
25
+ public static final byte CMD_TYPE_PHOTO = 0x31; // Photo file type
26
+ public static final byte CMD_TYPE_VIDEO = 0x32; // Video file type
27
+ public static final byte CMD_TYPE_MUSIC = 0x33; // Music file type
28
+ public static final byte CMD_TYPE_AUDIO = 0x34; // Audio file type
29
+ public static final byte CMD_TYPE_DATA = 0x35; // Generic data type
30
+ public static final byte CMD_TYPE_BINARY_MSG = BleWireProtocol.CMD_TYPE_BINARY_MSG;
31
+
32
+ // File transfer constants
33
+ // Negotiated file protocol ceiling. Legacy/GATT transfers remain smaller; 800-byte frames are
34
+ // accepted only after file_payload_v2 negotiation and an open CoC channel.
35
+ public static final int FILE_PACK_SIZE = 800;
36
+ public static final int LENGTH_FILE_START = 2;
37
+ public static final int LENGTH_FILE_TYPE = 1;
38
+ public static final int LENGTH_FILE_PACKSIZE = 2;
39
+ public static final int LENGTH_FILE_PACKINDEX = 2;
40
+ public static final int LENGTH_FILE_SIZE = 4;
41
+ public static final int LENGTH_FILE_NAME = 16;
42
+ public static final int LENGTH_FILE_FLAG = 2;
43
+ public static final int LENGTH_FILE_VERIFY = 1;
44
+ public static final int LENGTH_FILE_END = 2;
45
+
46
+ // JSON Field constants
47
+ public static final String FIELD_C = "C"; // Command/Content field
48
+ public static final String FIELD_V = "V"; // Version field
49
+ public static final String FIELD_B = "B"; // Body field
50
+
51
+ /**
52
+ * Pack a JSON string into the proper K900 format:
53
+ * 1. Wrap with C-field: {"C": jsonData}
54
+ * 2. Then pack with BES2700 protocol: ## + type + length + {"C": jsonData} + $$
55
+ *
56
+ * @param jsonData The JSON string to pack
57
+ * @return Byte array with packed data according to protocol format
58
+ */
59
+ public static byte[] packJsonCommand(String jsonData) {
60
+ return packJsonCommand(jsonData, K900LengthCodec.Endian.BE);
61
+ }
62
+
63
+ public static byte[] packJsonCommand(String jsonData, K900LengthCodec.Endian endian) {
64
+ if (jsonData == null) {
65
+ return null;
66
+ }
67
+
68
+ try {
69
+ // First wrap with C-field
70
+ JSONObject wrapper = new JSONObject();
71
+ wrapper.put(FIELD_C, jsonData);
72
+
73
+ // Convert to string
74
+ String wrappedJson = wrapper.toString();
75
+
76
+ // Then pack with BES2700 protocol format
77
+ byte[] jsonBytes = wrappedJson.getBytes(StandardCharsets.UTF_8);
78
+ return packDataCommand(jsonBytes, CMD_TYPE_STRING, endian);
79
+
80
+ } catch (JSONException e) {
81
+ android.util.Log.e("K900ProtocolUtils", "Error creating JSON wrapper", e);
82
+ return null;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Pack raw byte data with K900 BES2700 protocol format
88
+ * Format: ## + command_type + length(2bytes) + data + $$
89
+ *
90
+ * @param data The raw data to pack
91
+ * @param cmdType The command type (use CMD_TYPE_STRING for JSON)
92
+ * @return Byte array with packed data according to protocol format
93
+ */
94
+ public static byte[] packDataCommand(byte[] data, byte cmdType) {
95
+ // Default to legacy big-endian until wire_caps negotiates little-endian.
96
+ return packDataCommand(data, cmdType, K900LengthCodec.Endian.BE);
97
+ }
98
+
99
+ /**
100
+ * Pack raw byte data with K900 BES2700 protocol format, writing the 2-byte length field with an
101
+ * explicit endianness. Use the negotiated per-link endianness so both legacy big-endian and
102
+ * wire-v2 little-endian peers can parse the frame.
103
+ */
104
+ public static byte[] packDataCommand(byte[] data, byte cmdType, K900LengthCodec.Endian endian) {
105
+ if (data == null) {
106
+ return null;
107
+ }
108
+
109
+ int dataLength = data.length;
110
+
111
+ // Command structure: ## + type + length(2 bytes) + data + $$
112
+ byte[] result = new byte[dataLength + 7]; // 2(start) + 1(type) + 2(length) + data + 2(end)
113
+
114
+ // Start code ##
115
+ result[0] = CMD_START_CODE[0]; // #
116
+ result[1] = CMD_START_CODE[1]; // #
117
+
118
+ // Command type
119
+ result[2] = cmdType;
120
+
121
+ // Length (2 bytes, negotiated endianness)
122
+ K900LengthCodec.writeLength(result, 3, dataLength, endian);
123
+
124
+ // Copy the data
125
+ System.arraycopy(data, 0, result, 5, dataLength);
126
+
127
+ // End code $$
128
+ result[5 + dataLength] = CMD_END_CODE[0]; // $
129
+ result[6 + dataLength] = CMD_END_CODE[1]; // $
130
+
131
+ return result;
132
+ }
133
+
134
+ /**
135
+ * Pack raw byte data with K900 BES2700 protocol format for phone-to-device communication
136
+ * Format: ## + command_type + length(2bytes) + data + $$
137
+ * Uses little-endian byte order for length field
138
+ *
139
+ * @param data The raw data to pack
140
+ * @param cmdType The command type (use CMD_TYPE_STRING for JSON)
141
+ * @return Byte array with packed data according to protocol format
142
+ */
143
+ public static byte[] packDataToK900(byte[] data, byte cmdType) {
144
+ return packDataToK900(data, cmdType, K900LengthCodec.Endian.BE);
145
+ }
146
+
147
+ /**
148
+ * Pack raw byte data with K900 BES2700 protocol format for phone-to-device communication.
149
+ * Format: ## + command_type + length(2bytes) + data + $$
150
+ */
151
+ public static byte[] packDataToK900(byte[] data, byte cmdType, K900LengthCodec.Endian endian) {
152
+ return packDataCommand(data, cmdType, endian);
153
+ }
154
+
155
+ /**
156
+ * Pack a JSON string for phone-to-K900 device communication
157
+ * 1. Wrap with C-field: {"C": jsonData}
158
+ * 2. Then pack with BES2700 protocol using little-endian: ## + type + length + {"C": jsonData} + $$
159
+ *
160
+ * @param jsonData The JSON string to pack
161
+ * @return Byte array with packed data according to protocol format
162
+ */
163
+ public static byte[] packJsonToK900(String jsonData, boolean wakeup) {
164
+ return packJsonToK900(jsonData, wakeup, K900LengthCodec.Endian.BE);
165
+ }
166
+
167
+ /**
168
+ * Pack a C-wrapped JSON string for phone-to-glasses transmission, writing the STRING frame
169
+ * length with the negotiated per-link endianness. Legacy big-endian glasses require BE until
170
+ * they advertise {@code wire_caps.k900_le}.
171
+ */
172
+ public static byte[] packJsonToK900(String jsonData, boolean wakeup, K900LengthCodec.Endian endian) {
173
+ if (jsonData == null) {
174
+ return null;
175
+ }
176
+
177
+ try {
178
+ // First wrap with C-field
179
+ JSONObject wrapper = new JSONObject();
180
+ wrapper.put(FIELD_C, jsonData);
181
+ if (wakeup) {
182
+ wrapper.put("W", 1); // Add W field as seen in MentraLiveSGC
183
+ }
184
+
185
+ // Convert to string
186
+ String wrappedJson = wrapper.toString();
187
+
188
+ // Then pack with BES2700 protocol format using the negotiated endianness
189
+ byte[] jsonBytes = wrappedJson.getBytes(StandardCharsets.UTF_8);
190
+ return packDataCommand(jsonBytes, CMD_TYPE_STRING, endian);
191
+
192
+ } catch (JSONException e) {
193
+ android.util.Log.e("K900ProtocolUtils", "Error creating JSON wrapper for K900", e);
194
+ return null;
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Formats a standard ASG-client JSON message for transmission to MentraLiveSGC
200
+ * This does both:
201
+ * 1. Wrap with C-field: {"C": jsonData}
202
+ * 2. Format with BES2700 protocol: ## + type + length + data + $$
203
+ *
204
+ * @param jsonData The JSON string to format (must be valid JSON)
205
+ * @return Formatted bytes ready for transmission
206
+ */
207
+ public static byte[] formatMessageForTransmission(String jsonData) {
208
+ return formatMessageForTransmission(jsonData, K900LengthCodec.Endian.BE);
209
+ }
210
+
211
+ /**
212
+ * Format an ASG-client JSON message for transmission, writing the STRING frame length with the
213
+ * negotiated per-link endianness.
214
+ */
215
+ public static byte[] formatMessageForTransmission(String jsonData, K900LengthCodec.Endian endian) {
216
+ try {
217
+ android.util.Log.e("K900ProtocolUtils", "🔄 Formatting message: " + jsonData);
218
+
219
+ // Validate that input is proper JSON
220
+ new JSONObject(jsonData);
221
+
222
+ // First, create C wrapper: {"C": jsonData}
223
+ JSONObject wrapper = new JSONObject();
224
+ wrapper.put(FIELD_C, jsonData);
225
+ wrapper.put(FIELD_V, 1); // Optional version field
226
+ wrapper.put(FIELD_B, new JSONObject()); // Optional body field
227
+ String wrappedJson = wrapper.toString();
228
+ android.util.Log.e("K900ProtocolUtils", "🔄 After C-wrapping: " + wrappedJson);
229
+
230
+ // Now format with BES2700 protocol
231
+ byte[] result =
232
+ packDataCommand(
233
+ wrappedJson.getBytes(StandardCharsets.UTF_8), CMD_TYPE_STRING, endian);
234
+
235
+ // Log some bytes for debugging
236
+ StringBuilder hexDump = new StringBuilder();
237
+ for (int i = 0; i < Math.min(result.length, 30); i++) {
238
+ hexDump.append(String.format("%02X ", result[i]));
239
+ }
240
+ //android.util.Log.e("K900ProtocolUtils", "🔄 After protocol formatting (first 30 bytes): " + hexDump);
241
+ //android.util.Log.e("K900ProtocolUtils", "🔄 Final length: " + result.length + " bytes");
242
+
243
+ return result;
244
+
245
+ } catch (JSONException e) {
246
+ android.util.Log.e("K900ProtocolUtils", "❌ Error in formatMessageForTransmission", e);
247
+ // Fallback: if json is invalid, still try to pack it without validation
248
+ return packJsonCommand(jsonData, endian);
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Create a C-wrapped JSON object ready for protocol formatting
254
+ * Format: {"C": content}
255
+ *
256
+ * @param content The content to wrap in the C field
257
+ * @return C-wrapped JSON string
258
+ */
259
+ public static String createCWrappedJson(String content) {
260
+ try {
261
+ JSONObject wrapper = new JSONObject();
262
+ wrapper.put(FIELD_C, content);
263
+ return wrapper.toString();
264
+ } catch (JSONException e) {
265
+ android.util.Log.e("K900ProtocolUtils", "Error creating C-wrapped JSON", e);
266
+ return null;
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Check if data follows the K900 BES2700 protocol format
272
+ * Verifies if data starts with ## markers
273
+ */
274
+ public static boolean isK900ProtocolFormat(byte[] data) {
275
+ if (data == null || data.length < 7) { // Minimum protocol size
276
+ return false;
277
+ }
278
+
279
+ return data[0] == CMD_START_CODE[0] &&
280
+ data[1] == CMD_START_CODE[1];
281
+ }
282
+
283
+ /**
284
+ * Check if a JSON string is already properly formatted for K900 protocol
285
+ * This can either be:
286
+ * 1. Simple C-wrapped format: {"C": "content"}
287
+ * 2. Full K900 format: {"C": "command", "V": value, "B": body}
288
+ *
289
+ * @return true if already in proper format, false otherwise
290
+ */
291
+ public static boolean isCWrappedJson(String jsonStr) {
292
+ try {
293
+ JSONObject json = new JSONObject(jsonStr);
294
+
295
+ // Check for simple C-wrapping {"C": "content"} - only one field
296
+ if (json.has(FIELD_C) && json.length() == 1) {
297
+ return true;
298
+ }
299
+
300
+ // Check for full K900 format {"C": "command", "V": val, "B": body}
301
+ if (json.has(FIELD_C) && json.has(FIELD_V) && json.has(FIELD_B)) {
302
+ return true;
303
+ }
304
+
305
+ return false;
306
+ } catch (JSONException e) {
307
+ return false;
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Extract payload from K900 protocol formatted data
313
+ * @return Raw payload data or null if format is invalid
314
+ */
315
+ public static byte[] extractPayload(byte[] protocolData) {
316
+ return extractPayload(protocolData, K900LengthCodec.Endian.BE);
317
+ }
318
+
319
+ /**
320
+ * Extract payload from a K900 STRING frame, reading the length field with an explicit
321
+ * endianness. Prefer {@link #extractPayloadAuto} on receive when the peer endianness is not yet
322
+ * negotiated.
323
+ */
324
+ public static byte[] extractPayload(byte[] protocolData, K900LengthCodec.Endian endian) {
325
+ if (!isK900ProtocolFormat(protocolData) || protocolData.length < 7) {
326
+ return null;
327
+ }
328
+
329
+ int length = K900LengthCodec.readLength(protocolData, 3, endian);
330
+
331
+ if (length + 7 > protocolData.length) {
332
+ return null; // Invalid length
333
+ }
334
+
335
+ byte[] payload = new byte[length];
336
+ System.arraycopy(protocolData, 5, payload, 0, length);
337
+ return payload;
338
+ }
339
+
340
+ /**
341
+ * Extract payload from a K900 STRING frame, heuristically detecting the length field's
342
+ * endianness. Safe RX entry point when the peer endianness is not yet negotiated (fixes the
343
+ * "Extracted length=9472" misframe against legacy big-endian BES firmware).
344
+ */
345
+ public static byte[] extractPayloadAuto(byte[] protocolData) {
346
+ if (!isK900ProtocolFormat(protocolData) || protocolData.length < 7) {
347
+ return null;
348
+ }
349
+ K900LengthCodec.Detected detected = K900LengthCodec.detectLength(protocolData);
350
+ if (detected == null) {
351
+ return null;
352
+ }
353
+ byte[] payload = new byte[detected.length];
354
+ System.arraycopy(protocolData, 5, payload, 0, detected.length);
355
+ return payload;
356
+ }
357
+
358
+ /**
359
+ * Extract payload from K900 protocol formatted data received from device
360
+ * Uses little-endian byte order for length field
361
+ * @return Raw payload data or null if format is invalid
362
+ */
363
+ public static byte[] extractPayloadFromK900(byte[] protocolData) {
364
+ // Retained for backward compatibility: device-to-phone frames may arrive in either
365
+ // endianness depending on firmware vintage, so auto-detect rather than assuming LE.
366
+ return extractPayloadAuto(protocolData);
367
+ }
368
+
369
+ /**
370
+ * Process received bytes from Bluetooth into a JSON object
371
+ * Handles K900 protocol format detection, payload extraction, and C-field unwrapping
372
+ *
373
+ * @param data The raw bytes received from Bluetooth
374
+ * @return Parsed JSON object or null if not valid protocol data or valid JSON
375
+ */
376
+ public static JSONObject processReceivedBytesToJson(byte[] data) {
377
+ android.util.Log.d("K900ProtocolUtils", "Processing received bytes for JSON extraction");
378
+
379
+ // Check for null or too small data
380
+ if (data == null || data.length < 7) {
381
+ android.util.Log.d("K900ProtocolUtils", "Received data is null or too short to be valid protocol data");
382
+ return null;
383
+ }
384
+
385
+ // Verify if this is K900 protocol format (starts with ##)
386
+ if (!isK900ProtocolFormat(data)) {
387
+ android.util.Log.d("K900ProtocolUtils", "Not in K900 protocol format (missing ## markers)");
388
+ return null;
389
+ }
390
+
391
+ // Extract the command type
392
+ byte commandType = data[2];
393
+
394
+ // Extract the length, auto-detecting endianness so we parse both legacy big-endian and
395
+ // wire-v2 little-endian frames.
396
+ K900LengthCodec.Detected detected = K900LengthCodec.detectLength(data);
397
+ int payloadLength =
398
+ detected != null
399
+ ? detected.length
400
+ : ((data[3] & 0xFF) | ((data[4] & 0xFF) << 8));
401
+
402
+ android.util.Log.d("K900ProtocolUtils", "Command type: 0x" + String.format("%02X", commandType) +
403
+ ", Payload length: " + payloadLength);
404
+
405
+ // Verify we have enough data and the right command type
406
+ if (commandType != CMD_TYPE_STRING) {
407
+ android.util.Log.d("K900ProtocolUtils", "Not a JSON/string command type (0x30), got: 0x" +
408
+ String.format("%02X", commandType));
409
+ return null;
410
+ }
411
+
412
+ if (data.length < payloadLength + 7) {
413
+ android.util.Log.d("K900ProtocolUtils", "Received data size (" + data.length +
414
+ ") is less than expected size (" + (payloadLength + 7) + ")");
415
+ return null;
416
+ }
417
+
418
+ // Check for end markers ($$)
419
+ if (data[5 + payloadLength] != CMD_END_CODE[0] || data[6 + payloadLength] != CMD_END_CODE[1]) {
420
+ android.util.Log.d("K900ProtocolUtils", "End markers ($$) not found where expected");
421
+ return null;
422
+ }
423
+
424
+ // Extract the payload
425
+ byte[] payload = new byte[payloadLength];
426
+ System.arraycopy(data, 5, payload, 0, payloadLength);
427
+
428
+ // Convert to string
429
+ String payloadStr;
430
+ try {
431
+ payloadStr = new String(payload, StandardCharsets.UTF_8);
432
+ android.util.Log.d("K900ProtocolUtils", "Extracted JSON payload bytes: " + payloadLength);
433
+ } catch (Exception e) {
434
+ android.util.Log.e("K900ProtocolUtils", "Error converting payload to string", e);
435
+ return null;
436
+ }
437
+
438
+ // Check if it's valid JSON
439
+ if (!payloadStr.startsWith("{") || !payloadStr.endsWith("}")) {
440
+ android.util.Log.d("K900ProtocolUtils", "Payload is not valid JSON");
441
+ return null;
442
+ }
443
+
444
+ try {
445
+ // Parse the JSON payload
446
+ JSONObject json = new JSONObject(payloadStr);
447
+
448
+ // Check if this is C-wrapped format {"C": "..."}
449
+ if (json.has(FIELD_C)) {
450
+ String innerContent = json.optString(FIELD_C, "");
451
+ android.util.Log.d("K900ProtocolUtils", "Detected C-wrapped format");
452
+
453
+ // Try to parse the inner content as JSON
454
+ try {
455
+ JSONObject innerJson = new JSONObject(innerContent);
456
+ return innerJson;
457
+ } catch (JSONException e) {
458
+ android.util.Log.d("K900ProtocolUtils", "Inner content is not JSON, returning outer JSON object");
459
+ // If inner content is not JSON, return the outer JSON
460
+ return json;
461
+ }
462
+ } else {
463
+ // Not C-wrapped, return the JSON directly
464
+ return json;
465
+ }
466
+ } catch (JSONException e) {
467
+ android.util.Log.e("K900ProtocolUtils", "Error parsing JSON payload: " + e.getMessage(), e);
468
+ return null;
469
+ }
470
+ }
471
+
472
+ /**
473
+ * Unified method to prepare data for transmission according to K900 protocol
474
+ * This handles all formatting cases:
475
+ * 1. Data already in protocol format
476
+ * 2. JSON data that needs C-wrapping
477
+ * 3. Raw data that needs protocol packaging
478
+ *
479
+ * @param data The raw data to prepare for transmission
480
+ * @return Properly formatted data according to K900 protocol
481
+ */
482
+ public static byte[] prepareDataForTransmission(byte[] data) {
483
+ if (data == null || data.length == 0) {
484
+ return null;
485
+ }
486
+
487
+ // If already in protocol format, don't modify
488
+ if (isK900ProtocolFormat(data)) {
489
+ return data;
490
+ }
491
+
492
+ // Try to interpret as a JSON string that needs C-wrapping and protocol formatting
493
+ try {
494
+ // Convert to string for processing
495
+ String originalData = new String(data, "UTF-8");
496
+
497
+ // If looks like JSON but not C-wrapped, use the full formatting function
498
+ if (originalData.startsWith("{") && !isCWrappedJson(originalData)) {
499
+ android.util.Log.d("K900ProtocolUtils", "📦 JSON DATA BEFORE C-WRAPPING: " + originalData);
500
+ byte[] formattedData = formatMessageForTransmission(originalData);
501
+
502
+ // Debug log the formatting results if needed
503
+ if (android.util.Log.isLoggable("K900ProtocolUtils", android.util.Log.DEBUG)) {
504
+ StringBuilder hexDump = new StringBuilder();
505
+ for (int i = 0; i < Math.min(formattedData.length, 50); i++) {
506
+ hexDump.append(String.format("%02X ", formattedData[i]));
507
+ }
508
+ android.util.Log.d("K900ProtocolUtils", "📦 AFTER C-WRAPPING & PROTOCOL FORMATTING (first 50 bytes): " + hexDump.toString());
509
+ android.util.Log.d("K900ProtocolUtils", "📦 Total formatted length: " + formattedData.length + " bytes");
510
+ }
511
+
512
+ return formattedData;
513
+ } else {
514
+ // Otherwise just apply protocol formatting
515
+ android.util.Log.d("K900ProtocolUtils", "📦 Data already C-wrapped or not JSON: " + originalData);
516
+ android.util.Log.d("K900ProtocolUtils", "Formatting data with K900 protocol (adding ##...)");
517
+ return packDataCommand(data, CMD_TYPE_STRING);
518
+ }
519
+ } catch (Exception e) {
520
+ // If we can't interpret as string, just apply protocol formatting to raw bytes
521
+ android.util.Log.d("K900ProtocolUtils", "Applying protocol format to raw bytes");
522
+ return packDataCommand(data, CMD_TYPE_STRING);
523
+ }
524
+ }
525
+
526
+ /**
527
+ * Check if the device is a K900
528
+ * @param context The application context
529
+ * @return true if the device is a K900, false otherwise
530
+ */
531
+ public static boolean isK900Device(Context context) {
532
+ // Check for K900-specific broadcast receivers
533
+ try {
534
+ // Verify the SystemUI package exists
535
+ PackageManager pm = context.getPackageManager();
536
+ pm.getPackageInfo("com.android.systemui", 0);
537
+
538
+ // Check for K900-specific system action
539
+ try {
540
+ // Set up a result receiver to check if our probe was received
541
+ final boolean[] responseReceived = {false};
542
+ BroadcastReceiver testReceiver = new BroadcastReceiver() {
543
+ @Override
544
+ public void onReceive(Context context, Intent intent) {
545
+ responseReceived[0] = true;
546
+ try {
547
+ context.unregisterReceiver(this);
548
+ } catch (Exception e) {
549
+ // Ignore unregister failures
550
+ }
551
+ }
552
+ };
553
+
554
+ // Register for any response from our probe
555
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
556
+ context.registerReceiver(testReceiver,
557
+ new IntentFilter("com.xy.xsetting.response"),
558
+ Context.RECEIVER_NOT_EXPORTED);
559
+ } else {
560
+ context.registerReceiver(testReceiver,
561
+ new IntentFilter("com.xy.xsetting.response"),
562
+ Context.RECEIVER_NOT_EXPORTED);
563
+ }
564
+
565
+ // Send a test probe
566
+ Intent testIntent = new Intent("com.xy.xsetting.action");
567
+ testIntent.setPackage("com.android.systemui");
568
+ testIntent.putExtra("cmd", "test_k900");
569
+ context.sendBroadcast(testIntent);
570
+
571
+ // In a real implementation, we would wait for a response
572
+ // For now, we check device model as a fallback
573
+ String model = android.os.Build.MODEL.toLowerCase();
574
+ return model.contains("k900") || model.contains("xyglasses");
575
+ } catch (Exception e) {
576
+ Log.e("K900ProtocolUtils", "Error checking for K900 specific broadcast", e);
577
+ }
578
+ } catch (Exception e) {
579
+ Log.d("K900ProtocolUtils", "Not a K900 device: " + e.getMessage());
580
+ }
581
+
582
+ return false;
583
+ }
584
+
585
+ public static boolean isBinaryFrame(byte[] data) {
586
+ return BleWireProtocol.isBinaryFrame(data);
587
+ }
588
+
589
+ public static byte[] packBinaryFragment(
590
+ byte flags, int msgId, int fragIdx, int fragCount, byte[] payload) {
591
+ return BleWireProtocol.packBinaryFragment(flags, msgId, fragIdx, fragCount, payload);
592
+ }
593
+
594
+ public static BleWireProtocol.BinaryFragmentInfo extractBinaryFragmentInfo(byte[] frame) {
595
+ return BleWireProtocol.extractBinaryFragmentInfo(frame);
596
+ }
597
+
598
+ public static byte[] extractBinaryPayload(byte[] frame) {
599
+ return BleWireProtocol.extractBinaryPayload(frame);
600
+ }
601
+
602
+ /**
603
+ * Inner class to represent file packet information
604
+ */
605
+ public static class FilePacketInfo {
606
+ public byte fileType;
607
+ public int packSize;
608
+ public int packIndex;
609
+ public int fileSize;
610
+ public String fileName;
611
+ public int flags;
612
+ public byte[] data;
613
+ public byte verifyCode;
614
+ public boolean isValid;
615
+
616
+ public FilePacketInfo() {
617
+ this.isValid = false;
618
+ }
619
+ }
620
+
621
+ /**
622
+ * Pack a file packet according to K900 file transfer protocol
623
+ * Format: ## + fileType + packSize + packIndex + fileSize + fileName + flags + data + verify + $$
624
+ *
625
+ * @param fileData The file data chunk to send (max 400 bytes)
626
+ * @param packIndex The index of this packet (0-based)
627
+ * @param packSize The size of data in this packet
628
+ * @param fileSize The total file size
629
+ * @param fileName The file name (max 16 chars)
630
+ * @param flags Optional flags
631
+ * @param fileType The file type (CMD_TYPE_PHOTO, etc)
632
+ * @return Packed byte array ready for transmission
633
+ */
634
+ public static byte[] packFilePacket(byte[] fileData, int packIndex, int packSize,
635
+ int fileSize, String fileName, int flags, byte fileType) {
636
+ if (fileData == null || packSize > FILE_PACK_SIZE) {
637
+ return null;
638
+ }
639
+
640
+ // Calculate total packet size
641
+ int totalSize = LENGTH_FILE_START + LENGTH_FILE_TYPE + LENGTH_FILE_PACKSIZE +
642
+ LENGTH_FILE_PACKINDEX + LENGTH_FILE_SIZE + LENGTH_FILE_NAME +
643
+ LENGTH_FILE_FLAG + packSize + LENGTH_FILE_VERIFY + LENGTH_FILE_END;
644
+
645
+ byte[] packet = new byte[totalSize];
646
+ int pos = 0;
647
+
648
+ // Start code ##
649
+ System.arraycopy(CMD_START_CODE, 0, packet, pos, LENGTH_FILE_START);
650
+ pos += LENGTH_FILE_START;
651
+
652
+ // File type
653
+ packet[pos] = fileType;
654
+ pos += LENGTH_FILE_TYPE;
655
+
656
+ // Pack size (2 bytes, big-endian like reference implementation)
657
+ packet[pos] = (byte)((packSize >> 8) & 0xFF);
658
+ packet[pos + 1] = (byte)(packSize & 0xFF);
659
+ pos += LENGTH_FILE_PACKSIZE;
660
+
661
+ // Pack index (2 bytes, big-endian)
662
+ packet[pos] = (byte)((packIndex >> 8) & 0xFF);
663
+ packet[pos + 1] = (byte)(packIndex & 0xFF);
664
+ pos += LENGTH_FILE_PACKINDEX;
665
+
666
+ // File size (4 bytes, big-endian)
667
+ packet[pos] = (byte)((fileSize >> 24) & 0xFF);
668
+ packet[pos + 1] = (byte)((fileSize >> 16) & 0xFF);
669
+ packet[pos + 2] = (byte)((fileSize >> 8) & 0xFF);
670
+ packet[pos + 3] = (byte)(fileSize & 0xFF);
671
+ pos += LENGTH_FILE_SIZE;
672
+
673
+ // File name (16 bytes, padded with zeros)
674
+ byte[] nameBytes = fileName.getBytes(StandardCharsets.UTF_8);
675
+ int nameLen = Math.min(nameBytes.length, LENGTH_FILE_NAME);
676
+ System.arraycopy(nameBytes, 0, packet, pos, nameLen);
677
+ // Pad with zeros if name is shorter than 16 bytes
678
+ for (int i = nameLen; i < LENGTH_FILE_NAME; i++) {
679
+ packet[pos + i] = 0;
680
+ }
681
+ pos += LENGTH_FILE_NAME;
682
+
683
+ // Flags (2 bytes, big-endian)
684
+ packet[pos] = (byte)((flags >> 8) & 0xFF);
685
+ packet[pos + 1] = (byte)(flags & 0xFF);
686
+ pos += LENGTH_FILE_FLAG;
687
+
688
+ // Data
689
+ System.arraycopy(fileData, 0, packet, pos, packSize);
690
+ pos += packSize;
691
+
692
+ // Calculate verify code (checksum of data bytes)
693
+ int checkSum = 0;
694
+ for (int i = 0; i < packSize; i++) {
695
+ checkSum += (fileData[i] & 0xFF);
696
+ }
697
+ packet[pos] = (byte)(checkSum & 0xFF);
698
+ pos += LENGTH_FILE_VERIFY;
699
+
700
+ // End code $$
701
+ System.arraycopy(CMD_END_CODE, 0, packet, pos, LENGTH_FILE_END);
702
+
703
+ return packet;
704
+ }
705
+
706
+ /**
707
+ * Extract file packet information from received protocol data
708
+ *
709
+ * @param protocolData The raw protocol data received
710
+ * @return FilePacketInfo object with parsed data, or null if invalid
711
+ */
712
+ public static FilePacketInfo extractFilePacket(byte[] protocolData) {
713
+ if (!isK900ProtocolFormat(protocolData) || protocolData.length < 31) {
714
+ Log.e("K900ProtocolUtils", "extractFilePacket: Invalid format or too short. Length=" +
715
+ (protocolData != null ? protocolData.length : 0) +
716
+ ", isK900Format=" + isK900ProtocolFormat(protocolData));
717
+ return null;
718
+ }
719
+
720
+ FilePacketInfo info = new FilePacketInfo();
721
+ int pos = LENGTH_FILE_START; // Skip start code
722
+
723
+ // File type
724
+ info.fileType = protocolData[pos];
725
+ pos += LENGTH_FILE_TYPE;
726
+
727
+ // Pack size (big-endian)
728
+ info.packSize = ((protocolData[pos] & 0xFF) << 8) | (protocolData[pos + 1] & 0xFF);
729
+ pos += LENGTH_FILE_PACKSIZE;
730
+
731
+ // Pack index (big-endian)
732
+ info.packIndex = ((protocolData[pos] & 0xFF) << 8) | (protocolData[pos + 1] & 0xFF);
733
+ pos += LENGTH_FILE_PACKINDEX;
734
+
735
+ // File size (big-endian)
736
+ info.fileSize = ((protocolData[pos] & 0xFF) << 24) |
737
+ ((protocolData[pos + 1] & 0xFF) << 16) |
738
+ ((protocolData[pos + 2] & 0xFF) << 8) |
739
+ (protocolData[pos + 3] & 0xFF);
740
+ pos += LENGTH_FILE_SIZE;
741
+
742
+ // File name
743
+ byte[] nameBytes = new byte[LENGTH_FILE_NAME];
744
+ System.arraycopy(protocolData, pos, nameBytes, 0, LENGTH_FILE_NAME);
745
+ // Find null terminator
746
+ int nameLen = 0;
747
+ for (int i = 0; i < LENGTH_FILE_NAME; i++) {
748
+ if (nameBytes[i] == 0) break;
749
+ nameLen++;
750
+ }
751
+ info.fileName = new String(nameBytes, 0, nameLen, StandardCharsets.UTF_8);
752
+ pos += LENGTH_FILE_NAME;
753
+
754
+ // Flags (big-endian)
755
+ info.flags = ((protocolData[pos] & 0xFF) << 8) | (protocolData[pos + 1] & 0xFF);
756
+ pos += LENGTH_FILE_FLAG;
757
+
758
+ // Verify packet has enough data
759
+ if (protocolData.length < pos + info.packSize + LENGTH_FILE_VERIFY + LENGTH_FILE_END) {
760
+ Log.e("K900ProtocolUtils", "File packet too short for data. Need: " +
761
+ (pos + info.packSize + LENGTH_FILE_VERIFY + LENGTH_FILE_END) +
762
+ ", Have: " + protocolData.length +
763
+ ", packSize=" + info.packSize + ", pos=" + pos);
764
+ return null;
765
+ }
766
+
767
+ // Data
768
+ info.data = new byte[info.packSize];
769
+ System.arraycopy(protocolData, pos, info.data, 0, info.packSize);
770
+ pos += info.packSize;
771
+
772
+ // Verify code
773
+ info.verifyCode = protocolData[pos];
774
+ pos += LENGTH_FILE_VERIFY;
775
+
776
+ // Check end code
777
+ if (protocolData[pos] != CMD_END_CODE[0] || protocolData[pos + 1] != CMD_END_CODE[1]) {
778
+ return null;
779
+ }
780
+
781
+ // Calculate and verify checksum
782
+ int checkSum = 0;
783
+ for (int i = 0; i < info.packSize; i++) {
784
+ checkSum += (info.data[i] & 0xFF);
785
+ }
786
+ byte calculatedVerify = (byte)(checkSum & 0xFF);
787
+
788
+ info.isValid = (calculatedVerify == info.verifyCode);
789
+
790
+ if (!info.isValid) {
791
+ Log.e("K900ProtocolUtils", "File packet checksum failed. Expected: " +
792
+ String.format("%02X", info.verifyCode) + ", Calculated: " +
793
+ String.format("%02X", calculatedVerify));
794
+ } else if (info.packIndex == 0
795
+ || info.packIndex % 32 == 0
796
+ || info.packIndex == (info.fileSize + FILE_PACK_SIZE - 1) / FILE_PACK_SIZE - 1) {
797
+ Log.d("K900ProtocolUtils", "File packet extracted successfully: index=" + info.packIndex +
798
+ ", size=" + info.packSize + ", fileName=" + info.fileName);
799
+ }
800
+
801
+ return info;
802
+ }
803
+
804
+ /**
805
+ * Create a file transfer acknowledgment message
806
+ *
807
+ * @param state 1 for success, 0 for failure
808
+ * @param index The packet index being acknowledged
809
+ * @return JSON string ready to be sent
810
+ */
811
+ public static String createFileTransferAck(int state, int index) {
812
+ try {
813
+ JSONObject body = new JSONObject();
814
+ body.put("state", state);
815
+ body.put("index", index);
816
+
817
+ JSONObject message = new JSONObject();
818
+ message.put("C", "cs_flts");
819
+ message.put("B", body); // Send as JSON object, not string
820
+
821
+ return message.toString();
822
+ } catch (JSONException e) {
823
+ Log.e("K900ProtocolUtils", "Error creating file transfer ack", e);
824
+ return null;
825
+ }
826
+ }
827
+ }