@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.
- package/README.md +278 -0
- package/android/build.gradle +167 -0
- package/android/lc3Lib/CMakeLists.txt +6 -0
- package/android/lc3Lib/build.gradle +109 -0
- package/android/lc3Lib/proguard-rules.pro +33 -0
- package/android/lc3Lib/src/main/AndroidManifest.xml +2 -0
- package/android/lc3Lib/src/main/cpp/CMakeLists.txt +8 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/CMakeLists.txt +30 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/CMakeLists.txt +7 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.cc +96 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.h +53 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/Makefile.am +6 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h +26 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h.in +26 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/ogg.h +209 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/os_types.h +158 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus.h +981 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_custom.h +342 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_defines.h +799 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_multistream.h +660 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_projection.h +568 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_types.h +166 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.cc +268 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.h +115 -0
- package/android/lc3Lib/src/main/cpp/google_opus_stuff/opus_tools/opus_header.h +59 -0
- package/android/lc3Lib/src/main/cpp/liblc3/CMakeLists.txt +38 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/lc3.h +309 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/lc3_private.h +162 -0
- package/android/lc3Lib/src/main/cpp/liblc3/include/rnnoise.h +114 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/CMakeLists.txt +19 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.c +92 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.h +44 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.c +375 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.h +315 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.c +129 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.h +69 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/common.h +148 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.c +70 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.h +43 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/fastmath.h +158 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/lc3.c +702 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.c +893 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.h +111 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_arm.h +506 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_neon.h +281 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/makefile.mk +35 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.c +452 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.h +57 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct_neon.h +296 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/meson.build +46 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.c +61 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.h +57 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.c +880 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.h +103 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.c +904 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.h +119 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.c +3457 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.h +94 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.c +457 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.h +99 -0
- package/android/lc3Lib/src/main/cpp/liblc3/liblc3.cpp +159 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/_kiss_fft_guts.h +182 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/arch.h +261 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.c +279 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.h +59 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/common.h +48 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/compile.sh +3 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/denoise.c +646 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.c +601 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.h +203 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/opus_types.h +159 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.c +526 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.h +149 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.c +178 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.h +69 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.c +11051 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.h +34 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_reader.c +168 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_train.py +66 -0
- package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/tansig_table.h +45 -0
- package/android/lc3Lib/src/main/java/com/mentra/lc3Lib/Lc3Cpp.java +38 -0
- package/android/lc3Lib/third_party/CMakeLists.txt +23 -0
- package/android/lc3Lib/third_party/CMakeLists_libogg.txt +18 -0
- package/android/lc3Lib/third_party/CMakeLists_libopus.txt +18 -0
- package/android/lc3Lib/third_party/CMakeLists_opus-tools.txt +23 -0
- package/android/lc3Lib/third_party/opus_tools/src/AUTHORS +5 -0
- package/android/lc3Lib/third_party/opus_tools/src/CMakeLists.txt +4 -0
- package/android/lc3Lib/third_party/opus_tools/src/COPYING +371 -0
- package/android/lc3Lib/third_party/opus_tools/src/ChangeLog +3 -0
- package/android/lc3Lib/third_party/opus_tools/src/Makefile.am +42 -0
- package/android/lc3Lib/third_party/opus_tools/src/Makefile.unix +23 -0
- package/android/lc3Lib/third_party/opus_tools/src/NEWS +0 -0
- package/android/lc3Lib/third_party/opus_tools/src/README +0 -0
- package/android/lc3Lib/third_party/opus_tools/src/autogen.sh +115 -0
- package/android/lc3Lib/third_party/opus_tools/src/configure.ac +293 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/arch.h +239 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/audio-in.c +1046 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.c +245 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.h +28 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.c +320 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.h +51 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/lpc.c +157 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/lpc.h +27 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.c +286 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.h +59 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusdec.c +884 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.c +1021 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.h +101 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.c +639 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.h +51 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/os_support.h +167 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/resample.c +1137 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/speex_resampler.h +344 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/stack_alloc.h +115 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.c +125 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.h +62 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.c +223 -0
- package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.h +60 -0
- package/android/settings.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +40 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +528 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +610 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +1616 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +314 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothModels.kt +1710 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +554 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/ObservableStore.kt +68 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +158 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +934 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/services/Foreground.kt +175 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/services/PhoneMic.kt +1109 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +3974 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +3551 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.java +1327 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.java +6959 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +1655 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraosBle.java +53675 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +202 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +224 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/STTTools.kt +340 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +465 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/VadGateSpeechPolicy.kt +221 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/AES.java +106 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/AudioSessionMonitor.kt +189 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BitmapJavaUtils.java +169 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BlePhotoUploadService.java +179 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/Constants.kt +44 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/G1Text.kt +436 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/IncidentLogBleRelayNaming.java +29 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/IncidentLogBleUploadService.java +76 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/K900ProtocolUtils.java +791 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunker.java +186 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/NexSGCUtils.kt +589 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/PhoneAudioMonitor.kt +303 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/SmartGlassesConnectionState.java +9 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/ByteUtilAudioPlayer.java +655 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/Lc3Player.java +441 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/PCMAudioPlayer.java +431 -0
- package/android/src/main/res/values/strings.xml +4 -0
- package/app.plugin.js +1 -0
- package/build/BluetoothSdk.types.d.ts +498 -0
- package/build/BluetoothSdk.types.d.ts.map +1 -0
- package/build/BluetoothSdk.types.js +23 -0
- package/build/BluetoothSdk.types.js.map +1 -0
- package/build/BluetoothSdkModule.d.ts +71 -0
- package/build/BluetoothSdkModule.d.ts.map +1 -0
- package/build/BluetoothSdkModule.js +106 -0
- package/build/BluetoothSdkModule.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +5 -0
- package/build/index.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/ios/BluetoothSdkModule.swift +665 -0
- package/ios/MentraBluetoothSDK.podspec +77 -0
- package/ios/Packages/CoreObjC/CoreObjC.xcodeproj/project.pbxproj +213 -0
- package/ios/Packages/CoreObjC/PcmConverter.h +22 -0
- package/ios/Packages/CoreObjC/PcmConverter.m +266 -0
- package/ios/Packages/CoreObjC/attdet.c +92 -0
- package/ios/Packages/CoreObjC/attdet.h +44 -0
- package/ios/Packages/CoreObjC/bits.c +375 -0
- package/ios/Packages/CoreObjC/bits.h +315 -0
- package/ios/Packages/CoreObjC/bwdet.c +129 -0
- package/ios/Packages/CoreObjC/bwdet.h +69 -0
- package/ios/Packages/CoreObjC/common.h +151 -0
- package/ios/Packages/CoreObjC/energy.c +70 -0
- package/ios/Packages/CoreObjC/energy.h +43 -0
- package/ios/Packages/CoreObjC/fastmath.h +158 -0
- package/ios/Packages/CoreObjC/lc3.c +704 -0
- package/ios/Packages/CoreObjC/lc3.h +313 -0
- package/ios/Packages/CoreObjC/lc3_cpp.h +283 -0
- package/ios/Packages/CoreObjC/lc3_private.h +163 -0
- package/ios/Packages/CoreObjC/ltpf.c +905 -0
- package/ios/Packages/CoreObjC/ltpf.h +111 -0
- package/ios/Packages/CoreObjC/ltpf_arm.h +506 -0
- package/ios/Packages/CoreObjC/ltpf_neon.h +281 -0
- package/ios/Packages/CoreObjC/makefile.mk +35 -0
- package/ios/Packages/CoreObjC/mdct.c +469 -0
- package/ios/Packages/CoreObjC/mdct.h +57 -0
- package/ios/Packages/CoreObjC/mdct_neon.h +296 -0
- package/ios/Packages/CoreObjC/meson.build +61 -0
- package/ios/Packages/CoreObjC/plc.c +61 -0
- package/ios/Packages/CoreObjC/plc.h +57 -0
- package/ios/Packages/CoreObjC/rnnoise.h +114 -0
- package/ios/Packages/CoreObjC/sns.c +880 -0
- package/ios/Packages/CoreObjC/sns.h +103 -0
- package/ios/Packages/CoreObjC/spec.c +907 -0
- package/ios/Packages/CoreObjC/spec.h +119 -0
- package/ios/Packages/CoreObjC/tables.c +3457 -0
- package/ios/Packages/CoreObjC/tables.h +94 -0
- package/ios/Packages/CoreObjC/tns.c +457 -0
- package/ios/Packages/CoreObjC/tns.h +99 -0
- package/ios/Packages/SherpaOnnx/Model/joiner.onnx +0 -0
- package/ios/Packages/SherpaOnnx/Model/tokens.txt +502 -0
- package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +1659 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/cargs.h +162 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/sherpa-onnx/c-api/c-api.h +1852 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/sherpa-onnx/c-api/cxx-api.h +674 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +44 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/sherpa-onnx.a +0 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/sherpa-onnx.a +0 -0
- package/ios/Packages/VAD/Common/VAD/VADQuality.swift +41 -0
- package/ios/Packages/VAD/Common/VAD/VADState.swift +26 -0
- package/ios/Packages/VAD/Common/VAD/VADStrategy.swift +29 -0
- package/ios/Packages/VAD/Common/VAD/VADType.swift +14 -0
- package/ios/Packages/VAD/Data/Configuration.swift +68 -0
- package/ios/Packages/VAD/Data/FrameSize.swift +39 -0
- package/ios/Packages/VAD/Data/Record.swift +13 -0
- package/ios/Packages/VAD/Data/Result.swift +22 -0
- package/ios/Packages/VAD/Data/SampleRate.swift +48 -0
- package/ios/Packages/VAD/Silero/Model/silero_vad.onnx +0 -0
- package/ios/Packages/VAD/Silero/SileroVAD.swift +284 -0
- package/ios/Packages/VAD/Silero/SileroVADStrategy.swift +64 -0
- package/ios/Packages/libbz2/module.modulemap +5 -0
- package/ios/Packages/libbz2/shim.h +1 -0
- package/ios/Source/Bridge.swift +353 -0
- package/ios/Source/Bridging-Header.h +16 -0
- package/ios/Source/DeviceManager.swift +1478 -0
- package/ios/Source/DeviceStore.swift +295 -0
- package/ios/Source/MentraBluetoothSDK.swift +2439 -0
- package/ios/Source/ObservableStore.swift +88 -0
- package/ios/Source/PrivacyInfo.xcprivacy +23 -0
- package/ios/Source/controllers/ControllerManager.swift +187 -0
- package/ios/Source/controllers/R1.swift +827 -0
- package/ios/Source/services/PhoneMic.swift +662 -0
- package/ios/Source/sgcs/Frame.swift +651 -0
- package/ios/Source/sgcs/G1.swift +2505 -0
- package/ios/Source/sgcs/G2.swift +3730 -0
- package/ios/Source/sgcs/Mach1.swift +543 -0
- package/ios/Source/sgcs/MentraLive.swift +4708 -0
- package/ios/Source/sgcs/MentraNex.swift +2479 -0
- package/ios/Source/sgcs/SGCManager.swift +243 -0
- package/ios/Source/sgcs/Simulated.swift +270 -0
- package/ios/Source/sgcs/mentraos_ble.pb.swift +3811 -0
- package/ios/Source/stt/STTTools.swift +154 -0
- package/ios/Source/stt/SherpaOnnxTranscriber.swift +401 -0
- package/ios/Source/utils/AudioSessionMonitor.swift +283 -0
- package/ios/Source/utils/Constants.swift +74 -0
- package/ios/Source/utils/Enums.swift +95 -0
- package/ios/Source/utils/G1Text.swift +2067 -0
- package/ios/Source/utils/JSCExperiment.swift +241 -0
- package/ios/Source/utils/MemoryMonitor.swift +44 -0
- package/ios/Source/utils/MessageChunker.swift +164 -0
- package/ios/Source/utils/Models.swift +135 -0
- package/ios/Source/utils/PhoneAudioMonitor.swift +226 -0
- package/ios/Source/utils/TarBz2Extractor.swift +206 -0
- package/package.json +78 -0
- package/plugin/build/index.d.ts +6 -0
- package/plugin/build/index.js +12 -0
- package/plugin/build/withAndroid.d.ts +4 -0
- package/plugin/build/withAndroid.js +80 -0
- package/plugin/build/withIos.d.ts +4 -0
- package/plugin/build/withIos.js +64 -0
- package/src/BluetoothSdk.types.ts +581 -0
- package/src/BluetoothSdkModule.ts +259 -0
- package/src/index.ts +4 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk.utils
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.media.AudioManager
|
|
5
|
+
import android.media.AudioPlaybackConfiguration
|
|
6
|
+
import android.os.Build
|
|
7
|
+
import android.os.Handler
|
|
8
|
+
import android.os.Looper
|
|
9
|
+
import com.mentra.bluetoothsdk.Bridge
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* PhoneAudioMonitor - Monitors system audio playback state
|
|
13
|
+
*
|
|
14
|
+
* Used to detect when the phone is playing audio (music, podcasts, etc.)
|
|
15
|
+
* so we can temporarily suspend the LC3 microphone on MentraLive glasses
|
|
16
|
+
* to avoid overloading the MCU when both A2DP output and LC3 mic input
|
|
17
|
+
* are active simultaneously.
|
|
18
|
+
*
|
|
19
|
+
* This class mirrors the iOS PhoneAudioMonitor.swift implementation.
|
|
20
|
+
*/
|
|
21
|
+
class PhoneAudioMonitor private constructor(private val context: Context) {
|
|
22
|
+
|
|
23
|
+
companion object {
|
|
24
|
+
private const val TAG = "PhoneAudioMonitor"
|
|
25
|
+
|
|
26
|
+
@Volatile
|
|
27
|
+
private var instance: PhoneAudioMonitor? = null
|
|
28
|
+
|
|
29
|
+
@JvmStatic
|
|
30
|
+
fun getInstance(context: Context): PhoneAudioMonitor {
|
|
31
|
+
return instance ?: synchronized(this) {
|
|
32
|
+
instance ?: PhoneAudioMonitor(context.applicationContext).also {
|
|
33
|
+
instance = it
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Listener callback for audio state changes
|
|
40
|
+
interface Listener {
|
|
41
|
+
fun onPhoneAudioStateChanged(isPlaying: Boolean)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private val audioManager: AudioManager =
|
|
45
|
+
context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
|
46
|
+
private val mainHandler = Handler(Looper.getMainLooper())
|
|
47
|
+
|
|
48
|
+
private var listener: Listener? = null
|
|
49
|
+
private var isMonitoring = false
|
|
50
|
+
private var lastKnownState = false
|
|
51
|
+
|
|
52
|
+
// Rate limiting: max 1 state change notification per 500ms
|
|
53
|
+
// If state changes rapidly (true/false/true), we wait and send the final state
|
|
54
|
+
private var lastNotificationTime = 0L
|
|
55
|
+
private var pendingStateRunnable: Runnable? = null
|
|
56
|
+
private var pendingState: Boolean? = null
|
|
57
|
+
private val STATE_CHANGE_MIN_INTERVAL_MS = 500L
|
|
58
|
+
|
|
59
|
+
// Hold-off period: When our app signals it's about to play audio, ignore STOPPED
|
|
60
|
+
// reports for this duration. This handles the brief gap during codec transitions
|
|
61
|
+
// when one audio interrupts another (system reports 0 configs briefly).
|
|
62
|
+
private var audioStartHoldoffUntil = 0L
|
|
63
|
+
private val AUDIO_START_HOLDOFF_MS = 1000L // 1 second hold-off when starting audio
|
|
64
|
+
|
|
65
|
+
// AudioPlaybackCallback for API 26+ (real-time detection)
|
|
66
|
+
private var playbackCallback: AudioManager.AudioPlaybackCallback? = null
|
|
67
|
+
|
|
68
|
+
// Fallback polling for older devices or edge cases
|
|
69
|
+
private var pollingRunnable: Runnable? = null
|
|
70
|
+
private val POLLING_INTERVAL_MS = 1000L // 1 second polling fallback
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Check if any audio is currently playing on the device (including our own app)
|
|
74
|
+
* On Android, isMusicActive and AudioPlaybackCallback detect ALL apps including ours,
|
|
75
|
+
* so we don't need to manually track our own app's audio like on iOS.
|
|
76
|
+
*/
|
|
77
|
+
fun isPlaying(): Boolean {
|
|
78
|
+
return audioManager.isMusicActive
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Notify the monitor that our own app started/stopped playing audio
|
|
83
|
+
* Called from RN AudioPlaybackService via Bridge
|
|
84
|
+
*
|
|
85
|
+
* On Android, isMusicActive already detects our app's audio, but we use this signal
|
|
86
|
+
* to set a hold-off period during audio transitions. When one audio interrupts another,
|
|
87
|
+
* there's a brief gap where the system reports 0 active configs (codec is switching).
|
|
88
|
+
* The hold-off prevents us from reporting STOPPED during this transition.
|
|
89
|
+
*/
|
|
90
|
+
fun setOwnAppAudioPlaying(playing: Boolean) {
|
|
91
|
+
Bridge.log("$TAG: Own app audio -> ${if (playing) "PLAYING" else "STOPPED"}")
|
|
92
|
+
|
|
93
|
+
if (playing) {
|
|
94
|
+
// Starting audio: set hold-off to ignore STOPPED during codec transition
|
|
95
|
+
audioStartHoldoffUntil = System.currentTimeMillis() + AUDIO_START_HOLDOFF_MS
|
|
96
|
+
Bridge.log("$TAG: Set audio start hold-off for ${AUDIO_START_HOLDOFF_MS}ms")
|
|
97
|
+
|
|
98
|
+
// Cancel any pending STOPPED notification since we're about to play
|
|
99
|
+
if (pendingState == false) {
|
|
100
|
+
pendingStateRunnable?.let { mainHandler.removeCallbacks(it) }
|
|
101
|
+
pendingStateRunnable = null
|
|
102
|
+
pendingState = null
|
|
103
|
+
Bridge.log("$TAG: Cancelled pending STOPPED notification")
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// If we were in STOPPED state, notify PLAYING immediately
|
|
107
|
+
if (!lastKnownState) {
|
|
108
|
+
doNotify(true)
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
// Stopping audio: clear hold-off and check actual state
|
|
112
|
+
audioStartHoldoffUntil = 0L
|
|
113
|
+
notifyIfStateChanged(isPlaying())
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Start monitoring for phone audio playback changes
|
|
119
|
+
*
|
|
120
|
+
* @param listener Callback to receive audio state change notifications
|
|
121
|
+
*/
|
|
122
|
+
fun startMonitoring(listener: Listener) {
|
|
123
|
+
if (isMonitoring) {
|
|
124
|
+
Bridge.log("$TAG: Already monitoring")
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
this.listener = listener
|
|
129
|
+
this.lastKnownState = isPlaying()
|
|
130
|
+
this.isMonitoring = true
|
|
131
|
+
|
|
132
|
+
Bridge.log("$TAG: Starting audio playback monitoring (initial state: ${if (lastKnownState) "playing" else "not playing"})")
|
|
133
|
+
|
|
134
|
+
// Use AudioPlaybackCallback for API 26+ (real-time detection)
|
|
135
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
136
|
+
playbackCallback = object : AudioManager.AudioPlaybackCallback() {
|
|
137
|
+
override fun onPlaybackConfigChanged(configs: MutableList<AudioPlaybackConfiguration>?) {
|
|
138
|
+
super.onPlaybackConfigChanged(configs)
|
|
139
|
+
handlePlaybackConfigChanged(configs)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
audioManager.registerAudioPlaybackCallback(playbackCallback!!, mainHandler)
|
|
143
|
+
Bridge.log("$TAG: Registered AudioPlaybackCallback (API 26+)")
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Also start polling as a fallback/supplement
|
|
147
|
+
// Some audio sources might not trigger the callback reliably
|
|
148
|
+
startPolling()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Stop monitoring for phone audio playback changes
|
|
153
|
+
*/
|
|
154
|
+
fun stopMonitoring() {
|
|
155
|
+
if (!isMonitoring) {
|
|
156
|
+
Bridge.log("$TAG: Not currently monitoring")
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
Bridge.log("$TAG: Stopping audio playback monitoring")
|
|
161
|
+
|
|
162
|
+
// Unregister callback
|
|
163
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && playbackCallback != null) {
|
|
164
|
+
audioManager.unregisterAudioPlaybackCallback(playbackCallback!!)
|
|
165
|
+
playbackCallback = null
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Stop polling
|
|
169
|
+
stopPolling()
|
|
170
|
+
|
|
171
|
+
// Cancel any pending state notification
|
|
172
|
+
pendingStateRunnable?.let { mainHandler.removeCallbacks(it) }
|
|
173
|
+
pendingStateRunnable = null
|
|
174
|
+
pendingState = null
|
|
175
|
+
|
|
176
|
+
listener = null
|
|
177
|
+
isMonitoring = false
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Handle playback configuration changes from AudioPlaybackCallback
|
|
182
|
+
* Note: This callback fires when audio players are added/removed, but may not
|
|
183
|
+
* fire reliably when other apps pause (they keep the player, just paused).
|
|
184
|
+
* We rely on polling for pause detection.
|
|
185
|
+
*/
|
|
186
|
+
private fun handlePlaybackConfigChanged(configs: MutableList<AudioPlaybackConfiguration>?) {
|
|
187
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
188
|
+
// Log active configs for debugging
|
|
189
|
+
val activeCount = configs?.size ?: 0
|
|
190
|
+
Bridge.log("$TAG: Playback config changed, ${activeCount} active configs")
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Use the combined isPlaying() which includes ownAppAudioPlaying
|
|
194
|
+
// This prevents the system callback from triggering STOPPED when our app is still playing
|
|
195
|
+
notifyIfStateChanged(isPlaying())
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Start polling isMusicActive as a fallback mechanism
|
|
200
|
+
*/
|
|
201
|
+
private fun startPolling() {
|
|
202
|
+
pollingRunnable = object : Runnable {
|
|
203
|
+
override fun run() {
|
|
204
|
+
if (!isMonitoring) return
|
|
205
|
+
|
|
206
|
+
notifyIfStateChanged(isPlaying())
|
|
207
|
+
|
|
208
|
+
mainHandler.postDelayed(this, POLLING_INTERVAL_MS)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
mainHandler.postDelayed(pollingRunnable!!, POLLING_INTERVAL_MS)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Stop the polling mechanism
|
|
216
|
+
*/
|
|
217
|
+
private fun stopPolling() {
|
|
218
|
+
pollingRunnable?.let { mainHandler.removeCallbacks(it) }
|
|
219
|
+
pollingRunnable = null
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Notify listener if state has changed, with rate limiting and hold-off protection.
|
|
224
|
+
*
|
|
225
|
+
* Hold-off: When our app signals it's about to play audio, we ignore STOPPED reports
|
|
226
|
+
* for a short period to handle codec transition gaps.
|
|
227
|
+
*
|
|
228
|
+
* Rate limiting: Max 1 notification per 500ms. If state changes rapidly, we send the final state.
|
|
229
|
+
*/
|
|
230
|
+
private fun notifyIfStateChanged(isPlaying: Boolean) {
|
|
231
|
+
if (isPlaying == lastKnownState) return
|
|
232
|
+
|
|
233
|
+
val now = System.currentTimeMillis()
|
|
234
|
+
|
|
235
|
+
// Hold-off protection: Don't report STOPPED during audio start hold-off period
|
|
236
|
+
// This handles the brief gap when one audio interrupts another (codec switching)
|
|
237
|
+
if (!isPlaying && audioStartHoldoffUntil > now) {
|
|
238
|
+
Bridge.log("$TAG: Ignoring STOPPED during audio start hold-off (${audioStartHoldoffUntil - now}ms remaining)")
|
|
239
|
+
return
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
val timeSinceLastNotification = now - lastNotificationTime
|
|
243
|
+
|
|
244
|
+
// Cancel any pending notification - we'll either send immediately or schedule new one
|
|
245
|
+
pendingStateRunnable?.let { mainHandler.removeCallbacks(it) }
|
|
246
|
+
pendingStateRunnable = null
|
|
247
|
+
pendingState = null
|
|
248
|
+
|
|
249
|
+
if (timeSinceLastNotification >= STATE_CHANGE_MIN_INTERVAL_MS) {
|
|
250
|
+
// It's been long enough, notify immediately
|
|
251
|
+
doNotify(isPlaying)
|
|
252
|
+
} else {
|
|
253
|
+
// Too soon, schedule for later
|
|
254
|
+
val delay = STATE_CHANGE_MIN_INTERVAL_MS - timeSinceLastNotification
|
|
255
|
+
pendingState = isPlaying
|
|
256
|
+
pendingStateRunnable = Runnable {
|
|
257
|
+
pendingState?.let { state ->
|
|
258
|
+
// Re-check hold-off at execution time
|
|
259
|
+
if (!state && audioStartHoldoffUntil > System.currentTimeMillis()) {
|
|
260
|
+
Bridge.log("$TAG: Ignoring scheduled STOPPED during audio start hold-off")
|
|
261
|
+
pendingStateRunnable = null
|
|
262
|
+
pendingState = null
|
|
263
|
+
return@Runnable
|
|
264
|
+
}
|
|
265
|
+
doNotify(state)
|
|
266
|
+
}
|
|
267
|
+
pendingStateRunnable = null
|
|
268
|
+
pendingState = null
|
|
269
|
+
}
|
|
270
|
+
mainHandler.postDelayed(pendingStateRunnable!!, delay)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Actually send the notification to listener
|
|
276
|
+
*/
|
|
277
|
+
private fun doNotify(isPlaying: Boolean) {
|
|
278
|
+
lastKnownState = isPlaying
|
|
279
|
+
lastNotificationTime = System.currentTimeMillis()
|
|
280
|
+
Bridge.log("$TAG: Audio state changed -> ${if (isPlaying) "PLAYING" else "STOPPED"}")
|
|
281
|
+
|
|
282
|
+
listener?.onPhoneAudioStateChanged(isPlaying)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Force a state check and notify if changed.
|
|
287
|
+
* Call this when the app returns to foreground to catch any changes
|
|
288
|
+
* that may have been missed while backgrounded.
|
|
289
|
+
*/
|
|
290
|
+
fun checkStateNow() {
|
|
291
|
+
if (!isMonitoring) return
|
|
292
|
+
Bridge.log("$TAG: Forcing state check")
|
|
293
|
+
notifyIfStateChanged(isPlaying())
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Clean up resources
|
|
298
|
+
*/
|
|
299
|
+
fun destroy() {
|
|
300
|
+
stopMonitoring()
|
|
301
|
+
instance = null
|
|
302
|
+
}
|
|
303
|
+
}
|