@mentra/bluetooth-sdk 3.2.0-dev.232 → 3.2.0-dev.233
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/android/src/main/java/com/mentra/bluetoothsdk/GeneratedReleaseMetadata.kt +5 -5
- package/android/src/main/java/com/mentra/bluetoothsdk/services/PhoneMic.kt +10 -18
- package/android/src/test/java/com/mentra/bluetoothsdk/services/PhoneMicFallbackTest.kt +73 -0
- package/build/generated/releaseMetadata.js +5 -5
- package/build/generated/releaseMetadata.js.map +1 -1
- package/ios/Source/BluetoothSdkDefaults.swift +1 -1
- package/ios/Source/GeneratedReleaseMetadata.swift +5 -5
- package/package.json +1 -1
- package/src/generated/releaseMetadata.ts +5 -5
|
@@ -3,9 +3,9 @@ package com.mentra.bluetoothsdk
|
|
|
3
3
|
/** Generated by release CI. Do not edit in a release checkout. */
|
|
4
4
|
internal object GeneratedReleaseMetadata {
|
|
5
5
|
const val FAMILY_BASE_VERSION: String = "3.2.0"
|
|
6
|
-
const val RELEASE_IDENTITY: String = "3.2.0-dev.
|
|
7
|
-
const val RELEASE_SET_ID: String = "mentra-3.2.0-dev.
|
|
8
|
-
const val SOURCE_COMMIT: String = "
|
|
9
|
-
const val OTA_MANIFEST_URL: String = "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.
|
|
10
|
-
const val OTA_MANIFEST_SHA256: String = "
|
|
6
|
+
const val RELEASE_IDENTITY: String = "3.2.0-dev.233"
|
|
7
|
+
const val RELEASE_SET_ID: String = "mentra-3.2.0-dev.233"
|
|
8
|
+
const val SOURCE_COMMIT: String = "626082d1f9ddc939fc90eefc7af897878a79cbb0"
|
|
9
|
+
const val OTA_MANIFEST_URL: String = "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.233.json"
|
|
10
|
+
const val OTA_MANIFEST_SHA256: String = "70fce776c2f8653db65522606340c0b1d7246398c205cf2da45c2f3177909f99"
|
|
11
11
|
}
|
|
@@ -241,6 +241,12 @@ class PhoneMic private constructor(private val context: Context) {
|
|
|
241
241
|
return true
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
+
// Reject unavailable candidates before disturbing the active recorder. DeviceManager
|
|
245
|
+
// tries these in one ranked pass, so an unsupported HQ profile must not stop HFP.
|
|
246
|
+
if (mode == MicTypes.BLUETOOTH && !isHighQualityBluetoothAvailable()) return false
|
|
247
|
+
if (mode == MicTypes.BLUETOOTH_CLASSIC && !audioManager.isBluetoothScoAvailableOffCall) return false
|
|
248
|
+
if (mode !in listOf(MicTypes.PHONE_INTERNAL, MicTypes.BLUETOOTH_CLASSIC, MicTypes.BLUETOOTH)) return false
|
|
249
|
+
|
|
244
250
|
// recording with a different mode, so stop recording and start recording with the new mode:
|
|
245
251
|
if (isRecording.get()) {
|
|
246
252
|
Bridge.log(
|
|
@@ -256,14 +262,10 @@ class PhoneMic private constructor(private val context: Context) {
|
|
|
256
262
|
return false
|
|
257
263
|
}
|
|
258
264
|
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
return false
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
lastModeChangeTime = System.currentTimeMillis()
|
|
265
|
+
// Do not debounce ranked candidates: failure must allow the next source to
|
|
266
|
+
// start immediately. isRecordingWithMode above already makes repeated starts
|
|
267
|
+
// of the selected source idempotent. The legacy startRecording entry retains
|
|
268
|
+
// its own debounce for independent recording requests.
|
|
267
269
|
|
|
268
270
|
// Check for conflicts
|
|
269
271
|
if (isPhoneCallActive) {
|
|
@@ -291,20 +293,10 @@ class PhoneMic private constructor(private val context: Context) {
|
|
|
291
293
|
}
|
|
292
294
|
MicTypes.BLUETOOTH_CLASSIC -> {
|
|
293
295
|
Bridge.log("MIC: Starting Bluetooth Classic (SCO)")
|
|
294
|
-
if (!audioManager.isBluetoothScoAvailableOffCall) {
|
|
295
|
-
Bridge.log("MIC: Bluetooth SCO not available")
|
|
296
|
-
notifyDeviceManager("bt_classic_unavailable", emptyList())
|
|
297
|
-
return false
|
|
298
|
-
}
|
|
299
296
|
return startRecordingBtClassic()
|
|
300
297
|
}
|
|
301
298
|
MicTypes.BLUETOOTH -> {
|
|
302
299
|
Bridge.log("MIC: Starting high-quality Bluetooth mic")
|
|
303
|
-
if (!isHighQualityBluetoothAvailable()) {
|
|
304
|
-
Bridge.log("MIC: High-quality Bluetooth not available")
|
|
305
|
-
notifyDeviceManager("bt_hq_unavailable", emptyList())
|
|
306
|
-
return false
|
|
307
|
-
}
|
|
308
300
|
return startRecordingBtHighQuality()
|
|
309
301
|
}
|
|
310
302
|
else -> {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
package com.mentra.bluetoothsdk.services
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.media.AudioManager
|
|
6
|
+
import com.mentra.bluetoothsdk.Bridge
|
|
7
|
+
import com.mentra.bluetoothsdk.utils.MicTypes
|
|
8
|
+
import org.assertj.core.api.Assertions.assertThat
|
|
9
|
+
import org.junit.After
|
|
10
|
+
import org.junit.Before
|
|
11
|
+
import org.junit.Test
|
|
12
|
+
import org.junit.runner.RunWith
|
|
13
|
+
import org.robolectric.RobolectricTestRunner
|
|
14
|
+
import org.robolectric.RuntimeEnvironment
|
|
15
|
+
import org.robolectric.Shadows.shadowOf
|
|
16
|
+
import org.robolectric.annotation.Config
|
|
17
|
+
import org.robolectric.annotation.LooperMode
|
|
18
|
+
import org.robolectric.shadows.ShadowAudioRecord
|
|
19
|
+
|
|
20
|
+
@RunWith(RobolectricTestRunner::class)
|
|
21
|
+
@Config(sdk = [28], manifest = Config.NONE)
|
|
22
|
+
@LooperMode(LooperMode.Mode.PAUSED)
|
|
23
|
+
class PhoneMicFallbackTest {
|
|
24
|
+
private lateinit var mic: PhoneMic
|
|
25
|
+
|
|
26
|
+
@Before
|
|
27
|
+
fun setUp() {
|
|
28
|
+
val context = RuntimeEnvironment.getApplication()
|
|
29
|
+
shadowOf(context).grantPermissions(Manifest.permission.RECORD_AUDIO)
|
|
30
|
+
Bridge.initialize(context)
|
|
31
|
+
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
|
32
|
+
shadowOf(audioManager).setIsBluetoothScoAvailableOffCall(true)
|
|
33
|
+
// Keep the test recorder alive without forwarding synthetic audio to DeviceManager.
|
|
34
|
+
ShadowAudioRecord.setSource(object : ShadowAudioRecord.AudioRecordSource {
|
|
35
|
+
override fun readInShortArray(buffer: ShortArray, offset: Int, size: Int, blocking: Boolean): Int {
|
|
36
|
+
try { Thread.sleep(1) } catch (_: InterruptedException) {}
|
|
37
|
+
return 0
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
val constructor = PhoneMic::class.java.getDeclaredConstructor(Context::class.java)
|
|
41
|
+
constructor.isAccessible = true
|
|
42
|
+
mic = constructor.newInstance(context)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@After
|
|
46
|
+
fun tearDown() {
|
|
47
|
+
mic.cleanup()
|
|
48
|
+
ShadowAudioRecord.clearSource()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Test
|
|
52
|
+
fun unavailableHighQualityProfileDoesNotBlockImmediateHfpFallback() {
|
|
53
|
+
assertThat(mic.startMode(MicTypes.BLUETOOTH)).isFalse()
|
|
54
|
+
assertThat(mic.startMode(MicTypes.BLUETOOTH_CLASSIC)).isTrue()
|
|
55
|
+
assertThat(mic.isRecordingWithMode(MicTypes.BLUETOOTH_CLASSIC)).isTrue()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@Test
|
|
59
|
+
fun reevaluatingUnavailableProfileDoesNotStopActiveHfpRecorder() {
|
|
60
|
+
assertThat(mic.startMode(MicTypes.BLUETOOTH_CLASSIC)).isTrue()
|
|
61
|
+
assertThat(mic.startMode(MicTypes.BLUETOOTH)).isFalse()
|
|
62
|
+
assertThat(mic.isRecordingWithMode(MicTypes.BLUETOOTH_CLASSIC)).isTrue()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@Test
|
|
66
|
+
fun switchingFromPhoneToHfpDoesNotRequireWaitingForDebounce() {
|
|
67
|
+
assertThat(mic.startMode(MicTypes.PHONE_INTERNAL)).isTrue()
|
|
68
|
+
assertThat(mic.startMode(MicTypes.BLUETOOTH)).isFalse()
|
|
69
|
+
assertThat(mic.isRecordingWithMode(MicTypes.PHONE_INTERNAL)).isTrue()
|
|
70
|
+
assertThat(mic.startMode(MicTypes.BLUETOOTH_CLASSIC)).isTrue()
|
|
71
|
+
assertThat(mic.isRecordingWithMode(MicTypes.BLUETOOTH_CLASSIC)).isTrue()
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export const BLUETOOTH_SDK_RELEASE_METADATA = Object.freeze({
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"familyBaseVersion": "3.2.0",
|
|
4
|
-
"releaseIdentity": "3.2.0-dev.
|
|
5
|
-
"releaseSetId": "mentra-3.2.0-dev.
|
|
6
|
-
"sourceCommit": "
|
|
7
|
-
"otaManifestUrl": "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.
|
|
8
|
-
"otaManifestSha256": "
|
|
4
|
+
"releaseIdentity": "3.2.0-dev.233",
|
|
5
|
+
"releaseSetId": "mentra-3.2.0-dev.233",
|
|
6
|
+
"sourceCommit": "626082d1f9ddc939fc90eefc7af897878a79cbb0",
|
|
7
|
+
"otaManifestUrl": "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.233.json",
|
|
8
|
+
"otaManifestSha256": "70fce776c2f8653db65522606340c0b1d7246398c205cf2da45c2f3177909f99"
|
|
9
9
|
});
|
|
10
10
|
//# sourceMappingURL=releaseMetadata.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,8BAA8B,GAA0C,MAAM,CAAC,MAAM,CAAC;IACjG,eAAe,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,eAAe;IAClC,cAAc,EAAE,sBAAsB;IACtC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,wHAAwH;IAC1I,mBAAmB,EAAE,kEAAkE;CACxF,CAAC,CAAA","sourcesContent":["/** Generated by release CI. Do not edit in a release checkout. */\nexport interface BluetoothSdkReleaseMetadata {\n schemaVersion: 1\n familyBaseVersion: string | null\n releaseIdentity: string | null\n releaseSetId: string | null\n sourceCommit: string | null\n otaManifestUrl: string | null\n otaManifestSha256: string | null\n}\n\nexport const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"3.2.0\",\n \"releaseIdentity\": \"3.2.0-dev.
|
|
1
|
+
{"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,8BAA8B,GAA0C,MAAM,CAAC,MAAM,CAAC;IACjG,eAAe,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,eAAe;IAClC,cAAc,EAAE,sBAAsB;IACtC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,wHAAwH;IAC1I,mBAAmB,EAAE,kEAAkE;CACxF,CAAC,CAAA","sourcesContent":["/** Generated by release CI. Do not edit in a release checkout. */\nexport interface BluetoothSdkReleaseMetadata {\n schemaVersion: 1\n familyBaseVersion: string | null\n releaseIdentity: string | null\n releaseSetId: string | null\n sourceCommit: string | null\n otaManifestUrl: string | null\n otaManifestSha256: string | null\n}\n\nexport const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"3.2.0\",\n \"releaseIdentity\": \"3.2.0-dev.233\",\n \"releaseSetId\": \"mentra-3.2.0-dev.233\",\n \"sourceCommit\": \"626082d1f9ddc939fc90eefc7af897878a79cbb0\",\n \"otaManifestUrl\": \"https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.233.json\",\n \"otaManifestSha256\": \"70fce776c2f8653db65522606340c0b1d7246398c205cf2da45c2f3177909f99\"\n})\n"]}
|
|
@@ -11,7 +11,7 @@ enum BluetoothSdkDefaults {
|
|
|
11
11
|
static let voiceActivityDetectionEnabled = false
|
|
12
12
|
static let loudnessGateEnabled = false
|
|
13
13
|
private static let infoSdkVersionKey = "MentraBluetoothSdkVersion"
|
|
14
|
-
private static let swiftPackageSdkVersion = "3.2.0-dev.
|
|
14
|
+
private static let swiftPackageSdkVersion = "3.2.0-dev.233"
|
|
15
15
|
private static let swiftPackageSdkVersionPlaceholder = "__MENTRA" + "_BLUETOOTH_SDK_VERSION__"
|
|
16
16
|
|
|
17
17
|
private static func normalizedSdkVersion(_ value: String?) -> String? {
|
|
@@ -3,9 +3,9 @@ import Foundation
|
|
|
3
3
|
/// Generated by release CI. Do not edit in a release checkout.
|
|
4
4
|
enum GeneratedReleaseMetadata {
|
|
5
5
|
static let familyBaseVersion = "3.2.0"
|
|
6
|
-
static let releaseIdentity = "3.2.0-dev.
|
|
7
|
-
static let releaseSetId = "mentra-3.2.0-dev.
|
|
8
|
-
static let sourceCommit = "
|
|
9
|
-
static let otaManifestUrl = "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.
|
|
10
|
-
static let otaManifestSha256 = "
|
|
6
|
+
static let releaseIdentity = "3.2.0-dev.233"
|
|
7
|
+
static let releaseSetId = "mentra-3.2.0-dev.233"
|
|
8
|
+
static let sourceCommit = "626082d1f9ddc939fc90eefc7af897878a79cbb0"
|
|
9
|
+
static let otaManifestUrl = "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.233.json"
|
|
10
|
+
static let otaManifestSha256 = "70fce776c2f8653db65522606340c0b1d7246398c205cf2da45c2f3177909f99"
|
|
11
11
|
}
|
package/package.json
CHANGED
|
@@ -12,9 +12,9 @@ export interface BluetoothSdkReleaseMetadata {
|
|
|
12
12
|
export const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({
|
|
13
13
|
"schemaVersion": 1,
|
|
14
14
|
"familyBaseVersion": "3.2.0",
|
|
15
|
-
"releaseIdentity": "3.2.0-dev.
|
|
16
|
-
"releaseSetId": "mentra-3.2.0-dev.
|
|
17
|
-
"sourceCommit": "
|
|
18
|
-
"otaManifestUrl": "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.
|
|
19
|
-
"otaManifestSha256": "
|
|
15
|
+
"releaseIdentity": "3.2.0-dev.233",
|
|
16
|
+
"releaseSetId": "mentra-3.2.0-dev.233",
|
|
17
|
+
"sourceCommit": "626082d1f9ddc939fc90eefc7af897878a79cbb0",
|
|
18
|
+
"otaManifestUrl": "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.233.json",
|
|
19
|
+
"otaManifestSha256": "70fce776c2f8653db65522606340c0b1d7246398c205cf2da45c2f3177909f99"
|
|
20
20
|
})
|