@mentra/bluetooth-sdk 3.2.0-dev.191 → 3.2.0-dev.195
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 +29 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +1 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/GeneratedReleaseMetadata.kt +5 -5
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraLocalNetworkModule.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/debug/BleTraceLogger.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/otaserver/MentraOtaServerModule.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/MentraPhotoReceiverModule.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/services/PhoneMic.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Ar99.java +8 -8
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.kt +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLiveL2capChannel.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/ar99/ota/Ar99OtaManager.java +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/STTTools.kt +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/VadGateSpeechPolicy.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/tts/TTSTools.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/AES.java +7 -8
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BitmapJavaUtils.java +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BlePhotoUploadService.java +34 -34
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/G1Text.kt +1 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/IncidentLogBleUploadService.java +4 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/K900ProtocolUtils.java +34 -34
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunkReassembler.java +10 -10
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunker.java +6 -6
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/NativeLog.java +89 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/NexSGCUtils.kt +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/Ar99OpusPcmDecoder.java +10 -10
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/ByteUtilAudioPlayer.java +7 -7
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/Lc3Player.java +16 -16
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/PCMAudioPlayer.java +26 -26
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/PcmStreamPlayer.kt +1 -1
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/NativeLogTest.kt +61 -0
- package/build/BluetoothSdk.types.d.ts +7 -0
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js +4 -0
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/_private/nativeLogConsole.d.ts +17 -0
- package/build/_private/nativeLogConsole.d.ts.map +1 -0
- package/build/_private/nativeLogConsole.js +16 -0
- package/build/_private/nativeLogConsole.js.map +1 -0
- package/build/generated/releaseMetadata.js +5 -5
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/react/useGlassesConnection.d.ts +5 -0
- package/build/react/useGlassesConnection.d.ts.map +1 -1
- package/build/react/useGlassesConnection.js +2 -2
- package/build/react/useGlassesConnection.js.map +1 -1
- package/build/react/useMentraBluetooth.d.ts +5 -0
- package/build/react/useMentraBluetooth.d.ts.map +1 -1
- package/build/react/useMentraBluetooth.js +1 -0
- package/build/react/useMentraBluetooth.js.map +1 -1
- package/ios/BluetoothSdkModule.swift +2 -2
- package/ios/Source/BluetoothSdkDefaults.swift +1 -1
- package/ios/Source/Bridge.swift +3 -2
- package/ios/Source/DeviceManager.swift +4 -2
- package/ios/Source/GeneratedReleaseMetadata.swift +5 -5
- package/ios/Source/MentraBluetoothSDK.swift +10 -3
- package/ios/Source/internal/BleTraceLogger.swift +3 -0
- package/ios/Source/sgcs/G1.swift +1 -1
- package/ios/Source/sgcs/MentraLive.swift +28 -11
- package/ios/Source/stt/STTTools.swift +1 -1
- package/ios/Source/types/DeviceModels.swift +9 -1
- package/ios/Source/utils/G1Text.swift +1 -1
- package/ios/Source/utils/JSCExperiment.swift +1 -2
- package/ios/Source/utils/MessageChunkReassembler.swift +6 -6
- package/ios/Source/utils/MessageChunker.swift +8 -8
- package/ios/Source/utils/Models.swift +1 -1
- package/ios/Tests/MentraLiveConnectionOptionsTests.swift +30 -0
- package/ios/Tests/NativeLogTests.swift +34 -0
- package/package.json +1 -1
- package/src/BluetoothSdk.types.ts +7 -0
- package/src/_private/BluetoothSdkModule.ts +5 -0
- package/src/_private/nativeLogConsole.ts +24 -0
- package/src/generated/releaseMetadata.ts +5 -5
- package/src/react/useGlassesConnection.ts +7 -2
- package/src/react/useMentraBluetooth.ts +6 -0
package/android/src/main/java/com/mentra/bluetoothsdk/utils/IncidentLogBleUploadService.java
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
package com.mentra.bluetoothsdk.utils;
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import com.mentra.bluetoothsdk.utils.NativeLog;
|
|
4
4
|
|
|
5
5
|
import java.io.IOException;
|
|
6
6
|
import java.util.concurrent.TimeUnit;
|
|
@@ -60,16 +60,16 @@ public final class IncidentLogBleUploadService {
|
|
|
60
60
|
.build();
|
|
61
61
|
try (Response response = client.newCall(request).execute()) {
|
|
62
62
|
if (response.isSuccessful()) {
|
|
63
|
-
|
|
63
|
+
NativeLog.i(TAG, "Incident BLE relay upload OK: " + url);
|
|
64
64
|
callback.onDone(true, null);
|
|
65
65
|
} else {
|
|
66
66
|
String msg = "HTTP " + response.code();
|
|
67
|
-
|
|
67
|
+
NativeLog.e(TAG, "Incident BLE relay upload failed: " + msg + " " + url);
|
|
68
68
|
callback.onDone(false, msg);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
} catch (IOException e) {
|
|
72
|
-
|
|
72
|
+
NativeLog.e(TAG, "Incident BLE relay upload IO error", e);
|
|
73
73
|
callback.onDone(false, e.getMessage());
|
|
74
74
|
}
|
|
75
75
|
}).start();
|
|
@@ -5,7 +5,7 @@ import android.content.Context;
|
|
|
5
5
|
import android.content.Intent;
|
|
6
6
|
import android.content.IntentFilter;
|
|
7
7
|
import android.content.pm.PackageManager;
|
|
8
|
-
import
|
|
8
|
+
import com.mentra.bluetoothsdk.utils.NativeLog;
|
|
9
9
|
import android.os.Build;
|
|
10
10
|
|
|
11
11
|
import org.json.JSONException;
|
|
@@ -78,7 +78,7 @@ public class K900ProtocolUtils {
|
|
|
78
78
|
return packDataCommand(jsonBytes, CMD_TYPE_STRING, endian);
|
|
79
79
|
|
|
80
80
|
} catch (JSONException e) {
|
|
81
|
-
|
|
81
|
+
com.mentra.bluetoothsdk.utils.NativeLog.e("K900ProtocolUtils", "Error creating JSON wrapper", e);
|
|
82
82
|
return null;
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -190,7 +190,7 @@ public class K900ProtocolUtils {
|
|
|
190
190
|
return packDataCommand(jsonBytes, CMD_TYPE_STRING, endian);
|
|
191
191
|
|
|
192
192
|
} catch (JSONException e) {
|
|
193
|
-
|
|
193
|
+
com.mentra.bluetoothsdk.utils.NativeLog.e("K900ProtocolUtils", "Error creating JSON wrapper for K900", e);
|
|
194
194
|
return null;
|
|
195
195
|
}
|
|
196
196
|
}
|
|
@@ -214,7 +214,7 @@ public class K900ProtocolUtils {
|
|
|
214
214
|
*/
|
|
215
215
|
public static byte[] formatMessageForTransmission(String jsonData, K900LengthCodec.Endian endian) {
|
|
216
216
|
try {
|
|
217
|
-
|
|
217
|
+
com.mentra.bluetoothsdk.utils.NativeLog.e("K900ProtocolUtils", "🔄 Formatting message: " + jsonData);
|
|
218
218
|
|
|
219
219
|
// Validate that input is proper JSON
|
|
220
220
|
new JSONObject(jsonData);
|
|
@@ -225,7 +225,7 @@ public class K900ProtocolUtils {
|
|
|
225
225
|
wrapper.put(FIELD_V, 1); // Optional version field
|
|
226
226
|
wrapper.put(FIELD_B, new JSONObject()); // Optional body field
|
|
227
227
|
String wrappedJson = wrapper.toString();
|
|
228
|
-
|
|
228
|
+
com.mentra.bluetoothsdk.utils.NativeLog.e("K900ProtocolUtils", "🔄 After C-wrapping: " + wrappedJson);
|
|
229
229
|
|
|
230
230
|
// Now format with BES2700 protocol
|
|
231
231
|
byte[] result =
|
|
@@ -243,7 +243,7 @@ public class K900ProtocolUtils {
|
|
|
243
243
|
return result;
|
|
244
244
|
|
|
245
245
|
} catch (JSONException e) {
|
|
246
|
-
|
|
246
|
+
com.mentra.bluetoothsdk.utils.NativeLog.e("K900ProtocolUtils", "❌ Error in formatMessageForTransmission", e);
|
|
247
247
|
// Fallback: if json is invalid, still try to pack it without validation
|
|
248
248
|
return packJsonCommand(jsonData, endian);
|
|
249
249
|
}
|
|
@@ -262,7 +262,7 @@ public class K900ProtocolUtils {
|
|
|
262
262
|
wrapper.put(FIELD_C, content);
|
|
263
263
|
return wrapper.toString();
|
|
264
264
|
} catch (JSONException e) {
|
|
265
|
-
|
|
265
|
+
com.mentra.bluetoothsdk.utils.NativeLog.e("K900ProtocolUtils", "Error creating C-wrapped JSON", e);
|
|
266
266
|
return null;
|
|
267
267
|
}
|
|
268
268
|
}
|
|
@@ -374,17 +374,17 @@ public class K900ProtocolUtils {
|
|
|
374
374
|
* @return Parsed JSON object or null if not valid protocol data or valid JSON
|
|
375
375
|
*/
|
|
376
376
|
public static JSONObject processReceivedBytesToJson(byte[] data) {
|
|
377
|
-
|
|
377
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Processing received bytes for JSON extraction");
|
|
378
378
|
|
|
379
379
|
// Check for null or too small data
|
|
380
380
|
if (data == null || data.length < 7) {
|
|
381
|
-
|
|
381
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Received data is null or too short to be valid protocol data");
|
|
382
382
|
return null;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
385
|
// Verify if this is K900 protocol format (starts with ##)
|
|
386
386
|
if (!isK900ProtocolFormat(data)) {
|
|
387
|
-
|
|
387
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Not in K900 protocol format (missing ## markers)");
|
|
388
388
|
return null;
|
|
389
389
|
}
|
|
390
390
|
|
|
@@ -399,25 +399,25 @@ public class K900ProtocolUtils {
|
|
|
399
399
|
? detected.length
|
|
400
400
|
: ((data[3] & 0xFF) | ((data[4] & 0xFF) << 8));
|
|
401
401
|
|
|
402
|
-
|
|
402
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Command type: 0x" + String.format("%02X", commandType) +
|
|
403
403
|
", Payload length: " + payloadLength);
|
|
404
404
|
|
|
405
405
|
// Verify we have enough data and the right command type
|
|
406
406
|
if (commandType != CMD_TYPE_STRING) {
|
|
407
|
-
|
|
407
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Not a JSON/string command type (0x30), got: 0x" +
|
|
408
408
|
String.format("%02X", commandType));
|
|
409
409
|
return null;
|
|
410
410
|
}
|
|
411
411
|
|
|
412
412
|
if (data.length < payloadLength + 7) {
|
|
413
|
-
|
|
413
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Received data size (" + data.length +
|
|
414
414
|
") is less than expected size (" + (payloadLength + 7) + ")");
|
|
415
415
|
return null;
|
|
416
416
|
}
|
|
417
417
|
|
|
418
418
|
// Check for end markers ($$)
|
|
419
419
|
if (data[5 + payloadLength] != CMD_END_CODE[0] || data[6 + payloadLength] != CMD_END_CODE[1]) {
|
|
420
|
-
|
|
420
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "End markers ($$) not found where expected");
|
|
421
421
|
return null;
|
|
422
422
|
}
|
|
423
423
|
|
|
@@ -429,15 +429,15 @@ public class K900ProtocolUtils {
|
|
|
429
429
|
String payloadStr;
|
|
430
430
|
try {
|
|
431
431
|
payloadStr = new String(payload, StandardCharsets.UTF_8);
|
|
432
|
-
|
|
432
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Extracted JSON payload bytes: " + payloadLength);
|
|
433
433
|
} catch (Exception e) {
|
|
434
|
-
|
|
434
|
+
com.mentra.bluetoothsdk.utils.NativeLog.e("K900ProtocolUtils", "Error converting payload to string", e);
|
|
435
435
|
return null;
|
|
436
436
|
}
|
|
437
437
|
|
|
438
438
|
// Check if it's valid JSON
|
|
439
439
|
if (!payloadStr.startsWith("{") || !payloadStr.endsWith("}")) {
|
|
440
|
-
|
|
440
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Payload is not valid JSON");
|
|
441
441
|
return null;
|
|
442
442
|
}
|
|
443
443
|
|
|
@@ -448,14 +448,14 @@ public class K900ProtocolUtils {
|
|
|
448
448
|
// Check if this is C-wrapped format {"C": "..."}
|
|
449
449
|
if (json.has(FIELD_C)) {
|
|
450
450
|
String innerContent = json.optString(FIELD_C, "");
|
|
451
|
-
|
|
451
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Detected C-wrapped format");
|
|
452
452
|
|
|
453
453
|
// Try to parse the inner content as JSON
|
|
454
454
|
try {
|
|
455
455
|
JSONObject innerJson = new JSONObject(innerContent);
|
|
456
456
|
return innerJson;
|
|
457
457
|
} catch (JSONException e) {
|
|
458
|
-
|
|
458
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Inner content is not JSON, returning outer JSON object");
|
|
459
459
|
// If inner content is not JSON, return the outer JSON
|
|
460
460
|
return json;
|
|
461
461
|
}
|
|
@@ -464,7 +464,7 @@ public class K900ProtocolUtils {
|
|
|
464
464
|
return json;
|
|
465
465
|
}
|
|
466
466
|
} catch (JSONException e) {
|
|
467
|
-
|
|
467
|
+
com.mentra.bluetoothsdk.utils.NativeLog.e("K900ProtocolUtils", "Error parsing JSON payload: " + e.getMessage(), e);
|
|
468
468
|
return null;
|
|
469
469
|
}
|
|
470
470
|
}
|
|
@@ -496,29 +496,29 @@ public class K900ProtocolUtils {
|
|
|
496
496
|
|
|
497
497
|
// If looks like JSON but not C-wrapped, use the full formatting function
|
|
498
498
|
if (originalData.startsWith("{") && !isCWrappedJson(originalData)) {
|
|
499
|
-
|
|
499
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "📦 JSON DATA BEFORE C-WRAPPING: " + originalData);
|
|
500
500
|
byte[] formattedData = formatMessageForTransmission(originalData);
|
|
501
501
|
|
|
502
502
|
// Debug log the formatting results if needed
|
|
503
|
-
if (
|
|
503
|
+
if (com.mentra.bluetoothsdk.utils.NativeLog.isLoggable("K900ProtocolUtils", com.mentra.bluetoothsdk.utils.NativeLog.DEBUG)) {
|
|
504
504
|
StringBuilder hexDump = new StringBuilder();
|
|
505
505
|
for (int i = 0; i < Math.min(formattedData.length, 50); i++) {
|
|
506
506
|
hexDump.append(String.format("%02X ", formattedData[i]));
|
|
507
507
|
}
|
|
508
|
-
|
|
509
|
-
|
|
508
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "📦 AFTER C-WRAPPING & PROTOCOL FORMATTING (first 50 bytes): " + hexDump.toString());
|
|
509
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "📦 Total formatted length: " + formattedData.length + " bytes");
|
|
510
510
|
}
|
|
511
511
|
|
|
512
512
|
return formattedData;
|
|
513
513
|
} else {
|
|
514
514
|
// Otherwise just apply protocol formatting
|
|
515
|
-
|
|
516
|
-
|
|
515
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "📦 Data already C-wrapped or not JSON: " + originalData);
|
|
516
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Formatting data with K900 protocol (adding ##...)");
|
|
517
517
|
return packDataCommand(data, CMD_TYPE_STRING);
|
|
518
518
|
}
|
|
519
519
|
} catch (Exception e) {
|
|
520
520
|
// If we can't interpret as string, just apply protocol formatting to raw bytes
|
|
521
|
-
|
|
521
|
+
com.mentra.bluetoothsdk.utils.NativeLog.d("K900ProtocolUtils", "Applying protocol format to raw bytes");
|
|
522
522
|
return packDataCommand(data, CMD_TYPE_STRING);
|
|
523
523
|
}
|
|
524
524
|
}
|
|
@@ -573,10 +573,10 @@ public class K900ProtocolUtils {
|
|
|
573
573
|
String model = android.os.Build.MODEL.toLowerCase();
|
|
574
574
|
return model.contains("k900") || model.contains("xyglasses");
|
|
575
575
|
} catch (Exception e) {
|
|
576
|
-
|
|
576
|
+
NativeLog.e("K900ProtocolUtils", "Error checking for K900 specific broadcast", e);
|
|
577
577
|
}
|
|
578
578
|
} catch (Exception e) {
|
|
579
|
-
|
|
579
|
+
NativeLog.d("K900ProtocolUtils", "Not a K900 device: " + e.getMessage());
|
|
580
580
|
}
|
|
581
581
|
|
|
582
582
|
return false;
|
|
@@ -711,7 +711,7 @@ public class K900ProtocolUtils {
|
|
|
711
711
|
*/
|
|
712
712
|
public static FilePacketInfo extractFilePacket(byte[] protocolData) {
|
|
713
713
|
if (!isK900ProtocolFormat(protocolData) || protocolData.length < 31) {
|
|
714
|
-
|
|
714
|
+
NativeLog.e("K900ProtocolUtils", "extractFilePacket: Invalid format or too short. Length=" +
|
|
715
715
|
(protocolData != null ? protocolData.length : 0) +
|
|
716
716
|
", isK900Format=" + isK900ProtocolFormat(protocolData));
|
|
717
717
|
return null;
|
|
@@ -757,7 +757,7 @@ public class K900ProtocolUtils {
|
|
|
757
757
|
|
|
758
758
|
// Verify packet has enough data
|
|
759
759
|
if (protocolData.length < pos + info.packSize + LENGTH_FILE_VERIFY + LENGTH_FILE_END) {
|
|
760
|
-
|
|
760
|
+
NativeLog.e("K900ProtocolUtils", "File packet too short for data. Need: " +
|
|
761
761
|
(pos + info.packSize + LENGTH_FILE_VERIFY + LENGTH_FILE_END) +
|
|
762
762
|
", Have: " + protocolData.length +
|
|
763
763
|
", packSize=" + info.packSize + ", pos=" + pos);
|
|
@@ -788,13 +788,13 @@ public class K900ProtocolUtils {
|
|
|
788
788
|
info.isValid = (calculatedVerify == info.verifyCode);
|
|
789
789
|
|
|
790
790
|
if (!info.isValid) {
|
|
791
|
-
|
|
791
|
+
NativeLog.e("K900ProtocolUtils", "File packet checksum failed. Expected: " +
|
|
792
792
|
String.format("%02X", info.verifyCode) + ", Calculated: " +
|
|
793
793
|
String.format("%02X", calculatedVerify));
|
|
794
794
|
} else if (info.packIndex == 0
|
|
795
795
|
|| info.packIndex % 32 == 0
|
|
796
796
|
|| info.packIndex == (info.fileSize + FILE_PACK_SIZE - 1) / FILE_PACK_SIZE - 1) {
|
|
797
|
-
|
|
797
|
+
NativeLog.d("K900ProtocolUtils", "File packet extracted successfully: index=" + info.packIndex +
|
|
798
798
|
", size=" + info.packSize + ", fileName=" + info.fileName);
|
|
799
799
|
}
|
|
800
800
|
|
|
@@ -820,7 +820,7 @@ public class K900ProtocolUtils {
|
|
|
820
820
|
|
|
821
821
|
return message.toString();
|
|
822
822
|
} catch (JSONException e) {
|
|
823
|
-
|
|
823
|
+
NativeLog.e("K900ProtocolUtils", "Error creating file transfer ack", e);
|
|
824
824
|
return null;
|
|
825
825
|
}
|
|
826
826
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
package com.mentra.bluetoothsdk.utils;
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import com.mentra.bluetoothsdk.utils.NativeLog;
|
|
4
4
|
|
|
5
5
|
import java.util.Map;
|
|
6
6
|
import java.util.concurrent.ConcurrentHashMap;
|
|
@@ -21,7 +21,7 @@ public class MessageChunkReassembler {
|
|
|
21
21
|
cleanupTimedOutSessions();
|
|
22
22
|
|
|
23
23
|
if (msgId < 0 || fragCount <= 0 || fragIdx < 0 || fragIdx >= fragCount || data == null) {
|
|
24
|
-
|
|
24
|
+
NativeLog.w(TAG, "Dropping invalid binary fragment: msgId=" + msgId + ", index=" + fragIdx
|
|
25
25
|
+ ", total=" + fragCount);
|
|
26
26
|
return null;
|
|
27
27
|
}
|
|
@@ -36,7 +36,7 @@ public class MessageChunkReassembler {
|
|
|
36
36
|
return new BinarySession(msgId, fragCount);
|
|
37
37
|
}
|
|
38
38
|
if (existingSession.fragCount != fragCount) {
|
|
39
|
-
|
|
39
|
+
NativeLog.w(TAG, "fragCount mismatch for msgId " + msgId + ", resetting session");
|
|
40
40
|
return new BinarySession(msgId, fragCount);
|
|
41
41
|
}
|
|
42
42
|
return existingSession;
|
|
@@ -52,7 +52,7 @@ public class MessageChunkReassembler {
|
|
|
52
52
|
|
|
53
53
|
byte[] reassembled = session.reassemble();
|
|
54
54
|
activeBinarySessions.remove(msgId);
|
|
55
|
-
|
|
55
|
+
NativeLog.d(TAG, "Reassembled binary message of " + reassembled.length + " bytes from "
|
|
56
56
|
+ fragCount + " fragments");
|
|
57
57
|
return reassembled;
|
|
58
58
|
}
|
|
@@ -62,13 +62,13 @@ public class MessageChunkReassembler {
|
|
|
62
62
|
|
|
63
63
|
if (chunkId == null || chunkId.isEmpty() || totalChunks <= 0 || chunkIndex < 0
|
|
64
64
|
|| chunkIndex >= totalChunks || data == null) {
|
|
65
|
-
|
|
65
|
+
NativeLog.w(TAG, "Dropping invalid chunk metadata: id=" + chunkId + ", index=" + chunkIndex
|
|
66
66
|
+ ", total=" + totalChunks);
|
|
67
67
|
return null;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
if (activeSessions.size() >= MAX_CONCURRENT_SESSIONS && !activeSessions.containsKey(chunkId)) {
|
|
71
|
-
|
|
71
|
+
NativeLog.w(TAG, "Maximum concurrent chunk sessions reached, dropping oldest");
|
|
72
72
|
removeOldestSession();
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -77,7 +77,7 @@ public class MessageChunkReassembler {
|
|
|
77
77
|
return new ChunkSession(chunkId, totalChunks);
|
|
78
78
|
}
|
|
79
79
|
if (existingSession.totalChunks != totalChunks) {
|
|
80
|
-
|
|
80
|
+
NativeLog.w(TAG, "totalChunks mismatch for " + chunkId + " (expected "
|
|
81
81
|
+ existingSession.totalChunks + ", got " + totalChunks + "), resetting session");
|
|
82
82
|
return new ChunkSession(chunkId, totalChunks);
|
|
83
83
|
}
|
|
@@ -85,11 +85,11 @@ public class MessageChunkReassembler {
|
|
|
85
85
|
});
|
|
86
86
|
boolean added = session.addChunk(chunkIndex, data);
|
|
87
87
|
if (!added) {
|
|
88
|
-
|
|
88
|
+
NativeLog.w(TAG, "Failed to add chunk " + chunkIndex + " to session " + chunkId);
|
|
89
89
|
return null;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
NativeLog.d(TAG, "Added chunk " + chunkIndex + "/" + (totalChunks - 1) + " for session " + chunkId);
|
|
93
93
|
|
|
94
94
|
if (!session.isComplete()) {
|
|
95
95
|
return null;
|
|
@@ -97,7 +97,7 @@ public class MessageChunkReassembler {
|
|
|
97
97
|
|
|
98
98
|
String reassembled = session.reassemble();
|
|
99
99
|
activeSessions.remove(chunkId);
|
|
100
|
-
|
|
100
|
+
NativeLog.d(TAG, "Reassembled message of " + reassembled.length() + " bytes from " + totalChunks + " chunks");
|
|
101
101
|
return reassembled;
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
package com.mentra.bluetoothsdk.utils;
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import com.mentra.bluetoothsdk.utils.NativeLog;
|
|
4
4
|
|
|
5
5
|
import org.json.JSONException;
|
|
6
6
|
import org.json.JSONObject;
|
|
@@ -52,7 +52,7 @@ public class MessageChunker {
|
|
|
52
52
|
boolean needsChunking = messageBytes > MESSAGE_SIZE_THRESHOLD;
|
|
53
53
|
|
|
54
54
|
if (needsChunking) {
|
|
55
|
-
|
|
55
|
+
NativeLog.d(TAG, "Message size " + messageBytes + " exceeds threshold " + MESSAGE_SIZE_THRESHOLD + ", will chunk");
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
return needsChunking;
|
|
@@ -83,7 +83,7 @@ public class MessageChunker {
|
|
|
83
83
|
for (int chunkSize = INITIAL_CHUNK_DATA_SIZE; chunkSize >= MIN_CHUNK_DATA_SIZE; chunkSize--) {
|
|
84
84
|
List<JSONObject> chunks = buildChunks(messageBytes, chunkId, messageId, chunkSize);
|
|
85
85
|
if (allChunksFit(chunks, wakeup)) {
|
|
86
|
-
|
|
86
|
+
NativeLog.d(TAG, "Creating " + chunks.size() + " chunks for message of size " + totalBytes
|
|
87
87
|
+ " bytes using " + chunkSize + "-byte UTF-8 slices");
|
|
88
88
|
return chunks;
|
|
89
89
|
}
|
|
@@ -115,7 +115,7 @@ public class MessageChunker {
|
|
|
115
115
|
|
|
116
116
|
chunks.add(chunk);
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
NativeLog.d(TAG, "Created chunk " + i + "/" + (totalChunks - 1) + " with " + chunkData.getBytes(StandardCharsets.UTF_8).length + " bytes");
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
return chunks;
|
|
@@ -125,7 +125,7 @@ public class MessageChunker {
|
|
|
125
125
|
for (int i = 0; i < chunks.size(); i++) {
|
|
126
126
|
byte[] packed = K900ProtocolUtils.packJsonToK900(chunks.get(i).toString(), wakeup && i == 0);
|
|
127
127
|
if (packed == null || packed.length > MAX_PACKED_CHUNK_SIZE) {
|
|
128
|
-
|
|
128
|
+
NativeLog.d(TAG, "Chunk " + i + " packed to " + (packed != null ? packed.length : 0)
|
|
129
129
|
+ " bytes, exceeding " + MAX_PACKED_CHUNK_SIZE);
|
|
130
130
|
return false;
|
|
131
131
|
}
|
|
@@ -261,7 +261,7 @@ public class MessageChunker {
|
|
|
261
261
|
fragments.add(new BinaryFragment(flags, msgId, i, fragCount, fragPayload));
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
|
|
264
|
+
NativeLog.d(TAG, "Created " + fragments.size() + " binary fragments for "
|
|
265
265
|
+ payload.length + " byte payload");
|
|
266
266
|
return fragments;
|
|
267
267
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk.utils;
|
|
2
|
+
|
|
3
|
+
import com.mentra.bluetoothsdk.Bridge;
|
|
4
|
+
import java.util.HashMap;
|
|
5
|
+
import java.util.Map;
|
|
6
|
+
|
|
7
|
+
/** Writes SDK diagnostics to both the native console and the SDK's JavaScript log event. */
|
|
8
|
+
public final class NativeLog {
|
|
9
|
+
public static final int DEBUG = android.util.Log.DEBUG;
|
|
10
|
+
|
|
11
|
+
private NativeLog() {}
|
|
12
|
+
|
|
13
|
+
/** Preserves Android's per-tag log-level check for existing SDK callers. */
|
|
14
|
+
public static boolean isLoggable(String tag, int level) {
|
|
15
|
+
return android.util.Log.isLoggable(tag, level);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Emits a verbose diagnostic to both sinks. */
|
|
19
|
+
public static int v(String tag, String message) {
|
|
20
|
+
return write(android.util.Log.VERBOSE, tag, message, null);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Emits a verbose diagnostic with its stack trace to both sinks. */
|
|
24
|
+
public static int v(String tag, String message, Throwable error) {
|
|
25
|
+
return write(android.util.Log.VERBOSE, tag, message, error);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Emits a debug diagnostic to both sinks. */
|
|
29
|
+
public static int d(String tag, String message) {
|
|
30
|
+
return write(DEBUG, tag, message, null);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Emits a debug diagnostic with its stack trace to both sinks. */
|
|
34
|
+
public static int d(String tag, String message, Throwable error) {
|
|
35
|
+
return write(DEBUG, tag, message, error);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Emits an informational diagnostic to both sinks. */
|
|
39
|
+
public static int i(String tag, String message) {
|
|
40
|
+
return write(android.util.Log.INFO, tag, message, null);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Emits an informational diagnostic with its stack trace to both sinks. */
|
|
44
|
+
public static int i(String tag, String message, Throwable error) {
|
|
45
|
+
return write(android.util.Log.INFO, tag, message, error);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Emits a warning to both sinks. */
|
|
49
|
+
public static int w(String tag, String message) {
|
|
50
|
+
return write(android.util.Log.WARN, tag, message, null);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Emits a warning with its stack trace to both sinks. */
|
|
54
|
+
public static int w(String tag, String message, Throwable error) {
|
|
55
|
+
return write(android.util.Log.WARN, tag, message, error);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Emits an error to both sinks. */
|
|
59
|
+
public static int e(String tag, String message) {
|
|
60
|
+
return write(android.util.Log.ERROR, tag, message, null);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Emits an error with its stack trace to both sinks. */
|
|
64
|
+
public static int e(String tag, String message, Throwable error) {
|
|
65
|
+
return write(android.util.Log.ERROR, tag, message, error);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private static int write(int priority, String tag, String message, Throwable error) {
|
|
69
|
+
String text = String.valueOf(message);
|
|
70
|
+
if (error != null) text += "\n" + android.util.Log.getStackTraceString(error);
|
|
71
|
+
int result = android.util.Log.println(priority, tag, text);
|
|
72
|
+
Map<String, Object> body = new HashMap<>();
|
|
73
|
+
body.put("message", "[" + priorityLabel(priority) + "/" + tag + "] " + text);
|
|
74
|
+
// Dispatch directly: Bridge.log uses this logger too. Never tail logcat here,
|
|
75
|
+
// because React Native writes console output back to it.
|
|
76
|
+
Bridge.sendTypedMessage("log", body);
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private static String priorityLabel(int priority) {
|
|
81
|
+
switch (priority) {
|
|
82
|
+
case android.util.Log.VERBOSE: return "V";
|
|
83
|
+
case android.util.Log.DEBUG: return "D";
|
|
84
|
+
case android.util.Log.WARN: return "W";
|
|
85
|
+
case android.util.Log.ERROR: return "E";
|
|
86
|
+
default: return "I";
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -5,7 +5,7 @@ import java.io.IOException
|
|
|
5
5
|
import java.util.UUID
|
|
6
6
|
|
|
7
7
|
import android.content.Context
|
|
8
|
-
import
|
|
8
|
+
import com.mentra.bluetoothsdk.utils.NativeLog as Log
|
|
9
9
|
|
|
10
10
|
import com.mentra.bluetoothsdk.Bridge
|
|
11
11
|
import com.mentra.bluetoothsdk.DeviceStore
|
|
@@ -695,4 +695,4 @@ object NexEventUtils {
|
|
|
695
695
|
Log.e(TAG, "NOTIF: Error sending ble command received event", e)
|
|
696
696
|
}
|
|
697
697
|
}
|
|
698
|
-
}
|
|
698
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
package com.mentra.bluetoothsdk.utils.audio;
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import com.mentra.bluetoothsdk.utils.NativeLog;
|
|
4
4
|
|
|
5
5
|
import java.util.Arrays;
|
|
6
6
|
import java.util.concurrent.ArrayBlockingQueue;
|
|
@@ -76,7 +76,7 @@ public final class Ar99OpusPcmDecoder extends Thread {
|
|
|
76
76
|
}
|
|
77
77
|
byte[] payloadCopy = Arrays.copyOf(opusPayload, opusPayload.length);
|
|
78
78
|
if (!taskQueue.offer(new Task(TaskType.DECODE, payloadCopy))) {
|
|
79
|
-
|
|
79
|
+
NativeLog.w(TAG, "AR99 Opus task queue full, drop notify len=" + payloadCopy.length);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -123,7 +123,7 @@ public final class Ar99OpusPcmDecoder extends Thread {
|
|
|
123
123
|
}
|
|
124
124
|
} catch (InterruptedException e) {
|
|
125
125
|
if (running) {
|
|
126
|
-
|
|
126
|
+
NativeLog.w(TAG, "AR99 Opus worker interrupted: " + e.getMessage());
|
|
127
127
|
}
|
|
128
128
|
} finally {
|
|
129
129
|
taskQueue.clear();
|
|
@@ -150,7 +150,7 @@ public final class Ar99OpusPcmDecoder extends Thread {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
if (buffer.length + chunk.length > MAX_BUFFER_SIZE) {
|
|
153
|
-
|
|
153
|
+
NativeLog.w(
|
|
154
154
|
TAG,
|
|
155
155
|
"AR99 Opus buffer overflow, clear"
|
|
156
156
|
+ ", oldBuf="
|
|
@@ -179,7 +179,7 @@ public final class Ar99OpusPcmDecoder extends Thread {
|
|
|
179
179
|
if (drop > 0) {
|
|
180
180
|
totalResyncDropBytes += drop;
|
|
181
181
|
headerLooksStable = false;
|
|
182
|
-
|
|
182
|
+
NativeLog.w(
|
|
183
183
|
TAG,
|
|
184
184
|
"AR99 Opus resync drop(no header)"
|
|
185
185
|
+ " notify#="
|
|
@@ -200,7 +200,7 @@ public final class Ar99OpusPcmDecoder extends Thread {
|
|
|
200
200
|
headerLooksStable = false;
|
|
201
201
|
headerMismatch++;
|
|
202
202
|
totalHeaderMismatchCount++;
|
|
203
|
-
|
|
203
|
+
NativeLog.w(
|
|
204
204
|
TAG,
|
|
205
205
|
"AR99 Opus resync shift"
|
|
206
206
|
+ " notify#="
|
|
@@ -234,7 +234,7 @@ public final class Ar99OpusPcmDecoder extends Thread {
|
|
|
234
234
|
totalHeaderMismatchCount++;
|
|
235
235
|
headerLooksStable = false;
|
|
236
236
|
if (totalFrameCount <= MAX_DIAG_FRAMES || !headerLooksStable) {
|
|
237
|
-
|
|
237
|
+
NativeLog.w(
|
|
238
238
|
TAG,
|
|
239
239
|
"AR99 Opus frame header mismatch"
|
|
240
240
|
+ " frame#="
|
|
@@ -265,7 +265,7 @@ public final class Ar99OpusPcmDecoder extends Thread {
|
|
|
265
265
|
decodeFail++;
|
|
266
266
|
totalDecodeFailCount++;
|
|
267
267
|
if (totalFrameCount <= MAX_DIAG_FRAMES || !headerLooksStable) {
|
|
268
|
-
|
|
268
|
+
NativeLog.w(
|
|
269
269
|
TAG,
|
|
270
270
|
"AR99 Opus frame decode failed"
|
|
271
271
|
+ " frame#="
|
|
@@ -289,7 +289,7 @@ public final class Ar99OpusPcmDecoder extends Thread {
|
|
|
289
289
|
|| skipPayload > 0
|
|
290
290
|
|| pcmFrames == 0
|
|
291
291
|
|| !headerLooksStable) {
|
|
292
|
-
|
|
292
|
+
NativeLog.d(
|
|
293
293
|
TAG,
|
|
294
294
|
"AR99 Opus decode summary"
|
|
295
295
|
+ " notify#="
|
|
@@ -337,7 +337,7 @@ public final class Ar99OpusPcmDecoder extends Thread {
|
|
|
337
337
|
int bytes = samples * CHANNELS * 2;
|
|
338
338
|
return Arrays.copyOf(pcm, bytes);
|
|
339
339
|
} catch (OpusException | AssertionError | RuntimeException e) {
|
|
340
|
-
|
|
340
|
+
NativeLog.w(
|
|
341
341
|
TAG,
|
|
342
342
|
"AR99 Opus decode failed len="
|
|
343
343
|
+ opusPayload.length
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
package com.mentra.bluetoothsdk.utils.audio;
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import com.mentra.bluetoothsdk.utils.NativeLog;
|
|
4
4
|
|
|
5
5
|
import java.io.ByteArrayInputStream;
|
|
6
6
|
import java.io.ByteArrayOutputStream;
|
|
@@ -132,7 +132,7 @@ public class ByteUtilAudioPlayer {
|
|
|
132
132
|
|
|
133
133
|
if(str.length() + destoffset > dest.length)
|
|
134
134
|
{
|
|
135
|
-
|
|
135
|
+
NativeLog.v("ByteUtilAudioPlayer","error string2Bytes src.length="+str.length()+",dest.length="+dest.length+",destoffset="+destoffset);
|
|
136
136
|
return false;
|
|
137
137
|
}
|
|
138
138
|
|
|
@@ -189,7 +189,7 @@ public class ByteUtilAudioPlayer {
|
|
|
189
189
|
body = new String(bytes,offset, len,encode);
|
|
190
190
|
body = body.trim();
|
|
191
191
|
} catch (UnsupportedEncodingException e) {
|
|
192
|
-
e
|
|
192
|
+
com.mentra.bluetoothsdk.utils.NativeLog.e("ByteUtilAudioPlayer", "Native exception", e);
|
|
193
193
|
}
|
|
194
194
|
return body;
|
|
195
195
|
}
|
|
@@ -204,7 +204,7 @@ public class ByteUtilAudioPlayer {
|
|
|
204
204
|
|
|
205
205
|
if(src.length < offset + len || dest.length < destoffset +len)
|
|
206
206
|
{
|
|
207
|
-
|
|
207
|
+
NativeLog.v("ByteUtilAudioPlayer","error copyBytes src.length="+src.length+",dest.length="+dest.length);
|
|
208
208
|
return false;
|
|
209
209
|
}
|
|
210
210
|
for(int i = 0; i<len; i++)
|
|
@@ -251,17 +251,17 @@ public class ByteUtilAudioPlayer {
|
|
|
251
251
|
//BLog.v(CTConst.TAG,"copyBytes src="+src+",dest="+dest+",offset="+offset+",len="+len+",destoffset="+destoffset);
|
|
252
252
|
if(src == null || dest == null)
|
|
253
253
|
{
|
|
254
|
-
|
|
254
|
+
NativeLog.v("ByteUtilAudioPlayer","compareBytes error");
|
|
255
255
|
return false;
|
|
256
256
|
}
|
|
257
257
|
if(len != destlen)
|
|
258
258
|
{
|
|
259
|
-
|
|
259
|
+
NativeLog.v("ByteUtilAudioPlayer","error compareBytes len="+len+",destlen="+destlen);
|
|
260
260
|
return false;
|
|
261
261
|
}
|
|
262
262
|
if(src.length < offset + len || dest.length < destoffset +destlen)
|
|
263
263
|
{
|
|
264
|
-
|
|
264
|
+
NativeLog.v("ByteUtilAudioPlayer","error compareBytes src.length="+src.length+",dest.length="+dest.length);
|
|
265
265
|
return false;
|
|
266
266
|
}
|
|
267
267
|
for(int i = 0; i<len; i++)
|