@stream-io/video-react-native-sdk 1.21.2 → 1.22.1-alpha.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 (219) hide show
  1. package/android/gradle.properties +3 -3
  2. package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +10 -0
  3. package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativePackage.kt +2 -1
  4. package/android/src/main/java/com/streamvideo/reactnative/audio/AudioDeviceManager.kt +592 -0
  5. package/android/src/main/java/com/streamvideo/reactnative/audio/BluetoothManager.kt +755 -0
  6. package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioDeviceEndpointUtils.kt +192 -0
  7. package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioFocusUtil.kt +62 -0
  8. package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioManagerUtil.kt +159 -0
  9. package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioSetupStoreUtil.kt +41 -0
  10. package/android/src/main/java/com/streamvideo/reactnative/audio/utils/WebRtcAudioUtils.kt +250 -0
  11. package/android/src/main/java/com/streamvideo/reactnative/callmanager/StreamInCallManagerModule.kt +191 -0
  12. package/android/src/main/java/com/streamvideo/reactnative/model/AudioDeviceEndpoint.kt +136 -0
  13. package/android/src/main/java/org/webrtc/audio/WebRtcAudioTrackHelper.kt +12 -0
  14. package/dist/commonjs/components/Call/CallContent/CallContent.js +13 -9
  15. package/dist/commonjs/components/Call/CallContent/CallContent.js.map +1 -1
  16. package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js +9 -2
  17. package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
  18. package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js +3 -0
  19. package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js.map +1 -1
  20. package/dist/commonjs/components/Livestream/HostLivestream/HostLivestream.js +10 -6
  21. package/dist/commonjs/components/Livestream/HostLivestream/HostLivestream.js.map +1 -1
  22. package/dist/commonjs/components/Livestream/LivestreamControls/ViewerLivestreamControls.js +8 -4
  23. package/dist/commonjs/components/Livestream/LivestreamControls/ViewerLivestreamControls.js.map +1 -1
  24. package/dist/commonjs/components/Livestream/LivestreamLayout/LivestreamLayout.js +26 -27
  25. package/dist/commonjs/components/Livestream/LivestreamLayout/LivestreamLayout.js.map +1 -1
  26. package/dist/commonjs/components/Livestream/ViewerLivestream/ViewerLivestream.js +10 -6
  27. package/dist/commonjs/components/Livestream/ViewerLivestream/ViewerLivestream.js.map +1 -1
  28. package/dist/commonjs/hooks/useIsInPiPMode.js +3 -3
  29. package/dist/commonjs/hooks/useIsInPiPMode.js.map +1 -1
  30. package/dist/commonjs/hooks/usePermissionNotification.js +5 -5
  31. package/dist/commonjs/hooks/usePermissionNotification.js.map +1 -1
  32. package/dist/commonjs/index.js +12 -0
  33. package/dist/commonjs/index.js.map +1 -1
  34. package/dist/commonjs/modules/call-manager/CallManager.js +113 -0
  35. package/dist/commonjs/modules/call-manager/CallManager.js.map +1 -0
  36. package/dist/commonjs/modules/call-manager/PrevLibDetection.js +18 -0
  37. package/dist/commonjs/modules/call-manager/PrevLibDetection.js.map +1 -0
  38. package/dist/commonjs/modules/call-manager/index.js +24 -0
  39. package/dist/commonjs/modules/call-manager/index.js.map +1 -0
  40. package/dist/commonjs/modules/call-manager/native-module.d.js +4 -0
  41. package/dist/commonjs/modules/call-manager/native-module.d.js.map +1 -0
  42. package/dist/commonjs/modules/call-manager/types.js +2 -0
  43. package/dist/commonjs/modules/call-manager/types.js.map +1 -0
  44. package/dist/commonjs/providers/StreamCall/AppStateListener.js +5 -5
  45. package/dist/commonjs/providers/StreamCall/AppStateListener.js.map +1 -1
  46. package/dist/commonjs/theme/theme.js.map +1 -1
  47. package/dist/commonjs/utils/internal/rxSubjects.js +2 -2
  48. package/dist/commonjs/utils/internal/rxSubjects.js.map +1 -1
  49. package/dist/commonjs/version.js +1 -1
  50. package/dist/commonjs/version.js.map +1 -1
  51. package/dist/module/components/Call/CallContent/CallContent.js +14 -9
  52. package/dist/module/components/Call/CallContent/CallContent.js.map +1 -1
  53. package/dist/module/components/Call/CallContent/RTCViewPipIOS.js +9 -2
  54. package/dist/module/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
  55. package/dist/module/components/Call/CallContent/RTCViewPipNative.js +3 -0
  56. package/dist/module/components/Call/CallContent/RTCViewPipNative.js.map +1 -1
  57. package/dist/module/components/Livestream/HostLivestream/HostLivestream.js +10 -5
  58. package/dist/module/components/Livestream/HostLivestream/HostLivestream.js.map +1 -1
  59. package/dist/module/components/Livestream/LivestreamControls/ViewerLivestreamControls.js +9 -4
  60. package/dist/module/components/Livestream/LivestreamControls/ViewerLivestreamControls.js.map +1 -1
  61. package/dist/module/components/Livestream/LivestreamLayout/LivestreamLayout.js +26 -27
  62. package/dist/module/components/Livestream/LivestreamLayout/LivestreamLayout.js.map +1 -1
  63. package/dist/module/components/Livestream/ViewerLivestream/ViewerLivestream.js +10 -5
  64. package/dist/module/components/Livestream/ViewerLivestream/ViewerLivestream.js.map +1 -1
  65. package/dist/module/hooks/useIsInPiPMode.js +4 -4
  66. package/dist/module/hooks/useIsInPiPMode.js.map +1 -1
  67. package/dist/module/hooks/usePermissionNotification.js +7 -6
  68. package/dist/module/hooks/usePermissionNotification.js.map +1 -1
  69. package/dist/module/icons/Back.js +1 -1
  70. package/dist/module/icons/Back.js.map +1 -1
  71. package/dist/module/icons/CameraSwitch.js +1 -1
  72. package/dist/module/icons/CameraSwitch.js.map +1 -1
  73. package/dist/module/icons/Mic.js +1 -1
  74. package/dist/module/icons/Mic.js.map +1 -1
  75. package/dist/module/icons/MicOff.js +1 -1
  76. package/dist/module/icons/MicOff.js.map +1 -1
  77. package/dist/module/icons/Phone.js +1 -1
  78. package/dist/module/icons/Phone.js.map +1 -1
  79. package/dist/module/icons/PinVertical.js +1 -1
  80. package/dist/module/icons/PinVertical.js.map +1 -1
  81. package/dist/module/icons/Reaction.js +1 -1
  82. package/dist/module/icons/Reaction.js.map +1 -1
  83. package/dist/module/icons/Spotlight.js +1 -1
  84. package/dist/module/icons/Spotlight.js.map +1 -1
  85. package/dist/module/icons/Video.js +1 -1
  86. package/dist/module/icons/Video.js.map +1 -1
  87. package/dist/module/icons/VideoSlash.js +1 -1
  88. package/dist/module/icons/VideoSlash.js.map +1 -1
  89. package/dist/module/index.js +1 -0
  90. package/dist/module/index.js.map +1 -1
  91. package/dist/module/modules/call-manager/CallManager.js +106 -0
  92. package/dist/module/modules/call-manager/CallManager.js.map +1 -0
  93. package/dist/module/modules/call-manager/PrevLibDetection.js +12 -0
  94. package/dist/module/modules/call-manager/PrevLibDetection.js.map +1 -0
  95. package/dist/module/modules/call-manager/index.js +4 -0
  96. package/dist/module/modules/call-manager/index.js.map +1 -0
  97. package/dist/module/modules/call-manager/native-module.d.js +2 -0
  98. package/dist/module/modules/call-manager/native-module.d.js.map +1 -0
  99. package/dist/module/modules/call-manager/types.js +2 -0
  100. package/dist/module/modules/call-manager/types.js.map +1 -0
  101. package/dist/module/providers/StreamCall/AppStateListener.js +6 -6
  102. package/dist/module/providers/StreamCall/AppStateListener.js.map +1 -1
  103. package/dist/module/theme/theme.js.map +1 -1
  104. package/dist/module/utils/internal/rxSubjects.js +1 -1
  105. package/dist/module/utils/internal/rxSubjects.js.map +1 -1
  106. package/dist/module/version.js +1 -1
  107. package/dist/module/version.js.map +1 -1
  108. package/dist/typescript/components/Call/CallContent/CallContent.d.ts +3 -2
  109. package/dist/typescript/components/Call/CallContent/CallContent.d.ts.map +1 -1
  110. package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts +5 -0
  111. package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts.map +1 -1
  112. package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts +6 -0
  113. package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts.map +1 -1
  114. package/dist/typescript/components/Livestream/HostLivestream/HostLivestream.d.ts.map +1 -1
  115. package/dist/typescript/components/Livestream/LivestreamControls/ViewerLivestreamControls.d.ts.map +1 -1
  116. package/dist/typescript/components/Livestream/LivestreamLayout/LivestreamLayout.d.ts.map +1 -1
  117. package/dist/typescript/components/Livestream/ViewerLivestream/ViewerLivestream.d.ts.map +1 -1
  118. package/dist/typescript/hooks/usePermissionNotification.d.ts.map +1 -1
  119. package/dist/typescript/icons/Back.d.ts +1 -1
  120. package/dist/typescript/icons/Back.d.ts.map +1 -1
  121. package/dist/typescript/icons/BadNetwork.d.ts +1 -1
  122. package/dist/typescript/icons/BadNetwork.d.ts.map +1 -1
  123. package/dist/typescript/icons/CameraSwitch.d.ts +1 -1
  124. package/dist/typescript/icons/CameraSwitch.d.ts.map +1 -1
  125. package/dist/typescript/icons/LivestreamControls.d.ts +1 -1
  126. package/dist/typescript/icons/LivestreamControls.d.ts.map +1 -1
  127. package/dist/typescript/icons/Lock.d.ts +1 -1
  128. package/dist/typescript/icons/Lock.d.ts.map +1 -1
  129. package/dist/typescript/icons/Maximize.d.ts +1 -1
  130. package/dist/typescript/icons/Maximize.d.ts.map +1 -1
  131. package/dist/typescript/icons/Mic.d.ts +1 -1
  132. package/dist/typescript/icons/Mic.d.ts.map +1 -1
  133. package/dist/typescript/icons/MicOff.d.ts +1 -1
  134. package/dist/typescript/icons/MicOff.d.ts.map +1 -1
  135. package/dist/typescript/icons/Phone.d.ts +1 -1
  136. package/dist/typescript/icons/Phone.d.ts.map +1 -1
  137. package/dist/typescript/icons/PhoneDown.d.ts +1 -1
  138. package/dist/typescript/icons/PhoneDown.d.ts.map +1 -1
  139. package/dist/typescript/icons/PinVertical.d.ts +1 -1
  140. package/dist/typescript/icons/PinVertical.d.ts.map +1 -1
  141. package/dist/typescript/icons/Reaction.d.ts +1 -1
  142. package/dist/typescript/icons/Reaction.d.ts.map +1 -1
  143. package/dist/typescript/icons/ScreenShare.d.ts +1 -1
  144. package/dist/typescript/icons/ScreenShare.d.ts.map +1 -1
  145. package/dist/typescript/icons/ScreenShareIndicator.d.ts +1 -1
  146. package/dist/typescript/icons/ScreenShareIndicator.d.ts.map +1 -1
  147. package/dist/typescript/icons/Spotlight.d.ts +1 -1
  148. package/dist/typescript/icons/Spotlight.d.ts.map +1 -1
  149. package/dist/typescript/icons/StopScreenShare.d.ts +1 -1
  150. package/dist/typescript/icons/StopScreenShare.d.ts.map +1 -1
  151. package/dist/typescript/icons/Video.d.ts +1 -1
  152. package/dist/typescript/icons/Video.d.ts.map +1 -1
  153. package/dist/typescript/icons/VideoSlash.d.ts +1 -1
  154. package/dist/typescript/icons/VideoSlash.d.ts.map +1 -1
  155. package/dist/typescript/index.d.ts +1 -0
  156. package/dist/typescript/index.d.ts.map +1 -1
  157. package/dist/typescript/modules/call-manager/CallManager.d.ts +67 -0
  158. package/dist/typescript/modules/call-manager/CallManager.d.ts.map +1 -0
  159. package/dist/typescript/modules/call-manager/PrevLibDetection.d.ts +13 -0
  160. package/dist/typescript/modules/call-manager/PrevLibDetection.d.ts.map +1 -0
  161. package/dist/typescript/modules/call-manager/index.d.ts +4 -0
  162. package/dist/typescript/modules/call-manager/index.d.ts.map +1 -0
  163. package/dist/typescript/modules/call-manager/types.d.ts +15 -0
  164. package/dist/typescript/modules/call-manager/types.d.ts.map +1 -0
  165. package/dist/typescript/providers/StreamCall/AppStateListener.d.ts.map +1 -1
  166. package/dist/typescript/theme/theme.d.ts +1 -2
  167. package/dist/typescript/theme/theme.d.ts.map +1 -1
  168. package/dist/typescript/utils/internal/rxSubjects.d.ts +1 -1
  169. package/dist/typescript/utils/internal/rxSubjects.d.ts.map +1 -1
  170. package/dist/typescript/version.d.ts +1 -1
  171. package/dist/typescript/version.d.ts.map +1 -1
  172. package/ios/PictureInPicture/StreamPictureInPictureController.swift +5 -0
  173. package/ios/RTCViewPip.swift +15 -0
  174. package/ios/RTCViewPipManager.mm +1 -0
  175. package/ios/StreamInCallManager.m +26 -0
  176. package/ios/StreamInCallManager.swift +303 -0
  177. package/ios/StreamVideoReactNative-Bridging-Header.h +1 -0
  178. package/ios/StreamVideoReactNative.m +6 -5
  179. package/ios/StreamVideoReactNative.xcodeproj/project.xcworkspace/xcuserdata/santhoshvaiyapuri.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  180. package/ios/StreamVideoReactNative.xcodeproj/xcuserdata/santhoshvaiyapuri.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  181. package/package.json +33 -35
  182. package/src/components/Call/CallContent/CallContent.tsx +14 -10
  183. package/src/components/Call/CallContent/RTCViewPipIOS.tsx +17 -2
  184. package/src/components/Call/CallContent/RTCViewPipNative.tsx +8 -0
  185. package/src/components/Livestream/HostLivestream/HostLivestream.tsx +8 -3
  186. package/src/components/Livestream/LivestreamControls/ViewerLivestreamControls.tsx +11 -5
  187. package/src/components/Livestream/LivestreamLayout/LivestreamLayout.tsx +38 -29
  188. package/src/components/Livestream/ViewerLivestream/ViewerLivestream.tsx +8 -3
  189. package/src/hooks/useIsInPiPMode.tsx +4 -4
  190. package/src/hooks/usePermissionNotification.tsx +7 -12
  191. package/src/icons/Back.tsx +2 -2
  192. package/src/icons/BadNetwork.tsx +1 -1
  193. package/src/icons/CameraSwitch.tsx +2 -2
  194. package/src/icons/LivestreamControls.tsx +1 -1
  195. package/src/icons/Lock.tsx +1 -1
  196. package/src/icons/Maximize.tsx +1 -1
  197. package/src/icons/Mic.tsx +2 -2
  198. package/src/icons/MicOff.tsx +2 -2
  199. package/src/icons/Phone.tsx +2 -2
  200. package/src/icons/PhoneDown.tsx +1 -1
  201. package/src/icons/PinVertical.tsx +2 -2
  202. package/src/icons/Reaction.tsx +2 -2
  203. package/src/icons/ScreenShare.tsx +1 -1
  204. package/src/icons/ScreenShareIndicator.tsx +1 -1
  205. package/src/icons/Spotlight.tsx +2 -2
  206. package/src/icons/StopScreenShare.tsx +1 -1
  207. package/src/icons/Video.tsx +2 -2
  208. package/src/icons/VideoSlash.tsx +2 -2
  209. package/src/index.ts +1 -0
  210. package/src/modules/call-manager/CallManager.ts +116 -0
  211. package/src/modules/call-manager/PrevLibDetection.ts +27 -0
  212. package/src/modules/call-manager/index.ts +5 -0
  213. package/src/modules/call-manager/native-module.d.ts +80 -0
  214. package/src/modules/call-manager/types.ts +25 -0
  215. package/src/providers/StreamCall/AppStateListener.tsx +6 -9
  216. package/src/theme/theme.ts +2 -2
  217. package/src/utils/internal/rxSubjects.ts +1 -1
  218. package/src/version.ts +1 -1
  219. package/CHANGELOG.md +0 -2783
