@qusaieilouti99/call-manager 0.1.69 → 0.1.70

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.
@@ -30,9 +30,6 @@ import android.telecom.PhoneAccountHandle
30
30
  import android.telecom.TelecomManager
31
31
  import android.telecom.VideoProfile
32
32
  import android.util.Log
33
- import kotlinx.coroutines.CoroutineScope
34
- import kotlinx.coroutines.Dispatchers
35
- import kotlinx.coroutines.launch
36
33
  import org.json.JSONArray
37
34
  import org.json.JSONObject
38
35
  import java.util.concurrent.ConcurrentHashMap
@@ -275,8 +272,11 @@ object CallEngine {
275
272
 
276
273
  val isVideoCall = callType == "Video"
277
274
  if (!canMakeMultipleCalls && activeCalls.isNotEmpty()) {
278
- activeCalls.values.filter { it.state == CallState.ACTIVE }
279
- .forEach { holdCallInternal(it.callId, heldBySystem = false) }
275
+ activeCalls.values.forEach {
276
+ if (it.state == CallState.ACTIVE) {
277
+ holdCallInternal(it.callId, heldBySystem = false)
278
+ }
279
+ }
280
280
  }
281
281
 
282
282
  // Track dialing state
@@ -653,14 +653,16 @@ object CallEngine {
653
653
  AudioDeviceInfo.TYPE_WIRED_HEADPHONES, AudioDeviceInfo.TYPE_WIRED_HEADSET -> {
654
654
  devices.add("Headset")
655
655
  }
656
- // Speaker and Earpiece already added above
656
+ // Speaker and Earpiece already added above if they are reported, but explicit add handles cases where they are not
657
657
  }
658
658
  }
659
659
  } else {
660
660
  // For older versions, check for Bluetooth and Headset
661
+ @Suppress("DEPRECATION")
661
662
  if (audioManager?.isBluetoothA2dpOn == true || audioManager?.isBluetoothScoOn == true) {
662
663
  devices.add("Bluetooth")
663
664
  }
665
+ @Suppress("DEPRECATION")
664
666
  if (audioManager?.isWiredHeadsetOn == true) {
665
667
  devices.add("Headset")
666
668
  }
@@ -669,6 +671,9 @@ object CallEngine {
669
671
  val currentRoute = getCurrentAudioRoute()
670
672
  Log.d(TAG, "Available audio devices: ${devices.toList()}, current route: $currentRoute")
671
673
 
674
+ // Update last known audio routes info
675
+ lastAudioRoutesInfo = AudioRoutesInfo(devices.toTypedArray(), currentRoute)
676
+
672
677
  return AudioRoutesInfo(devices.toTypedArray(), currentRoute)
673
678
  }
674
679
 
@@ -715,23 +720,6 @@ object CallEngine {
715
720
  }
716
721
  }
717
722
 
