@mentra/bluetooth-sdk 0.1.0

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 (278) hide show
  1. package/README.md +278 -0
  2. package/android/build.gradle +167 -0
  3. package/android/lc3Lib/CMakeLists.txt +6 -0
  4. package/android/lc3Lib/build.gradle +109 -0
  5. package/android/lc3Lib/proguard-rules.pro +33 -0
  6. package/android/lc3Lib/src/main/AndroidManifest.xml +2 -0
  7. package/android/lc3Lib/src/main/cpp/CMakeLists.txt +8 -0
  8. package/android/lc3Lib/src/main/cpp/google_opus_stuff/CMakeLists.txt +30 -0
  9. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/CMakeLists.txt +7 -0
  10. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.cc +96 -0
  11. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.h +53 -0
  12. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/Makefile.am +6 -0
  13. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h +26 -0
  14. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h.in +26 -0
  15. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/ogg.h +209 -0
  16. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/os_types.h +158 -0
  17. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus.h +981 -0
  18. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_custom.h +342 -0
  19. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_defines.h +799 -0
  20. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_multistream.h +660 -0
  21. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_projection.h +568 -0
  22. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_types.h +166 -0
  23. package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.cc +268 -0
  24. package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.h +115 -0
  25. package/android/lc3Lib/src/main/cpp/google_opus_stuff/opus_tools/opus_header.h +59 -0
  26. package/android/lc3Lib/src/main/cpp/liblc3/CMakeLists.txt +38 -0
  27. package/android/lc3Lib/src/main/cpp/liblc3/include/lc3.h +309 -0
  28. package/android/lc3Lib/src/main/cpp/liblc3/include/lc3_private.h +162 -0
  29. package/android/lc3Lib/src/main/cpp/liblc3/include/rnnoise.h +114 -0
  30. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/CMakeLists.txt +19 -0
  31. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.c +92 -0
  32. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.h +44 -0
  33. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.c +375 -0
  34. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.h +315 -0
  35. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.c +129 -0
  36. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.h +69 -0
  37. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/common.h +148 -0
  38. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.c +70 -0
  39. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.h +43 -0
  40. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/fastmath.h +158 -0
  41. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/lc3.c +702 -0
  42. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.c +893 -0
  43. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.h +111 -0
  44. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_arm.h +506 -0
  45. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_neon.h +281 -0
  46. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/makefile.mk +35 -0
  47. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.c +452 -0
  48. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.h +57 -0
  49. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct_neon.h +296 -0
  50. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/meson.build +46 -0
  51. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.c +61 -0
  52. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.h +57 -0
  53. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.c +880 -0
  54. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.h +103 -0
  55. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.c +904 -0
  56. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.h +119 -0
  57. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.c +3457 -0
  58. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.h +94 -0
  59. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.c +457 -0
  60. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.h +99 -0
  61. package/android/lc3Lib/src/main/cpp/liblc3/liblc3.cpp +159 -0
  62. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/_kiss_fft_guts.h +182 -0
  63. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/arch.h +261 -0
  64. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.c +279 -0
  65. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.h +59 -0
  66. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/common.h +48 -0
  67. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/compile.sh +3 -0
  68. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/denoise.c +646 -0
  69. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.c +601 -0
  70. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.h +203 -0
  71. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/opus_types.h +159 -0
  72. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.c +526 -0
  73. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.h +149 -0
  74. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.c +178 -0
  75. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.h +69 -0
  76. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.c +11051 -0
  77. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.h +34 -0
  78. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_reader.c +168 -0
  79. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_train.py +66 -0
  80. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/tansig_table.h +45 -0
  81. package/android/lc3Lib/src/main/java/com/mentra/lc3Lib/Lc3Cpp.java +38 -0
  82. package/android/lc3Lib/third_party/CMakeLists.txt +23 -0
  83. package/android/lc3Lib/third_party/CMakeLists_libogg.txt +18 -0
  84. package/android/lc3Lib/third_party/CMakeLists_libopus.txt +18 -0
  85. package/android/lc3Lib/third_party/CMakeLists_opus-tools.txt +23 -0
  86. package/android/lc3Lib/third_party/opus_tools/src/AUTHORS +5 -0
  87. package/android/lc3Lib/third_party/opus_tools/src/CMakeLists.txt +4 -0
  88. package/android/lc3Lib/third_party/opus_tools/src/COPYING +371 -0
  89. package/android/lc3Lib/third_party/opus_tools/src/ChangeLog +3 -0
  90. package/android/lc3Lib/third_party/opus_tools/src/Makefile.am +42 -0
  91. package/android/lc3Lib/third_party/opus_tools/src/Makefile.unix +23 -0
  92. package/android/lc3Lib/third_party/opus_tools/src/NEWS +0 -0
  93. package/android/lc3Lib/third_party/opus_tools/src/README +0 -0
  94. package/android/lc3Lib/third_party/opus_tools/src/autogen.sh +115 -0
  95. package/android/lc3Lib/third_party/opus_tools/src/configure.ac +293 -0
  96. package/android/lc3Lib/third_party/opus_tools/src/src/arch.h +239 -0
  97. package/android/lc3Lib/third_party/opus_tools/src/src/audio-in.c +1046 -0
  98. package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.c +245 -0
  99. package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.h +28 -0
  100. package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.c +320 -0
  101. package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.h +51 -0
  102. package/android/lc3Lib/third_party/opus_tools/src/src/lpc.c +157 -0
  103. package/android/lc3Lib/third_party/opus_tools/src/src/lpc.h +27 -0
  104. package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.c +286 -0
  105. package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.h +59 -0
  106. package/android/lc3Lib/third_party/opus_tools/src/src/opusdec.c +884 -0
  107. package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.c +1021 -0
  108. package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.h +101 -0
  109. package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.c +639 -0
  110. package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.h +51 -0
  111. package/android/lc3Lib/third_party/opus_tools/src/src/os_support.h +167 -0
  112. package/android/lc3Lib/third_party/opus_tools/src/src/resample.c +1137 -0
  113. package/android/lc3Lib/third_party/opus_tools/src/src/speex_resampler.h +344 -0
  114. package/android/lc3Lib/third_party/opus_tools/src/src/stack_alloc.h +115 -0
  115. package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.c +125 -0
  116. package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.h +62 -0
  117. package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.c +223 -0
  118. package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.h +60 -0
  119. package/android/settings.gradle +1 -0
  120. package/android/src/main/AndroidManifest.xml +40 -0
  121. package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +528 -0
  122. package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +610 -0
  123. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +1616 -0
  124. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +314 -0
  125. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothModels.kt +1710 -0
  126. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +554 -0
  127. package/android/src/main/java/com/mentra/bluetoothsdk/ObservableStore.kt +68 -0
  128. package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +158 -0
  129. package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +934 -0
  130. package/android/src/main/java/com/mentra/bluetoothsdk/services/Foreground.kt +175 -0
  131. package/android/src/main/java/com/mentra/bluetoothsdk/services/PhoneMic.kt +1109 -0
  132. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +3974 -0
  133. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +3551 -0
  134. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.java +1327 -0
  135. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.java +6959 -0
  136. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +1655 -0
  137. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraosBle.java +53675 -0
  138. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +202 -0
  139. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +224 -0
  140. package/android/src/main/java/com/mentra/bluetoothsdk/stt/STTTools.kt +340 -0
  141. package/android/src/main/java/com/mentra/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +465 -0
  142. package/android/src/main/java/com/mentra/bluetoothsdk/stt/VadGateSpeechPolicy.kt +221 -0
  143. package/android/src/main/java/com/mentra/bluetoothsdk/utils/AES.java +106 -0
  144. package/android/src/main/java/com/mentra/bluetoothsdk/utils/AudioSessionMonitor.kt +189 -0
  145. package/android/src/main/java/com/mentra/bluetoothsdk/utils/BitmapJavaUtils.java +169 -0
  146. package/android/src/main/java/com/mentra/bluetoothsdk/utils/BlePhotoUploadService.java +179 -0
  147. package/android/src/main/java/com/mentra/bluetoothsdk/utils/Constants.kt +44 -0
  148. package/android/src/main/java/com/mentra/bluetoothsdk/utils/G1Text.kt +436 -0
  149. package/android/src/main/java/com/mentra/bluetoothsdk/utils/IncidentLogBleRelayNaming.java +29 -0
  150. package/android/src/main/java/com/mentra/bluetoothsdk/utils/IncidentLogBleUploadService.java +76 -0
  151. package/android/src/main/java/com/mentra/bluetoothsdk/utils/K900ProtocolUtils.java +791 -0
  152. package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunker.java +186 -0
  153. package/android/src/main/java/com/mentra/bluetoothsdk/utils/NexSGCUtils.kt +589 -0
  154. package/android/src/main/java/com/mentra/bluetoothsdk/utils/PhoneAudioMonitor.kt +303 -0
  155. package/android/src/main/java/com/mentra/bluetoothsdk/utils/SmartGlassesConnectionState.java +9 -0
  156. package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/ByteUtilAudioPlayer.java +655 -0
  157. package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/Lc3Player.java +441 -0
  158. package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/PCMAudioPlayer.java +431 -0
  159. package/android/src/main/res/values/strings.xml +4 -0
  160. package/app.plugin.js +1 -0
  161. package/build/BluetoothSdk.types.d.ts +498 -0
  162. package/build/BluetoothSdk.types.d.ts.map +1 -0
  163. package/build/BluetoothSdk.types.js +23 -0
  164. package/build/BluetoothSdk.types.js.map +1 -0
  165. package/build/BluetoothSdkModule.d.ts +71 -0
  166. package/build/BluetoothSdkModule.d.ts.map +1 -0
  167. package/build/BluetoothSdkModule.js +106 -0
  168. package/build/BluetoothSdkModule.js.map +1 -0
  169. package/build/index.d.ts +3 -0
  170. package/build/index.d.ts.map +1 -0
  171. package/build/index.js +5 -0
  172. package/build/index.js.map +1 -0
  173. package/expo-module.config.json +9 -0
  174. package/ios/BluetoothSdkModule.swift +665 -0
  175. package/ios/MentraBluetoothSDK.podspec +77 -0
  176. package/ios/Packages/CoreObjC/CoreObjC.xcodeproj/project.pbxproj +213 -0
  177. package/ios/Packages/CoreObjC/PcmConverter.h +22 -0
  178. package/ios/Packages/CoreObjC/PcmConverter.m +266 -0
  179. package/ios/Packages/CoreObjC/attdet.c +92 -0
  180. package/ios/Packages/CoreObjC/attdet.h +44 -0
  181. package/ios/Packages/CoreObjC/bits.c +375 -0
  182. package/ios/Packages/CoreObjC/bits.h +315 -0
  183. package/ios/Packages/CoreObjC/bwdet.c +129 -0
  184. package/ios/Packages/CoreObjC/bwdet.h +69 -0
  185. package/ios/Packages/CoreObjC/common.h +151 -0
  186. package/ios/Packages/CoreObjC/energy.c +70 -0
  187. package/ios/Packages/CoreObjC/energy.h +43 -0
  188. package/ios/Packages/CoreObjC/fastmath.h +158 -0
  189. package/ios/Packages/CoreObjC/lc3.c +704 -0
  190. package/ios/Packages/CoreObjC/lc3.h +313 -0
  191. package/ios/Packages/CoreObjC/lc3_cpp.h +283 -0
  192. package/ios/Packages/CoreObjC/lc3_private.h +163 -0
  193. package/ios/Packages/CoreObjC/ltpf.c +905 -0
  194. package/ios/Packages/CoreObjC/ltpf.h +111 -0
  195. package/ios/Packages/CoreObjC/ltpf_arm.h +506 -0
  196. package/ios/Packages/CoreObjC/ltpf_neon.h +281 -0
  197. package/ios/Packages/CoreObjC/makefile.mk +35 -0
  198. package/ios/Packages/CoreObjC/mdct.c +469 -0
  199. package/ios/Packages/CoreObjC/mdct.h +57 -0
  200. package/ios/Packages/CoreObjC/mdct_neon.h +296 -0
  201. package/ios/Packages/CoreObjC/meson.build +61 -0
  202. package/ios/Packages/CoreObjC/plc.c +61 -0
  203. package/ios/Packages/CoreObjC/plc.h +57 -0
  204. package/ios/Packages/CoreObjC/rnnoise.h +114 -0
  205. package/ios/Packages/CoreObjC/sns.c +880 -0
  206. package/ios/Packages/CoreObjC/sns.h +103 -0
  207. package/ios/Packages/CoreObjC/spec.c +907 -0
  208. package/ios/Packages/CoreObjC/spec.h +119 -0
  209. package/ios/Packages/CoreObjC/tables.c +3457 -0
  210. package/ios/Packages/CoreObjC/tables.h +94 -0
  211. package/ios/Packages/CoreObjC/tns.c +457 -0
  212. package/ios/Packages/CoreObjC/tns.h +99 -0
  213. package/ios/Packages/SherpaOnnx/Model/joiner.onnx +0 -0
  214. package/ios/Packages/SherpaOnnx/Model/tokens.txt +502 -0
  215. package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +1659 -0
  216. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/cargs.h +162 -0
  217. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/sherpa-onnx/c-api/c-api.h +1852 -0
  218. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/sherpa-onnx/c-api/cxx-api.h +674 -0
  219. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +44 -0
  220. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
  221. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/sherpa-onnx.a +0 -0
  222. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
  223. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/sherpa-onnx.a +0 -0
  224. package/ios/Packages/VAD/Common/VAD/VADQuality.swift +41 -0
  225. package/ios/Packages/VAD/Common/VAD/VADState.swift +26 -0
  226. package/ios/Packages/VAD/Common/VAD/VADStrategy.swift +29 -0
  227. package/ios/Packages/VAD/Common/VAD/VADType.swift +14 -0
  228. package/ios/Packages/VAD/Data/Configuration.swift +68 -0
  229. package/ios/Packages/VAD/Data/FrameSize.swift +39 -0
  230. package/ios/Packages/VAD/Data/Record.swift +13 -0
  231. package/ios/Packages/VAD/Data/Result.swift +22 -0
  232. package/ios/Packages/VAD/Data/SampleRate.swift +48 -0
  233. package/ios/Packages/VAD/Silero/Model/silero_vad.onnx +0 -0
  234. package/ios/Packages/VAD/Silero/SileroVAD.swift +284 -0
  235. package/ios/Packages/VAD/Silero/SileroVADStrategy.swift +64 -0
  236. package/ios/Packages/libbz2/module.modulemap +5 -0
  237. package/ios/Packages/libbz2/shim.h +1 -0
  238. package/ios/Source/Bridge.swift +353 -0
  239. package/ios/Source/Bridging-Header.h +16 -0
  240. package/ios/Source/DeviceManager.swift +1478 -0
  241. package/ios/Source/DeviceStore.swift +295 -0
  242. package/ios/Source/MentraBluetoothSDK.swift +2439 -0
  243. package/ios/Source/ObservableStore.swift +88 -0
  244. package/ios/Source/PrivacyInfo.xcprivacy +23 -0
  245. package/ios/Source/controllers/ControllerManager.swift +187 -0
  246. package/ios/Source/controllers/R1.swift +827 -0
  247. package/ios/Source/services/PhoneMic.swift +662 -0
  248. package/ios/Source/sgcs/Frame.swift +651 -0
  249. package/ios/Source/sgcs/G1.swift +2505 -0
  250. package/ios/Source/sgcs/G2.swift +3730 -0
  251. package/ios/Source/sgcs/Mach1.swift +543 -0
  252. package/ios/Source/sgcs/MentraLive.swift +4708 -0
  253. package/ios/Source/sgcs/MentraNex.swift +2479 -0
  254. package/ios/Source/sgcs/SGCManager.swift +243 -0
  255. package/ios/Source/sgcs/Simulated.swift +270 -0
  256. package/ios/Source/sgcs/mentraos_ble.pb.swift +3811 -0
  257. package/ios/Source/stt/STTTools.swift +154 -0
  258. package/ios/Source/stt/SherpaOnnxTranscriber.swift +401 -0
  259. package/ios/Source/utils/AudioSessionMonitor.swift +283 -0
  260. package/ios/Source/utils/Constants.swift +74 -0
  261. package/ios/Source/utils/Enums.swift +95 -0
  262. package/ios/Source/utils/G1Text.swift +2067 -0
  263. package/ios/Source/utils/JSCExperiment.swift +241 -0
  264. package/ios/Source/utils/MemoryMonitor.swift +44 -0
  265. package/ios/Source/utils/MessageChunker.swift +164 -0
  266. package/ios/Source/utils/Models.swift +135 -0
  267. package/ios/Source/utils/PhoneAudioMonitor.swift +226 -0
  268. package/ios/Source/utils/TarBz2Extractor.swift +206 -0
  269. package/package.json +78 -0
  270. package/plugin/build/index.d.ts +6 -0
  271. package/plugin/build/index.js +12 -0
  272. package/plugin/build/withAndroid.d.ts +4 -0
  273. package/plugin/build/withAndroid.js +80 -0
  274. package/plugin/build/withIos.d.ts +4 -0
  275. package/plugin/build/withIos.js +64 -0
  276. package/src/BluetoothSdk.types.ts +581 -0
  277. package/src/BluetoothSdkModule.ts +259 -0
  278. package/src/index.ts +4 -0
