Committed by
GitHub
Fix memory leaks (#306)
* Fix memory leaks * Fix data channel leaking RTCEngine * Add room to leak canary in sample app * remove leakcanary watching of room
正在显示
6 个修改的文件
包含
22 行增加
和
16 行删除
| @@ -91,6 +91,7 @@ object RTCModule { | @@ -91,6 +91,7 @@ object RTCModule { | ||
| 91 | moduleCustomizer: ((builder: JavaAudioDeviceModule.Builder) -> Unit)?, | 91 | moduleCustomizer: ((builder: JavaAudioDeviceModule.Builder) -> Unit)?, |
| 92 | audioOutputAttributes: AudioAttributes, | 92 | audioOutputAttributes: AudioAttributes, |
| 93 | appContext: Context, | 93 | appContext: Context, |
| 94 | + closeableManager: CloseableManager, | ||
| 94 | ): AudioDeviceModule { | 95 | ): AudioDeviceModule { |
| 95 | if (audioDeviceModuleOverride != null) { | 96 | if (audioDeviceModuleOverride != null) { |
| 96 | return audioDeviceModuleOverride | 97 | return audioDeviceModuleOverride |
| @@ -167,12 +168,13 @@ object RTCModule { | @@ -167,12 +168,13 @@ object RTCModule { | ||
| 167 | 168 | ||
| 168 | moduleCustomizer?.invoke(builder) | 169 | moduleCustomizer?.invoke(builder) |
| 169 | return builder.createAudioDeviceModule() | 170 | return builder.createAudioDeviceModule() |
| 171 | + .apply { closeableManager.registerClosable { release() } } | ||
| 170 | } | 172 | } |
| 171 | 173 | ||
| 172 | @Provides | 174 | @Provides |
| 173 | @Singleton | 175 | @Singleton |
| 174 | fun eglBase( | 176 | fun eglBase( |
| 175 | - @Singleton memoryManager: CloseableManager, | 177 | + memoryManager: CloseableManager, |
| 176 | ): EglBase { | 178 | ): EglBase { |
| 177 | val eglBase = EglBase.create() | 179 | val eglBase = EglBase.create() |
| 178 | memoryManager.registerResource(eglBase) { eglBase.release() } | 180 | memoryManager.registerResource(eglBase) { eglBase.release() } |
| @@ -234,12 +236,14 @@ object RTCModule { | @@ -234,12 +236,14 @@ object RTCModule { | ||
| 234 | audioDeviceModule: AudioDeviceModule, | 236 | audioDeviceModule: AudioDeviceModule, |
| 235 | videoEncoderFactory: VideoEncoderFactory, | 237 | videoEncoderFactory: VideoEncoderFactory, |
| 236 | videoDecoderFactory: VideoDecoderFactory, | 238 | videoDecoderFactory: VideoDecoderFactory, |
| 239 | + memoryManager: CloseableManager, | ||
| 237 | ): PeerConnectionFactory { | 240 | ): PeerConnectionFactory { |
| 238 | return PeerConnectionFactory.builder() | 241 | return PeerConnectionFactory.builder() |
| 239 | .setAudioDeviceModule(audioDeviceModule) | 242 | .setAudioDeviceModule(audioDeviceModule) |
| 240 | .setVideoEncoderFactory(videoEncoderFactory) | 243 | .setVideoEncoderFactory(videoEncoderFactory) |
| 241 | .setVideoDecoderFactory(videoDecoderFactory) | 244 | .setVideoDecoderFactory(videoDecoderFactory) |
| 242 | .createPeerConnectionFactory() | 245 | .createPeerConnectionFactory() |
| 246 | + .apply { memoryManager.registerClosable { dispose() } } | ||
| 243 | } | 247 | } |
| 244 | 248 | ||
| 245 | @Provides | 249 | @Provides |
| @@ -25,7 +25,6 @@ import io.livekit.android.stats.AndroidNetworkInfo | @@ -25,7 +25,6 @@ import io.livekit.android.stats.AndroidNetworkInfo | ||
| 25 | import io.livekit.android.stats.NetworkInfo | 25 | import io.livekit.android.stats.NetworkInfo |
| 26 | import okhttp3.OkHttpClient | 26 | import okhttp3.OkHttpClient |
| 27 | import okhttp3.WebSocket | 27 | import okhttp3.WebSocket |
| 28 | -import java.util.concurrent.TimeUnit | ||
| 29 | import javax.inject.Named | 28 | import javax.inject.Named |
| 30 | import javax.inject.Singleton | 29 | import javax.inject.Singleton |
| 31 | 30 | ||
| @@ -41,10 +40,6 @@ object WebModule { | @@ -41,10 +40,6 @@ object WebModule { | ||
| 41 | @Nullable | 40 | @Nullable |
| 42 | okHttpClientOverride: OkHttpClient?, | 41 | okHttpClientOverride: OkHttpClient?, |
| 43 | ): OkHttpClient { | 42 | ): OkHttpClient { |
| 44 | - OkHttpClient.Builder() | ||
| 45 | - .pingInterval(20, TimeUnit.SECONDS) | ||
| 46 | - .build() | ||
| 47 | - | ||
| 48 | return okHttpClientOverride ?: OkHttpClient() | 43 | return okHttpClientOverride ?: OkHttpClient() |
| 49 | } | 44 | } |
| 50 | 45 |
| @@ -149,7 +149,7 @@ constructor( | @@ -149,7 +149,7 @@ constructor( | ||
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | fun close() { | 151 | fun close() { |
| 152 | - peerConnection.close() | 152 | + peerConnection.dispose() |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | fun updateRTCConfig(config: RTCConfiguration) { | 155 | fun updateRTCConfig(config: RTCConfiguration) { |
| @@ -314,13 +314,19 @@ internal constructor( | @@ -314,13 +314,19 @@ internal constructor( | ||
| 314 | _publisher = null | 314 | _publisher = null |
| 315 | _subscriber?.close() | 315 | _subscriber?.close() |
| 316 | _subscriber = null | 316 | _subscriber = null |
| 317 | - reliableDataChannel?.close() | 317 | + |
| 318 | + fun DataChannel?.completeDispose() { | ||
| 319 | + this?.unregisterObserver() | ||
| 320 | + this?.close() | ||
| 321 | + this?.dispose() | ||
| 322 | + } | ||
| 323 | + reliableDataChannel?.completeDispose() | ||
| 318 | reliableDataChannel = null | 324 | reliableDataChannel = null |
| 319 | - reliableDataChannelSub?.close() | 325 | + reliableDataChannelSub?.completeDispose() |
| 320 | reliableDataChannelSub = null | 326 | reliableDataChannelSub = null |
| 321 | - lossyDataChannel?.close() | 327 | + lossyDataChannel?.completeDispose() |
| 322 | lossyDataChannel = null | 328 | lossyDataChannel = null |
| 323 | - lossyDataChannelSub?.close() | 329 | + lossyDataChannelSub?.completeDispose() |
| 324 | lossyDataChannelSub = null | 330 | lossyDataChannelSub = null |
| 325 | isSubscriberPrimary = false | 331 | isSubscriberPrimary = false |
| 326 | client.close(reason = reason) | 332 | client.close(reason = reason) |
| @@ -49,7 +49,6 @@ import livekit.LivekitModels | @@ -49,7 +49,6 @@ import livekit.LivekitModels | ||
| 49 | import livekit.LivekitRtc | 49 | import livekit.LivekitRtc |
| 50 | import org.webrtc.* | 50 | import org.webrtc.* |
| 51 | import javax.inject.Named | 51 | import javax.inject.Named |
| 52 | -import javax.inject.Singleton | ||
| 53 | 52 | ||
| 54 | class Room | 53 | class Room |
| 55 | @AssistedInject | 54 | @AssistedInject |
| @@ -64,7 +63,6 @@ constructor( | @@ -64,7 +63,6 @@ constructor( | ||
| 64 | @Named(InjectionNames.DISPATCHER_IO) | 63 | @Named(InjectionNames.DISPATCHER_IO) |
| 65 | private val ioDispatcher: CoroutineDispatcher, | 64 | private val ioDispatcher: CoroutineDispatcher, |
| 66 | val audioHandler: AudioHandler, | 65 | val audioHandler: AudioHandler, |
| 67 | - @Singleton | ||
| 68 | private val closeableManager: CloseableManager, | 66 | private val closeableManager: CloseableManager, |
| 69 | private val e2EEManagerFactory: E2EEManager.Factory, | 67 | private val e2EEManagerFactory: E2EEManager.Factory, |
| 70 | ) : RTCEngine.Listener, ParticipantListener { | 68 | ) : RTCEngine.Listener, ParticipantListener { |
| @@ -127,7 +127,7 @@ class CallViewModel( | @@ -127,7 +127,7 @@ class CallViewModel( | ||
| 127 | handlePrimarySpeaker( | 127 | handlePrimarySpeaker( |
| 128 | participantsList, | 128 | participantsList, |
| 129 | speakers, | 129 | speakers, |
| 130 | - room | 130 | + room, |
| 131 | ) | 131 | ) |
| 132 | } | 132 | } |
| 133 | } | 133 | } |
| @@ -142,6 +142,7 @@ class CallViewModel( | @@ -142,6 +142,7 @@ class CallViewModel( | ||
| 142 | messagesReceived++ | 142 | messagesReceived++ |
| 143 | Timber.e { "message received from $identity, count $messagesReceived" } | 143 | Timber.e { "message received from $identity, count $messagesReceived" } |
| 144 | } | 144 | } |
| 145 | + | ||
| 145 | else -> { | 146 | else -> { |
| 146 | Timber.e { "Room event: $it" } | 147 | Timber.e { "Room event: $it" } |
| 147 | } | 148 | } |
| @@ -182,7 +183,7 @@ class CallViewModel( | @@ -182,7 +183,7 @@ class CallViewModel( | ||
| 182 | room.connect( | 183 | room.connect( |
| 183 | url = url, | 184 | url = url, |
| 184 | token = token, | 185 | token = token, |
| 185 | - roomOptions = RoomOptions(e2eeOptions = getE2EEOptions()) | 186 | + roomOptions = RoomOptions(e2eeOptions = getE2EEOptions()), |
| 186 | ) | 187 | ) |
| 187 | 188 | ||
| 188 | // Create and publish audio/video tracks | 189 | // Create and publish audio/video tracks |
| @@ -246,7 +247,7 @@ class CallViewModel( | @@ -246,7 +247,7 @@ class CallViewModel( | ||
| 246 | val screencastTrack = | 247 | val screencastTrack = |
| 247 | localParticipant.createScreencastTrack(mediaProjectionPermissionResultData = mediaProjectionPermissionResultData) | 248 | localParticipant.createScreencastTrack(mediaProjectionPermissionResultData = mediaProjectionPermissionResultData) |
| 248 | localParticipant.publishVideoTrack( | 249 | localParticipant.publishVideoTrack( |
| 249 | - screencastTrack | 250 | + screencastTrack, |
| 250 | ) | 251 | ) |
| 251 | 252 | ||
| 252 | // Must start the foreground prior to startCapture. | 253 | // Must start the foreground prior to startCapture. |
| @@ -270,6 +271,8 @@ class CallViewModel( | @@ -270,6 +271,8 @@ class CallViewModel( | ||
| 270 | 271 | ||
| 271 | override fun onCleared() { | 272 | override fun onCleared() { |
| 272 | super.onCleared() | 273 | super.onCleared() |
| 274 | + | ||
| 275 | + // Make sure to release any resources associated with LiveKit | ||
| 273 | room.disconnect() | 276 | room.disconnect() |
| 274 | room.release() | 277 | room.release() |
| 275 | 278 |
-
请 注册 或 登录 后发表评论