718
- val newRoute = getCurrentAudioRoute()
719
- if (previousRoute != newRoute) {
720
- emitEvent(CallEventType.AUDIO_ROUTE_CHANGED, JSONObject().put("route", newRoute))
721
- }
722
- }
723
-
724
- // UNIFIED event emission - always sends full audio context
725
- private fun emitAudioRouteChanged() {
726
- val audioInfo = getAudioDevices()
727
- val jsonPayload = JSONObject().apply {
728
- put("devices", JSONArray(audioInfo.devices.toList()))
729
- put("currentRoute", audioInfo.currentRoute)
730
- }
731
- emitEvent(CallEventType.AUDIO_ROUTE_CHANGED, jsonPayload)
732
- Log.d(TAG, "Audio route changed: ${audioInfo.currentRoute}, available: ${audioInfo.devices.toList()}")
733
- }
734
-
735
723
  private fun getCurrentAudioRoute(): String {
736
724
  return when {
737
725
  audioManager?.isBluetoothScoOn == true -> "Bluetooth"
@@ -742,7 +730,7 @@ object CallEngine {
742
730
  }
743
731
 
744
732
  private fun setInitialAudioRoute(callType: String) {
745
- val availableDevices = getAudioDevices()
733
+ val availableDevices = getAudioDevices() // This will update lastAudioRoutesInfo
746
734
 
747
735
  val defaultRoute = when {
748
736
  availableDevices.devices.contains("Bluetooth") -> "Bluetooth"
@@ -770,7 +758,19 @@ object CallEngine {
770
758
  }
771
759
  }
772
760
 
773
- // --- Audio Device Callback (simplified) ---
761
+ // UNIFIED event emission - always sends full audio context
762
+ private fun emitAudioRouteChanged() {
763
+ // Re-calculate latest state to ensure accuracy
764
+ val audioInfo = getAudioDevices() // This updates lastAudioRoutesInfo internally
765
+ val jsonPayload = JSONObject().apply {
766
+ put("devices", JSONArray(audioInfo.devices.toList()))
767
+ put("currentRoute", audioInfo.currentRoute)
768
+ }
769
+ emitEvent(CallEventType.AUDIO_ROUTE_CHANGED, jsonPayload)
770
+ Log.d(TAG, "Audio route changed: ${audioInfo.currentRoute}, available: ${audioInfo.devices.toList()}")
771
+ }
772
+
773
+ // --- Audio Device Callback ---
774
774
  private val audioDeviceCallback = object : AudioDeviceCallback() {
775
775
  override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
776
776
  Log.d(TAG, "Audio devices added")
@@ -783,9 +783,10 @@ object CallEngine {
783
783
  }
784
784
  }
785
785
 
786
- // Separate event for when physical devices are added/removed
786
+ // Event for when physical devices are added/removed - includes full audio context
787
787
  private fun emitAudioDevicesChanged() {
788
- val audioInfo = getAudioDevices()
788
+ // Re-calculate latest state to ensure accuracy
789
+ val audioInfo = getAudioDevices() // This updates lastAudioRoutesInfo internally
789
790
  val jsonPayload = JSONObject().apply {
790
791
  put("devices", JSONArray(audioInfo.devices.toList()))
791
792
  put("currentRoute", audioInfo.currentRoute)
@@ -794,6 +795,7 @@ object CallEngine {
794
795
  Log.d(TAG, "Audio devices changed: available: ${audioInfo.devices.toList()}")
795
796
  }
796
797
 
798
+
797
799
  fun registerAudioDeviceCallback() {
798
800
  val context = requireContext()
799
801
  audioManager = audioManager ?: context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
@@ -25,8 +25,8 @@ class MyConnection(
25
25
  init {
26
26
  connectionProperties = Connection.PROPERTY_SELF_MANAGED
27
27
  connectionCapabilities = Connection.CAPABILITY_SUPPORT_HOLD or
28
- Connection.CAPABILITY_MUTE or
29
- Connection.CAPABILITY_HOLD
28
+ Connection.CAPABILITY_MUTE or
29
+ Connection.CAPABILITY_HOLD
30
30
 
31
31
  if (callType == "Video") {
32
32
  Log.d(TAG, "MyConnection for callId $callId initialized as VIDEO call.")
@@ -84,11 +84,11 @@ class MyConnection(
84
84
  }
85
85
  }
86
86
 
87
- // Only emit route change if route actually changed
87
+ // Only react to route change if it's different.
88
+ // DO NOT emit AUDIO_ROUTE_CHANGED from here, let CallEngine's
89
+ // AudioDeviceCallback handle it for consistency and to avoid duplication.
88
90
  if (lastAudioState == null || lastAudioState!!.route != state.route) {
89
- // Don't emit here - let CallEngine handle it to avoid duplication
90
- // The system audio state change will be detected by CallEngine's audio management
91
- Log.d(TAG, "System audio route changed to: ${state.route} for callId: $callId")
91
+ Log.d(TAG, "System audio route changed for callId: $callId. Telecom route: ${state.route}")
92
92
  }
93
93
 
94
94
  lastAudioState = state
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qusaieilouti99/call-manager",
3
- "version": "0.1.69",
3
+ "version": "0.1.70",
4
4
  "description": "Call manager",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",