@@ -0,0 +1,250 @@
1
+ /*
2
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3
+ *
4
+ * Use of this source code is governed by a BSD-style license
5
+ * that can be found in the LICENSE file in the root of the source
6
+ * tree. An additional intellectual property rights grant can be found
7
+ * in the file PATENTS. All contributing project authors may
8
+ * be found in the AUTHORS file in the root of the source tree.
9
+ */
10
+ package com.streamvideo.reactnative.audio.utils
11
+
12
+ import android.content.Context
13
+ import android.content.pm.PackageManager
14
+ import android.media.AudioDeviceInfo
15
+ import android.media.AudioFormat
16
+ import android.media.AudioManager
17
+ import android.media.MediaRecorder
18
+ import android.os.Build
19
+ import android.util.Log
20
+ import com.facebook.react.bridge.ReactContext
21
+
22
+ /** Utilities for implementations of `AudioDeviceModule`, mostly for logging. */
23
+ object WebRtcAudioUtils {
24
+ /** Helper method for building a string of thread information. */
25
+ fun threadInfo(): String {
26
+ val current = Thread.currentThread()
27
+ return "@[name=" + current.name + ", id=" + current.id + "]"
28
+ }
29
+
30
+ /** Returns true if we're running on emulator. */
31
+ fun runningOnEmulator(): Boolean {
32
+ // Hardware type of qemu1 is goldfish and qemu2 is ranchu.
33
+ return Build.HARDWARE == "goldfish" || Build.HARDWARE == "ranchu"
34
+ }
35
+
36
+ /** Information about the current build, taken from system properties. */
37
+ private fun logDeviceInfo(tag: String) {
38
+ Log.d(
39
+ tag,
40
+ (("Android SDK: " + Build.VERSION.SDK_INT)
41
+ + (", Release: " + Build.VERSION.RELEASE)
42
+ + (", Brand: " + Build.BRAND)
43
+ + (", Device: " + Build.DEVICE)
44
+ + (", Id: " + Build.ID)
45
+ + (", Hardware: " + Build.HARDWARE)
46
+ + (", Manufacturer: " + Build.MANUFACTURER)
47
+ + (", Model: " + Build.MODEL)
48
+ + (", Product: " + Build.PRODUCT))
49
+ )
50
+ }
51
+
52
+ /**
53
+ * Logs information about the current audio state. The idea is to call this method when errors are
54
+ * detected to log under what conditions the error occurred. Hopefully it will provide clues to
55
+ * what might be the root cause.
56
+ */
57
+ fun logAudioState(tag: String, reactContext: ReactContext) {
58
+ reactContext.currentActivity?.let {
59
+ Log.d(tag, "volumeControlStream: " + streamTypeToString(it.volumeControlStream))
60
+ }
61
+ val audioManager = reactContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
62
+ logDeviceInfo(tag)
63
+ logAudioStateBasic(tag, reactContext, audioManager)
64
+ logAudioStateVolume(tag, audioManager)
65
+ logAudioDeviceInfo(tag, audioManager)
66
+ }
67
+
68
+ /** Converts AudioDeviceInfo types to local string representation. */
69
+ private fun deviceTypeToString(type: Int): String {
70
+ return when (type) {
71
+ AudioDeviceInfo.TYPE_AUX_LINE -> "TYPE_AUX_LINE"
72
+ AudioDeviceInfo.TYPE_BLE_BROADCAST -> "TYPE_BLE_BROADCAST"
73
+ AudioDeviceInfo.TYPE_BLE_HEADSET -> "TYPE_BLE_HEADSET"
74
+ AudioDeviceInfo.TYPE_BLE_SPEAKER -> "TYPE_BLE_SPEAKER"
75
+ AudioDeviceInfo.TYPE_BLUETOOTH_A2DP -> "TYPE_BLUETOOTH_A2DP"
76
+ AudioDeviceInfo.TYPE_BLUETOOTH_SCO -> "TYPE_BLUETOOTH_SCO"
77
+ AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> "TYPE_BUILTIN_EARPIECE"
78
+ AudioDeviceInfo.TYPE_BUILTIN_MIC -> "TYPE_BUILTIN_MIC"
79
+ AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> "TYPE_BUILTIN_SPEAKER"
80
+ AudioDeviceInfo.TYPE_BUILTIN_SPEAKER_SAFE -> "TYPE_BUILTIN_SPEAKER_SAFE"
81
+ AudioDeviceInfo.TYPE_BUS -> "TYPE_BUS"
82
+ AudioDeviceInfo.TYPE_DOCK -> "TYPE_DOCK"
83
+ AudioDeviceInfo.TYPE_DOCK_ANALOG -> "TYPE_DOCK_ANALOG"
84
+ AudioDeviceInfo.TYPE_FM -> "TYPE_FM"
85
+ AudioDeviceInfo.TYPE_FM_TUNER -> "TYPE_FM_TUNER"
86
+ AudioDeviceInfo.TYPE_HDMI -> "TYPE_HDMI"
87
+ AudioDeviceInfo.TYPE_HDMI_ARC -> "TYPE_HDMI_ARC"
88
+ AudioDeviceInfo.TYPE_HDMI_EARC -> "TYPE_HDMI_EARC"
89
+ AudioDeviceInfo.TYPE_HEARING_AID -> "TYPE_HEARING_AID"
90
+ AudioDeviceInfo.TYPE_IP -> "TYPE_IP"
91
+ AudioDeviceInfo.TYPE_LINE_ANALOG -> "TYPE_LINE_ANALOG"
92
+ AudioDeviceInfo.TYPE_LINE_DIGITAL -> "TYPE_LINE_DIGITAL"
93
+ AudioDeviceInfo.TYPE_REMOTE_SUBMIX -> "TYPE_REMOTE_SUBMIX"
94
+ AudioDeviceInfo.TYPE_TELEPHONY -> "TYPE_TELEPHONY"
95
+ AudioDeviceInfo.TYPE_TV_TUNER -> "TYPE_TV_TUNER"
96
+ AudioDeviceInfo.TYPE_UNKNOWN -> "TYPE_UNKNOWN"
97
+ AudioDeviceInfo.TYPE_USB_ACCESSORY -> "TYPE_USB_ACCESSORY"
98
+ AudioDeviceInfo.TYPE_USB_DEVICE -> "TYPE_USB_DEVICE"
99
+ AudioDeviceInfo.TYPE_USB_HEADSET -> "TYPE_USB_HEADSET"
100
+ AudioDeviceInfo.TYPE_WIRED_HEADPHONES -> "TYPE_WIRED_HEADPHONES"
101
+ AudioDeviceInfo.TYPE_WIRED_HEADSET -> "TYPE_WIRED_HEADSET"
102
+ else -> "TYPE_UNKNOWN($type)"
103
+ }
104
+ }
105
+
106
+ fun audioSourceToString(source: Int): String {
107
+ return when (source) {
108
+ MediaRecorder.AudioSource.DEFAULT -> "DEFAULT"
109
+ MediaRecorder.AudioSource.MIC -> "MIC"
110
+ MediaRecorder.AudioSource.VOICE_UPLINK -> "VOICE_UPLINK"
111
+ MediaRecorder.AudioSource.VOICE_DOWNLINK -> "VOICE_DOWNLINK"
112
+ MediaRecorder.AudioSource.VOICE_CALL -> "VOICE_CALL"
113
+ MediaRecorder.AudioSource.CAMCORDER -> "CAMCORDER"
114
+ MediaRecorder.AudioSource.VOICE_RECOGNITION -> "VOICE_RECOGNITION"
115
+ MediaRecorder.AudioSource.VOICE_COMMUNICATION -> "VOICE_COMMUNICATION"
116
+ MediaRecorder.AudioSource.UNPROCESSED -> "UNPROCESSED"
117
+ MediaRecorder.AudioSource.VOICE_PERFORMANCE -> "VOICE_PERFORMANCE"
118
+ else -> "INVALID"
119
+ }
120
+ }
121
+
122
+ fun channelMaskToString(mask: Int): String {
123
+ // For input or AudioRecord, the mask should be AudioFormat#CHANNEL_IN_MONO or
124
+ // AudioFormat#CHANNEL_IN_STEREO. AudioFormat#CHANNEL_IN_MONO is guaranteed to work on all
125
+ // devices.
126
+ return when (mask) {
127
+ AudioFormat.CHANNEL_IN_STEREO -> "IN_STEREO"
128
+ AudioFormat.CHANNEL_IN_MONO -> "IN_MONO"
129
+ else -> "INVALID"
130
+ }
131
+ }
132
+
133
+ fun audioEncodingToString(enc: Int): String {
134
+ return when (enc) {
135
+ AudioFormat.ENCODING_INVALID -> "INVALID"
136
+ AudioFormat.ENCODING_PCM_16BIT -> "PCM_16BIT"
137
+ AudioFormat.ENCODING_PCM_8BIT -> "PCM_8BIT"
138
+ AudioFormat.ENCODING_PCM_FLOAT -> "PCM_FLOAT"
139
+ AudioFormat.ENCODING_AC3 -> "AC3"
140
+ AudioFormat.ENCODING_E_AC3 -> "AC3"
141
+ AudioFormat.ENCODING_DTS -> "DTS"
142
+ AudioFormat.ENCODING_DTS_HD -> "DTS_HD"
143
+ AudioFormat.ENCODING_MP3 -> "MP3"
144
+ else -> "Invalid encoding: $enc"
145
+ }
146
+ }
147
+
148
+ /** Reports basic audio statistics. */
149
+ private fun logAudioStateBasic(tag: String, context: Context, audioManager: AudioManager) {
150
+ Log.d(
151
+ tag,
152
+ ("Audio State: "
153
+ + ("audio mode: " + modeToString(audioManager.mode))
154
+ + (", has mic: " + hasMicrophone(context))
155
+ + (", mic muted: " + audioManager.isMicrophoneMute)
156
+ + (", music active: " + audioManager.isMusicActive)
157
+ + (", speakerphone: " + audioManager.isSpeakerphoneOn)
158
+ + (", BT SCO: " + audioManager.isBluetoothScoOn))
159
+ )
160
+ }
161
+
162
+ /** Adds volume information for all possible stream types. */
163
+ private fun logAudioStateVolume(tag: String, audioManager: AudioManager) {
164
+ val streams = intArrayOf(
165
+ AudioManager.STREAM_VOICE_CALL,
166
+ AudioManager.STREAM_MUSIC,
167
+ AudioManager.STREAM_RING,
168
+ AudioManager.STREAM_ALARM,
169
+ AudioManager.STREAM_NOTIFICATION,
170
+ AudioManager.STREAM_SYSTEM
171
+ )
172
+ Log.d(tag, "Audio State: ")
173
+ // Some devices may not have volume controls and might use a fixed volume.
174
+ val fixedVolume = audioManager.isVolumeFixed
175
+ Log.d(tag, " fixed volume=$fixedVolume")
176
+ if (!fixedVolume) {
177
+ for (stream in streams) {
178
+ val info = StringBuilder()
179
+ info.append(" " + streamTypeToString(stream) + ": ")
180
+ info.append("volume=").append(audioManager.getStreamVolume(stream))
181
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
182
+ info.append(", min=").append(audioManager.getStreamMinVolume(stream))
183
+ }
184
+ info.append(", max=").append(audioManager.getStreamMaxVolume(stream))
185
+ info.append(", muted=").append(audioManager.isStreamMute(stream))
186
+ Log.d(tag, info.toString())
187
+ }
188
+ }
189
+ }
190
+
191
+ private fun logAudioDeviceInfo(tag: String, audioManager: AudioManager) {
192
+ val inputDevices = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)
193
+ val outputDevices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)
194
+ val devices = inputDevices + outputDevices
195
+ if (devices.isEmpty()) {
196
+ return
197
+ }
198
+ Log.d(tag, "Audio Devices: ")
199
+ for (device in devices) {
200
+ val info = StringBuilder()
201
+ info.append(" ").append(deviceTypeToString(device.type))
202
+ info.append(if (device.isSource) "(in): " else "(out): ")
203
+ // An empty array indicates that the device supports arbitrary channel counts.
204
+ if (device.channelCounts.size > 0) {
205
+ info.append("channels=").append(device.channelCounts.contentToString())
206
+ info.append(", ")
207
+ }
208
+ if (device.encodings.size > 0) {
209
+ // Examples: ENCODING_PCM_16BIT = 2, ENCODING_PCM_FLOAT = 4.
210
+ info.append("encodings=").append(device.encodings.contentToString())
211
+ info.append(", ")
212
+ }
213
+ if (device.sampleRates.size > 0) {
214
+ info.append("sample rates=").append(device.sampleRates.contentToString())
215
+ info.append(", ")
216
+ }
217
+ info.append("id=").append(device.id)
218
+ Log.d(tag, info.toString())
219
+ }
220
+ }
221
+
222
+ /** Converts media.AudioManager modes into local string representation. */
223
+ fun modeToString(mode: Int): String {
224
+ return when (mode) {
225
+ AudioManager.MODE_IN_CALL -> "MODE_IN_CALL"
226
+ AudioManager.MODE_IN_COMMUNICATION -> "MODE_IN_COMMUNICATION"
227
+ AudioManager.MODE_NORMAL -> "MODE_NORMAL"
228
+ AudioManager.MODE_RINGTONE -> "MODE_RINGTONE"
229
+ else -> "MODE_INVALID"
230
+ }
231
+ }
232
+
233
+ private fun streamTypeToString(stream: Int): String {
234
+ return when (stream) {
235
+ AudioManager.STREAM_VOICE_CALL -> "STREAM_VOICE_CALL"
236
+ AudioManager.STREAM_MUSIC -> "STREAM_MUSIC"
237
+ AudioManager.STREAM_RING -> "STREAM_RING"
238
+ AudioManager.STREAM_ALARM -> "STREAM_ALARM"
239
+ AudioManager.STREAM_NOTIFICATION -> "STREAM_NOTIFICATION"
240
+ AudioManager.STREAM_SYSTEM -> "STREAM_SYSTEM"
241
+ else -> "STREAM_INVALID"
242
+ }
243
+ }
244
+
245
+ /** Returns true if the device can record audio via a microphone. */
246
+ private fun hasMicrophone(context: Context): Boolean {
247
+ return context.packageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE)
248
+ }
249
+
250
+ }
@@ -0,0 +1,191 @@
1
+ package com.streamvideo.reactnative.callmanager
2
+
3
+ import android.util.Log
4
+ import android.view.WindowManager
5
+ import com.facebook.react.bridge.LifecycleEventListener
6
+ import com.facebook.react.bridge.ReactApplicationContext
7
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
8
+ import com.facebook.react.bridge.ReactMethod
9
+ import com.facebook.react.bridge.UiThreadUtil
10
+ import com.streamvideo.reactnative.audio.AudioDeviceManager
11
+ import com.streamvideo.reactnative.audio.utils.CallAudioRole
12
+ import com.streamvideo.reactnative.audio.utils.WebRtcAudioUtils
13
+ import com.streamvideo.reactnative.model.AudioDeviceEndpoint
14
+ import java.util.Locale
15
+
16
+
17
+ class StreamInCallManagerModule(reactContext: ReactApplicationContext) :
18
+ ReactContextBaseJavaModule(reactContext), LifecycleEventListener {
19
+
20
+ private var audioManagerActivated = false
21
+
22
+ private val mAudioDeviceManager = AudioDeviceManager(reactContext)
23
+
24
+
25
+ override fun getName(): String {
26
+ return TAG
27
+ }
28
+
29
+ init {
30
+ reactContext.addLifecycleEventListener(this)
31
+ }
32
+
33
+ // This method was removed upstream in react-native 0.74+, replaced with invalidate
34
+ // We will leave this stub here for older react-native versions compatibility
35
+ // ...but it will just delegate to the new invalidate method
36
+ @Deprecated("Deprecated in Java", ReplaceWith("invalidate()"))
37
+ @Suppress("removal")
38
+ override fun onCatalystInstanceDestroy() {
39
+ invalidate()
40
+ }
41
+
42
+ override fun invalidate() {
43
+ mAudioDeviceManager.close()
44
+ super.invalidate()
45
+ }
46
+
47
+ @ReactMethod
48
+ fun setAudioRole(audioRole: String) {
49
+ AudioDeviceManager.runInAudioThread {
50
+ if (audioManagerActivated) {
51
+ Log.e(TAG, "setAudioRole(): AudioManager is already activated and so Audio Role cannot be changed, current audio role is ${mAudioDeviceManager.callAudioRole}")
52
+ return@runInAudioThread
53
+ }
54
+ val role = audioRole.lowercase(Locale.getDefault())
55
+ Log.d(TAG, "setAudioRole(): $audioRole $role")
56
+ if (role == "listener") {
57
+ mAudioDeviceManager.callAudioRole = CallAudioRole.Listener
58
+ } else {
59
+ mAudioDeviceManager.callAudioRole = CallAudioRole.Communicator
60
+ }
61
+ }
62
+ }
63
+
64
+ @ReactMethod
65
+ fun setDefaultAudioDeviceEndpointType(endpointDeviceTypeName: String) {
66
+ AudioDeviceManager.runInAudioThread {
67
+ if (audioManagerActivated) {
68
+ Log.e(TAG, "setAudioRole(): AudioManager is already activated and so default audio device cannot be changed, current audio default device is ${mAudioDeviceManager.defaultAudioDevice}")
69
+ return@runInAudioThread
70
+ }
71
+ val endpointType = endpointDeviceTypeName.lowercase(Locale.getDefault())
72
+ Log.d(TAG, "runInAudioThread(): $endpointDeviceTypeName $endpointType")
73
+ if (endpointType == "earpiece") {
74
+ mAudioDeviceManager.defaultAudioDevice = AudioDeviceEndpoint.TYPE_EARPIECE
75
+ } else {
76
+ mAudioDeviceManager.defaultAudioDevice = AudioDeviceEndpoint.TYPE_SPEAKER
77
+ }
78
+ }
79
+ }
80
+
81
+ @ReactMethod
82
+ fun start() {
83
+ AudioDeviceManager.runInAudioThread {
84
+ if (!audioManagerActivated) {
85
+ reactApplicationContext.currentActivity?.let {
86
+ Log.d(TAG, "start() mAudioDeviceManager")
87
+ mAudioDeviceManager.start(it)
88
+ setKeepScreenOn(true)
89
+ audioManagerActivated = true
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ @ReactMethod
96
+ fun stop() {
97
+ AudioDeviceManager.runInAudioThread {
98
+ if (audioManagerActivated) {
99
+ Log.d(TAG, "stop() mAudioDeviceManager")
100
+ mAudioDeviceManager.stop()
101
+ setMicrophoneMute(false)
102
+ setKeepScreenOn(false)
103
+ audioManagerActivated = false
104
+ }
105
+ }
106
+ }
107
+
108
+ private fun setKeepScreenOn(enable: Boolean) {
109
+ Log.d(TAG, "setKeepScreenOn() $enable")
110
+ UiThreadUtil.runOnUiThread {
111
+ reactApplicationContext.currentActivity?.let {
112
+ val window = it.window
113
+ if (enable) {
114
+ window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
115
+ } else {
116
+ window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+ @Suppress("unused")
123
+ @ReactMethod
124
+ fun setForceSpeakerphoneOn(enable: Boolean) {
125
+ if (mAudioDeviceManager.callAudioRole !== CallAudioRole.Communicator) {
126
+ Log.e(TAG, "setForceSpeakerphoneOn() is not supported when audio role is not Communicator")
127
+ return
128
+ }
129
+ mAudioDeviceManager.setSpeakerphoneOn(enable)
130
+ }
131
+
132
+ @ReactMethod
133
+ fun setMicrophoneMute(enable: Boolean) {
134
+ mAudioDeviceManager.setMicrophoneMute(enable)
135
+ }
136
+
137
+ @ReactMethod
138
+ fun logAudioState() {
139
+ WebRtcAudioUtils.logAudioState(
140
+ TAG,
141
+ reactApplicationContext,
142
+ )
143
+ }
144
+
145
+ @Suppress("unused")
146
+ @ReactMethod
147
+ fun chooseAudioDeviceEndpoint(endpointDeviceName: String) {
148
+ if (mAudioDeviceManager.callAudioRole !== CallAudioRole.Communicator) {
149
+ Log.e(TAG, "chooseAudioDeviceEndpoint() is not supported when audio role is not Communicator")
150
+ return
151
+ }
152
+ mAudioDeviceManager.switchDeviceFromDeviceName(
153
+ endpointDeviceName
154
+ )
155
+ }
156
+
157
+ @ReactMethod
158
+ fun muteAudioOutput() {
159
+ mAudioDeviceManager.muteAudioOutput()
160
+ }
161
+
162
+ @ReactMethod
163
+ fun unmuteAudioOutput() {
164
+ mAudioDeviceManager.unmuteAudioOutput()
165
+ }
166
+
167
+ override fun onHostResume() {
168
+ }
169
+
170
+ override fun onHostPause() {
171
+ }
172
+
173
+ override fun onHostDestroy() {
174
+ stop()
175
+ }
176
+
177
+ @ReactMethod
178
+ fun addListener(eventName: String?) {
179
+ // Keep: Required for RN built in Event Emitter Calls.
180
+ }
181
+
182
+ @ReactMethod
183
+ fun removeListeners(count: Int?) {
184
+ // Keep: Required for RN built in Event Emitter Calls.
185
+ }
186
+
187
+ companion object {
188
+ const val TAG = "StreamInCallManager"
189
+ }
190
+ }
191
+
@@ -0,0 +1,136 @@
1
+ /*
2
+ * Copyright 2023 The Android Open Source Project
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ package com.streamvideo.reactnative.model
18
+
19
+ import android.media.AudioDeviceInfo
20
+ import androidx.annotation.IntDef
21
+ import androidx.annotation.RestrictTo
22
+ import com.streamvideo.reactnative.audio.utils.AudioDeviceEndpointUtils
23
+ import java.util.Objects
24
+
25
+ /**
26
+ * Represents a single audio device endpoint.
27
+ * @param name The name of the device. Bluetooth devices have their proper names, everything else their endpoint name. See [AudioDeviceEndpointUtils.remapAudioDeviceNameToEndpointDeviceName]
28
+ * @param type The type of endpoint.
29
+ * @param deviceInfo The [AudioDeviceInfo] associated with the endpoint.
30
+ */
31
+ public class AudioDeviceEndpoint(
32
+ public val name: String,
33
+ @EndpointType public val type: Int,
34
+ public val deviceInfo: AudioDeviceInfo,
35
+ ) : Comparable<AudioDeviceEndpoint> {
36
+
37
+ val deviceId = deviceInfo.id
38
+
39
+ override fun toString(): String {
40
+ return "CallEndpoint(" +
41
+ "name=[$name]," +
42
+ "type=[${
43
+ AudioDeviceEndpointUtils.endpointTypeToString(type)}]," +
44
+ "deviceId=[${deviceId}])"
45
+ }
46
+
47
+ /**
48
+ * Compares this [AudioDeviceEndpoint] to the other [AudioDeviceEndpoint] for order. Returns a
49
+ * positive number if this type rank is greater than the other value. Returns a negative number
50
+ * if this type rank is less than the other value. Sort the CallEndpoint by type. Ranking them
51
+ * by:
52
+ * 1. TYPE_WIRED_HEADSET
53
+ * 2. TYPE_BLUETOOTH
54
+ * 3. TYPE_SPEAKER
55
+ * 4. TYPE_EARPIECE
56
+ * 5. TYPE_UNKNOWN If two endpoints have the same type, the name is compared to determine the
57
+ * value.
58
+ */
59
+ override fun compareTo(other: AudioDeviceEndpoint): Int {
60
+ // sort by type
61
+ val res = this.getTypeRank().compareTo(other.getTypeRank())
62
+ if (res != 0) {
63
+ return res
64
+ }
65
+ // break ties using alphabetic order
66
+ return this.name.toString().compareTo(other.name.toString())
67
+ }
68
+
69
+ override fun equals(other: Any?): Boolean {
70
+ return other is AudioDeviceEndpoint &&
71
+ name == other.name &&
72
+ type == other.type && deviceId == other.deviceId
73
+ }
74
+
75
+ override fun hashCode(): Int {
76
+ return Objects.hash(name, type, deviceId)
77
+ }
78
+
79
+ public companion object {
80
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
81
+ @Retention(AnnotationRetention.SOURCE)
82
+ @IntDef(
83
+ TYPE_UNKNOWN,
84
+ TYPE_EARPIECE,
85
+ TYPE_BLUETOOTH,
86
+ TYPE_WIRED_HEADSET,
87
+ TYPE_SPEAKER,
88
+ )
89
+ @Target(AnnotationTarget.TYPE, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
90
+ public annotation class EndpointType
91
+
92
+ /** Indicates that the type of endpoint through which call media flows is unknown type. */
93
+ public const val TYPE_UNKNOWN: Int = -1
94
+
95
+ /** Indicates that the type of endpoint through which call media flows is an earpiece. */
96
+ public const val TYPE_EARPIECE: Int = 1
97
+
98
+ /** Indicates that the type of endpoint through which call media flows is a Bluetooth. */
99
+ public const val TYPE_BLUETOOTH: Int = 2
100
+
101
+ /**
102
+ * Indicates that the type of endpoint through which call media flows is a wired headset.
103
+ */
104
+ public const val TYPE_WIRED_HEADSET: Int = 3
105
+
106
+ /** Indicates that the type of endpoint through which call media flows is a speakerphone. */
107
+ public const val TYPE_SPEAKER: Int = 4
108
+
109
+ }
110
+
111
+ internal fun isBluetoothType(): Boolean {
112
+ return type == TYPE_BLUETOOTH
113
+ }
114
+
115
+ internal fun isSpeakerType(): Boolean {
116
+ return type == TYPE_SPEAKER
117
+ }
118
+
119
+ internal fun isWiredHeadsetType(): Boolean {
120
+ return type == TYPE_WIRED_HEADSET
121
+ }
122
+
123
+ internal fun isEarpieceType(): Boolean {
124
+ return type == TYPE_EARPIECE
125
+ }
126
+
127
+ private fun getTypeRank(): Int {
128
+ return when (this.type) {
129
+ TYPE_WIRED_HEADSET -> return 0
130
+ TYPE_BLUETOOTH -> return 1
131
+ TYPE_SPEAKER -> return 2
132
+ TYPE_EARPIECE -> return 3
133
+ else -> 4
134
+ }
135
+ }
136
+ }
@@ -0,0 +1,12 @@
1
+ package org.webrtc.audio
2
+
3
+ import android.media.AudioAttributes
4
+
5
+ object WebRtcAudioTrackHelper {
6
+ fun setAudioOutputAttributes(
7
+ adm: JavaAudioDeviceModule,
8
+ audioAttributes: AudioAttributes,
9
+ ) {
10
+ adm.audioOutput.audioAttributes = audioAttributes
11
+ }
12
+ }
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.CallContent = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
- var _reactNativeIncallManager = _interopRequireDefault(require("react-native-incall-manager"));
10
9
  var _CallLayout = require("../CallLayout");
11
10
  var _CallControls = require("../CallControls");
12
11
  var _videoReactBindings = require("@stream-io/video-react-bindings");
@@ -18,7 +17,7 @@ var _contexts = require("../../../contexts");
18
17
  var _hooks2 = require("../../../hooks");
19
18
  var _ScreenShareOverlay = require("../../utility/ScreenShareOverlay");
20
19
  var _RTCViewPipIOS = require("./RTCViewPipIOS");
21
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
20
+ var _PrevLibDetection = require("../../../modules/call-manager/PrevLibDetection");
22
21
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
23
22
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
24
23
  const CallContent = ({
@@ -36,9 +35,9 @@ const CallContent = ({
36
35
  layout = 'grid',
37
36
  landscape = false,
38
37
  supportedReactions,
38
+ initialInCallManagerAudioMode = 'video',
39
39
  iOSPiPIncludeLocalParticipantVideo,
40
- disablePictureInPicture,
41
- initialInCallManagerAudioMode = 'video'
40
+ disablePictureInPicture
42
41
  }) => {
43
42
  const [showRemoteParticipantInFloatingView, setShowRemoteParticipantInFloatingView] = (0, _react.useState)(false);
44
43
  const styles = useStyles();
@@ -54,7 +53,6 @@ const CallContent = ({
54
53
  useLocalParticipant
55
54
  } = (0, _videoReactBindings.useCallStateHooks)();
56
55
  (0, _hooks2.useAutoEnterPiPEffect)(disablePictureInPicture);
57
- const incallManagerModeRef = (0, _react.useRef)(initialInCallManagerAudioMode);
58
56
  const _remoteParticipants = useRemoteParticipants();
59
57
  const remoteParticipants = (0, _hooks.useDebouncedValue)(_remoteParticipants, 300); // we debounce the remote participants to avoid unnecessary rerenders that happen when participant tracks are all subscribed simultaneously
60
58
  const localParticipant = useLocalParticipant();
@@ -85,11 +83,17 @@ const CallContent = ({
85
83
  /**
86
84
  * This hook is used to handle IncallManager specs of the application.
87
85
  */
86
+ const incallManagerModeRef = (0, _react.useRef)(initialInCallManagerAudioMode);
88
87
  (0, _react.useEffect)(() => {
89
- _reactNativeIncallManager.default.start({
90
- media: incallManagerModeRef.current
91
- });
92
- return () => _reactNativeIncallManager.default.stop();
88
+ const prevInCallManager = (0, _PrevLibDetection.getRNInCallManagerLibNoThrow)();
89
+ if (prevInCallManager) {
90
+ prevInCallManager.start({
91
+ media: incallManagerModeRef.current
92
+ });
93
+ return () => {
94
+ prevInCallManager.stop();
95
+ };
96
+ }
93
97
  }, []);
94
98
  const handleFloatingViewParticipantSwitch = () => {
95
99
  if (remoteParticipants.length !== 1) {