@@ -0,0 +1,791 @@
1
+ package com.mentra.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
+
31
+ // File transfer constants
32
+ public static final int FILE_PACK_SIZE = 400; // Max data size per packet
33
+ public static final int LENGTH_FILE_START = 2;
34
+ public static final int LENGTH_FILE_TYPE = 1;
35
+ public static final int LENGTH_FILE_PACKSIZE = 2;
36
+ public static final int LENGTH_FILE_PACKINDEX = 2;
37
+ public static final int LENGTH_FILE_SIZE = 4;
38
+ public static final int LENGTH_FILE_NAME = 16;
39
+ public static final int LENGTH_FILE_FLAG = 2;
40
+ public static final int LENGTH_FILE_VERIFY = 1;
41
+ public static final int LENGTH_FILE_END = 2;
42
+
43
+ // JSON Field constants
44
+ public static final String FIELD_C = "C"; // Command/Content field
45
+ public static final String FIELD_V = "V"; // Version field
46
+ public static final String FIELD_B = "B"; // Body field
47
+
48
+ /**
49
+ * Pack a JSON string into the proper K900 format:
50
+ * 1. Wrap with C-field: {"C": jsonData}
51
+ * 2. Then pack with BES2700 protocol: ## + type + length + {"C": jsonData} + $$
52
+ *
53
+ * @param jsonData The JSON string to pack
54
+ * @return Byte array with packed data according to protocol format
55
+ */
56
+ public static byte[] packJsonCommand(String jsonData) {
57
+ if (jsonData == null) {
58
+ return null;
59
+ }
60
+
61
+ try {
62
+ // First wrap with C-field
63
+ JSONObject wrapper = new JSONObject();
64
+ wrapper.put(FIELD_C, jsonData);
65
+
66
+ // Convert to string
67
+ String wrappedJson = wrapper.toString();
68
+
69
+ // Then pack with BES2700 protocol format
70
+ byte[] jsonBytes = wrappedJson.getBytes(StandardCharsets.UTF_8);
71
+ return packDataCommand(jsonBytes, CMD_TYPE_STRING);
72
+
73
+ } catch (JSONException e) {
74
+ android.util.Log.e("K900ProtocolUtils", "Error creating JSON wrapper", e);
75
+ return null;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Pack raw byte data with K900 BES2700 protocol format
81
+ * Format: ## + command_type + length(2bytes) + data + $$
82
+ *
83
+ * @param data The raw data to pack
84
+ * @param cmdType The command type (use CMD_TYPE_STRING for JSON)
85
+ * @return Byte array with packed data according to protocol format
86
+ */
87
+ public static byte[] packDataCommand(byte[] data, byte cmdType) {
88
+ if (data == null) {
89
+ return null;
90
+ }
91
+
92
+ int dataLength = data.length;
93
+
94
+ // Command structure: ## + type + length(2 bytes) + data + $$
95
+ byte[] result = new byte[dataLength + 7]; // 2(start) + 1(type) + 2(length) + data + 2(end)
96
+
97
+ // Start code ##
98
+ result[0] = CMD_START_CODE[0]; // #
99
+ result[1] = CMD_START_CODE[1]; // #
100
+
101
+ // Command type
102
+ result[2] = cmdType;
103
+
104
+ // Length (2 bytes, big-endian)
105
+ result[3] = (byte)((dataLength >> 8) & 0xFF); // MSB first
106
+ result[4] = (byte)(dataLength & 0xFF); // LSB second
107
+
108
+ // Original little-endian implementation (commented out)
109
+ // result[3] = (byte)(dataLength & 0xFF); // LSB first
110
+ // result[4] = (byte)((dataLength >> 8) & 0xFF); // MSB second
111
+
112
+ // Copy the data
113
+ System.arraycopy(data, 0, result, 5, dataLength);
114
+
115
+ // End code $$
116
+ result[5 + dataLength] = CMD_END_CODE[0]; // $
117
+ result[6 + dataLength] = CMD_END_CODE[1]; // $
118
+
119
+ return result;
120
+ }
121
+
122
+ /**
123
+ * Pack raw byte data with K900 BES2700 protocol format for phone-to-device communication
124
+ * Format: ## + command_type + length(2bytes) + data + $$
125
+ * Uses little-endian byte order for length field
126
+ *
127
+ * @param data The raw data to pack
128
+ * @param cmdType The command type (use CMD_TYPE_STRING for JSON)
129
+ * @return Byte array with packed data according to protocol format
130
+ */
131
+ public static byte[] packDataToK900(byte[] data, byte cmdType) {
132
+ if (data == null) {
133
+ return null;
134
+ }
135
+
136
+ int dataLength = data.length;
137
+
138
+ // Command structure: ## + type + length(2 bytes) + data + $$
139
+ byte[] result = new byte[dataLength + 7]; // 2(start) + 1(type) + 2(length) + data + 2(end)
140
+
141
+ // Start code ##
142
+ result[0] = CMD_START_CODE[0]; // #
143
+ result[1] = CMD_START_CODE[1]; // #
144
+
145
+ // Command type
146
+ result[2] = cmdType;
147
+
148
+ // Length (2 bytes, little-endian for phone-to-device)
149
+ result[3] = (byte) (dataLength & 0xFF); // LSB first
150
+ result[4] = (byte) ((dataLength >> 8) & 0xFF); // MSB second
151
+
152
+ // Copy the data
153
+ System.arraycopy(data, 0, result, 5, dataLength);
154
+
155
+ // End code $$
156
+ result[5 + dataLength] = CMD_END_CODE[0]; // $
157
+ result[6 + dataLength] = CMD_END_CODE[1]; // $
158
+
159
+ return result;
160
+ }
161
+
162
+ /**
163
+ * Pack a JSON string for phone-to-K900 device communication
164
+ * 1. Wrap with C-field: {"C": jsonData}
165
+ * 2. Then pack with BES2700 protocol using little-endian: ## + type + length + {"C": jsonData} + $$
166
+ *
167
+ * @param jsonData The JSON string to pack
168
+ * @return Byte array with packed data according to protocol format
169
+ */
170
+ public static byte[] packJsonToK900(String jsonData, boolean wakeup) {
171
+ if (jsonData == null) {
172
+ return null;
173
+ }
174
+
175
+ try {
176
+ // First wrap with C-field
177
+ JSONObject wrapper = new JSONObject();
178
+ wrapper.put(FIELD_C, jsonData);
179
+ if (wakeup) {
180
+ wrapper.put("W", 1); // Add W field as seen in MentraLiveSGC
181
+ }
182
+
183
+ // Convert to string
184
+ String wrappedJson = wrapper.toString();
185
+
186
+ // Then pack with BES2700 protocol format using little-endian
187
+ byte[] jsonBytes = wrappedJson.getBytes(StandardCharsets.UTF_8);
188
+ return packDataToK900(jsonBytes, CMD_TYPE_STRING);
189
+
190
+ } catch (JSONException e) {
191
+ android.util.Log.e("K900ProtocolUtils", "Error creating JSON wrapper for K900", e);
192
+ return null;
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Formats a standard ASG-client JSON message for transmission to MentraLiveSGC
198
+ * This does both:
199
+ * 1. Wrap with C-field: {"C": jsonData}
200
+ * 2. Format with BES2700 protocol: ## + type + length + data + $$
201
+ *
202
+ * @param jsonData The JSON string to format (must be valid JSON)
203
+ * @return Formatted bytes ready for transmission
204
+ */
205
+ public static byte[] formatMessageForTransmission(String jsonData) {
206
+ try {
207
+ android.util.Log.e("K900ProtocolUtils", "🔄 Formatting message: " + jsonData);
208
+
209
+ // Validate that input is proper JSON
210
+ new JSONObject(jsonData);
211
+
212
+ // First, create C wrapper: {"C": jsonData}
213
+ JSONObject wrapper = new JSONObject();
214
+ wrapper.put(FIELD_C, jsonData);
215
+ wrapper.put(FIELD_V, 1); // Optional version field
216
+ wrapper.put(FIELD_B, new JSONObject()); // Optional body field
217
+ String wrappedJson = wrapper.toString();
218
+ android.util.Log.e("K900ProtocolUtils", "🔄 After C-wrapping: " + wrappedJson);
219
+
220
+ // Now format with BES2700 protocol
221
+ byte[] result = packDataCommand(wrappedJson.getBytes(StandardCharsets.UTF_8), CMD_TYPE_STRING);
222
+
223
+ // Log some bytes for debugging
224
+ StringBuilder hexDump = new StringBuilder();
225
+ for (int i = 0; i < Math.min(result.length, 30); i++) {
226
+ hexDump.append(String.format("%02X ", result[i]));
227
+ }
228
+ //android.util.Log.e("K900ProtocolUtils", "🔄 After protocol formatting (first 30 bytes): " + hexDump);
229
+ //android.util.Log.e("K900ProtocolUtils", "🔄 Final length: " + result.length + " bytes");
230
+
231
+ return result;
232
+
233
+ } catch (JSONException e) {
234
+ android.util.Log.e("K900ProtocolUtils", "❌ Error in formatMessageForTransmission", e);
235
+ // Fallback: if json is invalid, still try to pack it without validation
236
+ return packJsonCommand(jsonData);
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Create a C-wrapped JSON object ready for protocol formatting
242
+ * Format: {"C": content}
243
+ *
244
+ * @param content The content to wrap in the C field
245
+ * @return C-wrapped JSON string
246
+ */
247
+ public static String createCWrappedJson(String content) {
248
+ try {
249
+ JSONObject wrapper = new JSONObject();
250
+ wrapper.put(FIELD_C, content);
251
+ return wrapper.toString();
252
+ } catch (JSONException e) {
253
+ android.util.Log.e("K900ProtocolUtils", "Error creating C-wrapped JSON", e);
254
+ return null;
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Check if data follows the K900 BES2700 protocol format
260
+ * Verifies if data starts with ## markers
261
+ */
262
+ public static boolean isK900ProtocolFormat(byte[] data) {
263
+ if (data == null || data.length < 7) { // Minimum protocol size
264
+ return false;
265
+ }
266
+
267
+ Log.d("K900ProtocolUtils", "isK900ProtocolFormat: " + data[0] + " " + data[1]);
268
+ Log.d("K900ProtocolUtils", "CMD_START_CODE: " + CMD_START_CODE[0] + " " + CMD_START_CODE[1]);
269
+
270
+ return data[0] == CMD_START_CODE[0] &&
271
+ data[1] == CMD_START_CODE[1];
272
+ }
273
+
274
+ /**
275
+ * Check if a JSON string is already properly formatted for K900 protocol
276
+ * This can either be:
277
+ * 1. Simple C-wrapped format: {"C": "content"}
278
+ * 2. Full K900 format: {"C": "command", "V": value, "B": body}
279
+ *
280
+ * @return true if already in proper format, false otherwise
281
+ */
282
+ public static boolean isCWrappedJson(String jsonStr) {
283
+ try {
284
+ JSONObject json = new JSONObject(jsonStr);
285
+
286
+ // Check for simple C-wrapping {"C": "content"} - only one field
287
+ if (json.has(FIELD_C) && json.length() == 1) {
288
+ return true;
289
+ }
290
+
291
+ // Check for full K900 format {"C": "command", "V": val, "B": body}
292
+ if (json.has(FIELD_C) && json.has(FIELD_V) && json.has(FIELD_B)) {
293
+ return true;
294
+ }
295
+
296
+ return false;
297
+ } catch (JSONException e) {
298
+ return false;
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Extract payload from K900 protocol formatted data
304
+ * @return Raw payload data or null if format is invalid
305
+ */
306
+ public static byte[] extractPayload(byte[] protocolData) {
307
+ if (!isK900ProtocolFormat(protocolData) || protocolData.length < 7) {
308
+ return null;
309
+ }
310
+
311
+ // Extract length (big-endian)
312
+ int length = ((protocolData[3] & 0xFF) << 8) | (protocolData[4] & 0xFF);
313
+
314
+ // Original little-endian implementation (commented out)
315
+ // int length = (protocolData[3] & 0xFF) | ((protocolData[4] & 0xFF) << 8);
316
+
317
+ if (length + 7 > protocolData.length) {
318
+ return null; // Invalid length
319
+ }
320
+
321
+ // Extract payload
322
+ byte[] payload = new byte[length];
323
+ System.arraycopy(protocolData, 5, payload, 0, length);
324
+ return payload;
325
+ }
326
+
327
+ /**
328
+ * Extract payload from K900 protocol formatted data received from device
329
+ * Uses little-endian byte order for length field
330
+ * @return Raw payload data or null if format is invalid
331
+ */
332
+ public static byte[] extractPayloadFromK900(byte[] protocolData) {
333
+ if (!isK900ProtocolFormat(protocolData) || protocolData.length < 7) {
334
+ Log.e("K900ProtocolUtils", "extractPayloadFromK900: Not K900 format or too short. Length=" +
335
+ (protocolData != null ? protocolData.length : 0));
336
+ return null;
337
+ }
338
+
339
+ // Extract length (little-endian for device-to-phone)
340
+ int length = (protocolData[3] & 0xFF) | ((protocolData[4] & 0xFF) << 8);
341
+
342
+ Log.d("K900ProtocolUtils", "extractPayloadFromK900: Extracted length=" + length +
343
+ ", message length=" + protocolData.length + ", expected total=" + (length + 7));
344
+
345
+ if (length + 7 > protocolData.length) {
346
+ Log.e("K900ProtocolUtils", "extractPayloadFromK900: Invalid length. Need " +
347
+ (length + 7) + " bytes but have " + protocolData.length);
348
+ return null; // Invalid length
349
+ }
350
+
351
+ // Extract payload
352
+ byte[] payload = new byte[length];
353
+ System.arraycopy(protocolData, 5, payload, 0, length);
354
+ return payload;
355
+ }
356
+
357
+ /**
358
+ * Process received bytes from Bluetooth into a JSON object
359
+ * Handles K900 protocol format detection, payload extraction, and C-field unwrapping
360
+ *
361
+ * @param data The raw bytes received from Bluetooth
362
+ * @return Parsed JSON object or null if not valid protocol data or valid JSON
363
+ */
364
+ public static JSONObject processReceivedBytesToJson(byte[] data) {
365
+ android.util.Log.d("K900ProtocolUtils", "Processing received bytes for JSON extraction");
366
+
367
+ // Check for null or too small data
368
+ if (data == null || data.length < 7) {
369
+ android.util.Log.d("K900ProtocolUtils", "Received data is null or too short to be valid protocol data");
370
+ return null;
371
+ }
372
+
373
+ // Verify if this is K900 protocol format (starts with ##)
374
+ if (!isK900ProtocolFormat(data)) {
375
+ android.util.Log.d("K900ProtocolUtils", "Not in K900 protocol format (missing ## markers)");
376
+ return null;
377
+ }
378
+
379
+ // Extract the command type
380
+ byte commandType = data[2];
381
+
382
+ // Extract the length using big-endian format (MSB first)
383
+ int payloadLength = ((data[3] & 0xFF) << 8) | (data[4] & 0xFF);
384
+
385
+ android.util.Log.d("K900ProtocolUtils", "Command type: 0x" + String.format("%02X", commandType) +
386
+ ", Payload length: " + payloadLength);
387
+
388
+ // Verify we have enough data and the right command type
389
+ if (commandType != CMD_TYPE_STRING) {
390
+ android.util.Log.d("K900ProtocolUtils", "Not a JSON/string command type (0x30), got: 0x" +
391
+ String.format("%02X", commandType));
392
+ return null;
393
+ }
394
+
395
+ if (data.length < payloadLength + 7) {
396
+ android.util.Log.d("K900ProtocolUtils", "Received data size (" + data.length +
397
+ ") is less than expected size (" + (payloadLength + 7) + ")");
398
+ return null;
399
+ }
400
+
401
+ // Check for end markers ($$)
402
+ if (data[5 + payloadLength] != CMD_END_CODE[0] || data[6 + payloadLength] != CMD_END_CODE[1]) {
403
+ android.util.Log.d("K900ProtocolUtils", "End markers ($$) not found where expected");
404
+ return null;
405
+ }
406
+
407
+ // Extract the payload
408
+ byte[] payload = new byte[payloadLength];
409
+ System.arraycopy(data, 5, payload, 0, payloadLength);
410
+
411
+ // Convert to string
412
+ String payloadStr;
413
+ try {
414
+ payloadStr = new String(payload, StandardCharsets.UTF_8);
415
+ android.util.Log.d("K900ProtocolUtils", "Extracted payload: " + payloadStr);
416
+ } catch (Exception e) {
417
+ android.util.Log.e("K900ProtocolUtils", "Error converting payload to string", e);
418
+ return null;
419
+ }
420
+
421
+ // Check if it's valid JSON
422
+ if (!payloadStr.startsWith("{") || !payloadStr.endsWith("}")) {
423
+ android.util.Log.d("K900ProtocolUtils", "Payload is not valid JSON: " + payloadStr);
424
+ return null;
425
+ }
426
+
427
+ try {
428
+ // Parse the JSON payload
429
+ JSONObject json = new JSONObject(payloadStr);
430
+
431
+ // Check if this is C-wrapped format {"C": "..."}
432
+ if (json.has(FIELD_C)) {
433
+ String innerContent = json.optString(FIELD_C, "");
434
+ android.util.Log.d("K900ProtocolUtils", "Detected C-wrapped format, inner content: " + innerContent);
435
+
436
+ // Try to parse the inner content as JSON
437
+ try {
438
+ JSONObject innerJson = new JSONObject(innerContent);
439
+ return innerJson;
440
+ } catch (JSONException e) {
441
+ android.util.Log.d("K900ProtocolUtils", "Inner content is not JSON, returning outer JSON object");
442
+ // If inner content is not JSON, return the outer JSON
443
+ return json;
444
+ }
445
+ } else {
446
+ // Not C-wrapped, return the JSON directly
447
+ return json;
448
+ }
449
+ } catch (JSONException e) {
450
+ android.util.Log.e("K900ProtocolUtils", "Error parsing JSON payload: " + e.getMessage(), e);
451
+ return null;
452
+ }
453
+ }
454
+
455
+ /**
456
+ * Unified method to prepare data for transmission according to K900 protocol
457
+ * This handles all formatting cases:
458
+ * 1. Data already in protocol format
459
+ * 2. JSON data that needs C-wrapping
460
+ * 3. Raw data that needs protocol packaging
461
+ *
462
+ * @param data The raw data to prepare for transmission
463
+ * @return Properly formatted data according to K900 protocol
464
+ */
465
+ public static byte[] prepareDataForTransmission(byte[] data) {
466
+ if (data == null || data.length == 0) {
467
+ return null;
468
+ }
469
+
470
+ // If already in protocol format, don't modify
471
+ if (isK900ProtocolFormat(data)) {
472
+ return data;
473
+ }
474
+
475
+ // Try to interpret as a JSON string that needs C-wrapping and protocol formatting
476
+ try {
477
+ // Convert to string for processing
478
+ String originalData = new String(data, "UTF-8");
479
+
480
+ // If looks like JSON but not C-wrapped, use the full formatting function
481
+ if (originalData.startsWith("{") && !isCWrappedJson(originalData)) {
482
+ android.util.Log.d("K900ProtocolUtils", "📦 JSON DATA BEFORE C-WRAPPING: " + originalData);
483
+ byte[] formattedData = formatMessageForTransmission(originalData);
484
+
485
+ // Debug log the formatting results if needed
486
+ if (android.util.Log.isLoggable("K900ProtocolUtils", android.util.Log.DEBUG)) {
487
+ StringBuilder hexDump = new StringBuilder();
488
+ for (int i = 0; i < Math.min(formattedData.length, 50); i++) {
489
+ hexDump.append(String.format("%02X ", formattedData[i]));
490
+ }
491
+ android.util.Log.d("K900ProtocolUtils", "📦 AFTER C-WRAPPING & PROTOCOL FORMATTING (first 50 bytes): " + hexDump.toString());
492
+ android.util.Log.d("K900ProtocolUtils", "📦 Total formatted length: " + formattedData.length + " bytes");
493
+ }
494
+
495
+ return formattedData;
496
+ } else {
497
+ // Otherwise just apply protocol formatting
498
+ android.util.Log.d("K900ProtocolUtils", "📦 Data already C-wrapped or not JSON: " + originalData);
499
+ android.util.Log.d("K900ProtocolUtils", "Formatting data with K900 protocol (adding ##...)");
500
+ return packDataCommand(data, CMD_TYPE_STRING);
501
+ }
502
+ } catch (Exception e) {
503
+ // If we can't interpret as string, just apply protocol formatting to raw bytes
504
+ android.util.Log.d("K900ProtocolUtils", "Applying protocol format to raw bytes");
505
+ return packDataCommand(data, CMD_TYPE_STRING);
506
+ }
507
+ }
508
+
509
+ /**
510
+ * Check if the device is a K900
511
+ * @param context The application context
512
+ * @return true if the device is a K900, false otherwise
513
+ */
514
+ public static boolean isK900Device(Context context) {
515
+ // Check for K900-specific broadcast receivers
516
+ try {
517
+ // Verify the SystemUI package exists
518
+ PackageManager pm = context.getPackageManager();
519
+ pm.getPackageInfo("com.android.systemui", 0);
520
+
521
+ // Check for K900-specific system action
522
+ try {
523
+ // Set up a result receiver to check if our probe was received
524
+ final boolean[] responseReceived = {false};
525
+ BroadcastReceiver testReceiver = new BroadcastReceiver() {
526
+ @Override
527
+ public void onReceive(Context context, Intent intent) {
528
+ responseReceived[0] = true;
529
+ try {
530
+ context.unregisterReceiver(this);
531
+ } catch (Exception e) {
532
+ // Ignore unregister failures
533
+ }
534
+ }
535
+ };
536
+
537
+ // Register for any response from our probe
538
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
539
+ context.registerReceiver(testReceiver,
540
+ new IntentFilter("com.xy.xsetting.response"),
541
+ Context.RECEIVER_NOT_EXPORTED);
542
+ } else {
543
+ context.registerReceiver(testReceiver,
544
+ new IntentFilter("com.xy.xsetting.response"),
545
+ Context.RECEIVER_NOT_EXPORTED);
546
+ }
547
+
548
+ // Send a test probe
549
+ Intent testIntent = new Intent("com.xy.xsetting.action");
550
+ testIntent.setPackage("com.android.systemui");
551
+ testIntent.putExtra("cmd", "test_k900");
552
+ context.sendBroadcast(testIntent);
553
+
554
+ // In a real implementation, we would wait for a response
555
+ // For now, we check device model as a fallback
556
+ String model = android.os.Build.MODEL.toLowerCase();
557
+ return model.contains("k900") || model.contains("xyglasses");
558
+ } catch (Exception e) {
559
+ Log.e("K900ProtocolUtils", "Error checking for K900 specific broadcast", e);
560
+ }
561
+ } catch (Exception e) {
562
+ Log.d("K900ProtocolUtils", "Not a K900 device: " + e.getMessage());
563
+ }
564
+
565
+ return false;
566
+ }
567
+
568
+ /**
569
+ * Inner class to represent file packet information
570
+ */
571
+ public static class FilePacketInfo {
572
+ public byte fileType;
573
+ public int packSize;
574
+ public int packIndex;
575
+ public int fileSize;
576
+ public String fileName;
577
+ public int flags;
578
+ public byte[] data;
579
+ public byte verifyCode;
580
+ public boolean isValid;
581
+
582
+ public FilePacketInfo() {
583
+ this.isValid = false;
584
+ }
585
+ }
586
+
587
+ /**
588
+ * Pack a file packet according to K900 file transfer protocol
589
+ * Format: ## + fileType + packSize + packIndex + fileSize + fileName + flags + data + verify + $$
590
+ *
591
+ * @param fileData The file data chunk to send (max 400 bytes)
592
+ * @param packIndex The index of this packet (0-based)
593
+ * @param packSize The size of data in this packet
594
+ * @param fileSize The total file size
595
+ * @param fileName The file name (max 16 chars)
596
+ * @param flags Optional flags
597
+ * @param fileType The file type (CMD_TYPE_PHOTO, etc)
598
+ * @return Packed byte array ready for transmission
599
+ */
600
+ public static byte[] packFilePacket(byte[] fileData, int packIndex, int packSize,
601
+ int fileSize, String fileName, int flags, byte fileType) {
602
+ if (fileData == null || packSize > FILE_PACK_SIZE) {
603
+ return null;
604
+ }
605
+
606
+ // Calculate total packet size
607
+ int totalSize = LENGTH_FILE_START + LENGTH_FILE_TYPE + LENGTH_FILE_PACKSIZE +
608
+ LENGTH_FILE_PACKINDEX + LENGTH_FILE_SIZE + LENGTH_FILE_NAME +
609
+ LENGTH_FILE_FLAG + packSize + LENGTH_FILE_VERIFY + LENGTH_FILE_END;
610
+
611
+ byte[] packet = new byte[totalSize];
612
+ int pos = 0;
613
+
614
+ // Start code ##
615
+ System.arraycopy(CMD_START_CODE, 0, packet, pos, LENGTH_FILE_START);
616
+ pos += LENGTH_FILE_START;
617
+
618
+ // File type
619
+ packet[pos] = fileType;
620
+ pos += LENGTH_FILE_TYPE;
621
+
622
+ // Pack size (2 bytes, big-endian like reference implementation)
623
+ packet[pos] = (byte)((packSize >> 8) & 0xFF);
624
+ packet[pos + 1] = (byte)(packSize & 0xFF);
625
+ pos += LENGTH_FILE_PACKSIZE;
626
+
627
+ // Pack index (2 bytes, big-endian)
628
+ packet[pos] = (byte)((packIndex >> 8) & 0xFF);
629
+ packet[pos + 1] = (byte)(packIndex & 0xFF);
630
+ pos += LENGTH_FILE_PACKINDEX;
631
+
632
+ // File size (4 bytes, big-endian)
633
+ packet[pos] = (byte)((fileSize >> 24) & 0xFF);
634
+ packet[pos + 1] = (byte)((fileSize >> 16) & 0xFF);
635
+ packet[pos + 2] = (byte)((fileSize >> 8) & 0xFF);
636
+ packet[pos + 3] = (byte)(fileSize & 0xFF);
637
+ pos += LENGTH_FILE_SIZE;
638
+
639
+ // File name (16 bytes, padded with zeros)
640
+ byte[] nameBytes = fileName.getBytes(StandardCharsets.UTF_8);
641
+ int nameLen = Math.min(nameBytes.length, LENGTH_FILE_NAME);
642
+ System.arraycopy(nameBytes, 0, packet, pos, nameLen);
643
+ // Pad with zeros if name is shorter than 16 bytes
644
+ for (int i = nameLen; i < LENGTH_FILE_NAME; i++) {
645
+ packet[pos + i] = 0;
646
+ }
647
+ pos += LENGTH_FILE_NAME;
648
+
649
+ // Flags (2 bytes, big-endian)
650
+ packet[pos] = (byte)((flags >> 8) & 0xFF);
651
+ packet[pos + 1] = (byte)(flags & 0xFF);
652
+ pos += LENGTH_FILE_FLAG;
653
+
654
+ // Data
655
+ System.arraycopy(fileData, 0, packet, pos, packSize);
656
+ pos += packSize;
657
+
658
+ // Calculate verify code (checksum of data bytes)
659
+ int checkSum = 0;
660
+ for (int i = 0; i < packSize; i++) {
661
+ checkSum += (fileData[i] & 0xFF);
662
+ }
663
+ packet[pos] = (byte)(checkSum & 0xFF);
664
+ pos += LENGTH_FILE_VERIFY;
665
+
666
+ // End code $$
667
+ System.arraycopy(CMD_END_CODE, 0, packet, pos, LENGTH_FILE_END);
668
+
669
+ return packet;
670
+ }
671
+
672
+ /**
673
+ * Extract file packet information from received protocol data
674
+ *
675
+ * @param protocolData The raw protocol data received
676
+ * @return FilePacketInfo object with parsed data, or null if invalid
677
+ */
678
+ public static FilePacketInfo extractFilePacket(byte[] protocolData) {
679
+ if (!isK900ProtocolFormat(protocolData) || protocolData.length < 31) {
680
+ Log.e("K900ProtocolUtils", "extractFilePacket: Invalid format or too short. Length=" +
681
+ (protocolData != null ? protocolData.length : 0) +
682
+ ", isK900Format=" + isK900ProtocolFormat(protocolData));
683
+ return null;
684
+ }
685
+
686
+ FilePacketInfo info = new FilePacketInfo();
687
+ int pos = LENGTH_FILE_START; // Skip start code
688
+
689
+ // File type
690
+ info.fileType = protocolData[pos];
691
+ pos += LENGTH_FILE_TYPE;
692
+
693
+ // Pack size (big-endian)
694
+ info.packSize = ((protocolData[pos] & 0xFF) << 8) | (protocolData[pos + 1] & 0xFF);
695
+ pos += LENGTH_FILE_PACKSIZE;
696
+
697
+ // Pack index (big-endian)
698
+ info.packIndex = ((protocolData[pos] & 0xFF) << 8) | (protocolData[pos + 1] & 0xFF);
699
+ pos += LENGTH_FILE_PACKINDEX;
700
+
701
+ // File size (big-endian)
702
+ info.fileSize = ((protocolData[pos] & 0xFF) << 24) |
703
+ ((protocolData[pos + 1] & 0xFF) << 16) |
704
+ ((protocolData[pos + 2] & 0xFF) << 8) |
705
+ (protocolData[pos + 3] & 0xFF);
706
+ pos += LENGTH_FILE_SIZE;
707
+
708
+ // File name
709
+ byte[] nameBytes = new byte[LENGTH_FILE_NAME];
710
+ System.arraycopy(protocolData, pos, nameBytes, 0, LENGTH_FILE_NAME);
711
+ // Find null terminator
712
+ int nameLen = 0;
713
+ for (int i = 0; i < LENGTH_FILE_NAME; i++) {
714
+ if (nameBytes[i] == 0) break;
715
+ nameLen++;
716
+ }
717
+ info.fileName = new String(nameBytes, 0, nameLen, StandardCharsets.UTF_8);
718
+ pos += LENGTH_FILE_NAME;
719
+
720
+ // Flags (big-endian)
721
+ info.flags = ((protocolData[pos] & 0xFF) << 8) | (protocolData[pos + 1] & 0xFF);
722
+ pos += LENGTH_FILE_FLAG;
723
+
724
+ // Verify packet has enough data
725
+ if (protocolData.length < pos + info.packSize + LENGTH_FILE_VERIFY + LENGTH_FILE_END) {
726
+ Log.e("K900ProtocolUtils", "File packet too short for data. Need: " +
727
+ (pos + info.packSize + LENGTH_FILE_VERIFY + LENGTH_FILE_END) +
728
+ ", Have: " + protocolData.length +
729
+ ", packSize=" + info.packSize + ", pos=" + pos);
730
+ return null;
731
+ }
732
+
733
+ // Data
734
+ info.data = new byte[info.packSize];
735
+ System.arraycopy(protocolData, pos, info.data, 0, info.packSize);
736
+ pos += info.packSize;
737
+
738
+ // Verify code
739
+ info.verifyCode = protocolData[pos];
740
+ pos += LENGTH_FILE_VERIFY;
741
+
742
+ // Check end code
743
+ if (protocolData[pos] != CMD_END_CODE[0] || protocolData[pos + 1] != CMD_END_CODE[1]) {
744
+ return null;
745
+ }
746
+
747
+ // Calculate and verify checksum
748
+ int checkSum = 0;
749
+ for (int i = 0; i < info.packSize; i++) {
750
+ checkSum += (info.data[i] & 0xFF);
751
+ }
752
+ byte calculatedVerify = (byte)(checkSum & 0xFF);
753
+
754
+ info.isValid = (calculatedVerify == info.verifyCode);
755
+
756
+ if (!info.isValid) {
757
+ Log.e("K900ProtocolUtils", "File packet checksum failed. Expected: " +
758
+ String.format("%02X", info.verifyCode) + ", Calculated: " +
759
+ String.format("%02X", calculatedVerify));
760
+ } else {
761
+ Log.d("K900ProtocolUtils", "File packet extracted successfully: index=" + info.packIndex +
762
+ ", size=" + info.packSize + ", fileName=" + info.fileName);
763
+ }
764
+
765
+ return info;
766
+ }
767
+
768
+ /**
769
+ * Create a file transfer acknowledgment message
770
+ *
771
+ * @param state 1 for success, 0 for failure
772
+ * @param index The packet index being acknowledged
773
+ * @return JSON string ready to be sent
774
+ */
775
+ public static String createFileTransferAck(int state, int index) {
776
+ try {
777
+ JSONObject body = new JSONObject();
778
+ body.put("state", state);
779
+ body.put("index", index);
780
+
781
+ JSONObject message = new JSONObject();
782
+ message.put("C", "cs_flts");
783
+ message.put("B", body); // Send as JSON object, not string
784
+
785
+ return message.toString();
786
+ } catch (JSONException e) {
787
+ Log.e("K900ProtocolUtils", "Error creating file transfer ack", e);
788
+ return null;
789
+ }
790
+ }
791
+ }