From 32f00d53c15fdf7e7a0752d5499555e291935257 Mon Sep 17 00:00:00 2001 From: davidliu Date: Sun, 26 Apr 2026 19:04:56 +0900 Subject: [PATCH 1/2] Detekt CI --- .github/workflows/android.yml | 7 +- .idea/compiler.xml | 1 + .../detekt-baseline-release.xml | 166 ++++++++++++++++++ 3 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 livekit-android-sdk/detekt-baseline-release.xml diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 5446f7434..ac8c4d3a6 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -58,6 +58,9 @@ jobs: - name: Build and test with Gradle run: ./gradlew assembleRelease livekit-android-test:testRelease + - name: Run Detekt + run: ./gradlew livekit-android-sdk:detektMain + - name: Upload AAR uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: @@ -181,7 +184,7 @@ jobs: if: github.event_name == 'push' && contains(steps.version_name.outputs.version_name,'SNAPSHOT') run: ./gradlew publishReleasePublicationToMavenRepository - # Setting up diffuse artifacts + # Setting up diffuse artifacts - name: Setup cache for base source file for diffuse if: github.event_name == 'push' uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 @@ -189,7 +192,7 @@ jobs: path: client-sdk-android/diffuse-source-file key: diffuse-${{ github.sha }} - # Copy your build artifact under `diffuse-source-file` name which will be saved in cache + # Copy your build artifact under `diffuse-source-file` name which will be saved in cache - name: Copy diffuse source file run: cp ./livekit-android-sdk/build/outputs/aar/livekit-android-sdk-release.aar diffuse-source-file if: github.event_name == 'push' diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 70ac3a9f2..4b587e94a 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -4,6 +4,7 @@ + diff --git a/livekit-android-sdk/detekt-baseline-release.xml b/livekit-android-sdk/detekt-baseline-release.xml new file mode 100644 index 000000000..ba07c77f6 --- /dev/null +++ b/livekit-android-sdk/detekt-baseline-release.xml @@ -0,0 +1,166 @@ + + + + + ComplexCondition:LocalParticipant.kt$LocalParticipant$(originalEncoding == null && !simulcast) || width == 0 || height == 0 + ComplexCondition:PeerConnectionTransport.kt$PeerConnectionTransport$sd.type == SessionDescription.Type.ANSWER && currentOfferId > 0 && offerId > 0 && currentOfferId > offerId + ComplexCondition:PreconnectAudioBuffer.kt$sentIdentities.contains(identity) || kind != Participant.Kind.AGENT || state != Participant.State.ACTIVE || identity == null + ComplexCondition:RTCEngine.kt$RTCEngine$(connectionState == ConnectionState.CONNECTED || connectionState == ConnectionState.RESUMING) && subscriberConnected && publisherConnected + ComplexCondition:RemoteTrackPublication.kt$RemoteTrackPublication$isAutoManaged || !subscribed || quality == videoQuality || track !is VideoTrack + ComplexCondition:RemoteTrackPublication.kt$RemoteTrackPublication$isAutoManaged || !subscribed || this.fps == fps || track !is VideoTrack + ComplexCondition:RemoteTrackPublication.kt$RemoteTrackPublication$isAutoManaged || !subscribed || videoDimensions == dimensions || track !is VideoTrack + ComplexCondition:TextureViewRenderer.kt$TextureViewRenderer$enableFixedSize && rotatedFrameWidth != 0 && rotatedFrameHeight != 0 && width != 0 && height != 0 + CyclomaticComplexMethod:LocalParticipant.kt$LocalParticipant$@Throws(TrackException.PublishException::class) private suspend fun publishTrackImpl( track: Track, options: TrackPublishOptions, requestConfig: AddTrackRequest.Builder.() -> Unit, encodings: List<RtpParameters.Encoding> = emptyList(), publishListener: PublishListener? = null, ): LocalTrackPublication? + CyclomaticComplexMethod:LocalParticipant.kt$LocalParticipant$private fun computeVideoEncodings( isScreenShare: Boolean, dimensions: Track.Dimensions, options: VideoTrackPublishOptions, ): List<RtpParameters.Encoding> + CyclomaticComplexMethod:LocalParticipant.kt$LocalParticipant$private suspend fun setTrackEnabled( source: Track.Source, enabled: Boolean, screenCaptureParams: ScreenCaptureParams? = null, ): Boolean + CyclomaticComplexMethod:LocalParticipant.kt$LocalParticipant$suspend fun publishVideoTrack( track: LocalVideoTrack, options: VideoTrackPublishOptions = VideoTrackPublishOptions( null, if (track.options.isScreencast) screenShareTrackPublishDefaults else videoTrackPublishDefaults, ), publishListener: PublishListener? = null, ): Boolean + CyclomaticComplexMethod:LocalVideoTrack.kt$LocalVideoTrack$private fun setPublishingLayersForSender( sender: RtpSender, qualities: List<LivekitRtc.SubscribedQuality>, ) + CyclomaticComplexMethod:NetworkInfo.kt$AndroidNetworkInfo$override fun getNetworkType(): NetworkType + CyclomaticComplexMethod:PeerConnectionTransport.kt$@VisibleForTesting fun ensureCodecBitrates( media: MediaDescription, trackBitrates: Map<TrackBitrateInfoKey, TrackBitrateInfo>, ) + CyclomaticComplexMethod:PeerConnectionTransport.kt$PeerConnectionTransport$private suspend fun createAndSendOffer(constraints: MediaConstraints = MediaConstraints()) + CyclomaticComplexMethod:PreconnectAudioBuffer.kt$@Deprecated("Set AudioTrackPublishDefaults.preconnect = true on the RoomOptions instead.") suspend fun <T> Room.withPreconnectAudio( timeout: Duration = TIMEOUT, topic: String = DEFAULT_TOPIC, onError: ((e: Exception) -> Unit)? = null, operation: suspend () -> T, ) + CyclomaticComplexMethod:PreconnectAudioBuffer.kt$internal suspend fun Room.startPreconnectAudioJob( roomScope: CoroutineScope, timeout: Duration = TIMEOUT, topic: String = DEFAULT_TOPIC ): () -> Unit + CyclomaticComplexMethod:RTCEngine.kt$RTCEngine$@CheckResult internal suspend fun sendData(dataPacket: LivekitModels.DataPacket): Result<Unit> + CyclomaticComplexMethod:RTCEngine.kt$RTCEngine$@Synchronized @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) fun reconnect() + CyclomaticComplexMethod:RTCEngine.kt$RTCEngine$fun onMessage(dataChannel: DataChannel, buffer: DataChannel.Buffer?) + CyclomaticComplexMethod:RTCEngine.kt$RTCEngine$private fun makeRTCConfig( serverResponse: Either<JoinResponse, ReconnectResponse>, connectOptions: ConnectOptions, ): RTCConfiguration + CyclomaticComplexMethod:Room.kt$Room$@Throws(Exception::class) suspend fun connect(url: String, token: String, options: ConnectOptions = ConnectOptions()) + CyclomaticComplexMethod:RoomEvent.kt$fun LivekitModels.DisconnectReason?.convert(): DisconnectReason + CyclomaticComplexMethod:SignalClient.kt$SignalClient$private fun handleSignalResponseImpl(ws: WebSocket, response: LivekitRtc.SignalResponse) + DoubleMutabilityForCollection:CoroutineSdpObserver.kt$CoroutineSdpObserver$private var pendingCreate = mutableListOf<Continuation<Either<SessionDescription, String?>>>() + DoubleMutabilityForCollection:CoroutineSdpObserver.kt$CoroutineSdpObserver$private var pendingSets = mutableListOf<Continuation<Either<Unit, String?>>>() + DoubleMutabilityForCollection:E2EEManager.kt$E2EEManager$private var frameCryptors = mutableMapOf<Pair<String, Participant.Identity>, FrameCryptor>() + DoubleMutabilityForCollection:PeerConnectionTransport.kt$PeerConnectionTransport$private var trackBitrates = mutableMapOf<TrackBitrateInfoKey, TrackBitrateInfo>() + DoubleMutabilityForCollection:RegionUrlProvider.kt$RegionUrlProvider$private var attemptedRegions = mutableSetOf<RegionInfo>() + DoubleMutabilityForCollection:Room.kt$Room$private var sidToIdentity = mutableMapOf<Participant.Sid, Participant.Identity>() + DoubleMutabilityForCollection:Room.kt$Room$private var transcriptionReceivedTimes = mutableMapOf<String, Long>() + EmptyCatchBlock:EndpointTokenSource.kt$EndpointTokenSource.<no name provided>${ } + EmptyDefaultConstructor:CachingTokenSource.kt$InMemoryTokenStore$() + EmptyDefaultConstructor:LocalScreencastVideoTrack.kt$LocalScreencastVideoTrack.MediaProjectionCallback$() + EmptyFunctionBlock:CommunicationWorkaround.kt$NoopCommunicationWorkaround${ } + EmptyFunctionBlock:LocalVideoTrack.kt$LocalVideoTrack.<no name provided>.<no name provided>${ } + EmptyFunctionBlock:NoAudioHandler.kt$NoAudioHandler${ } + EmptyFunctionBlock:PublisherTransportObserver.kt$PublisherTransportObserver${ } + EmptyFunctionBlock:RTCEngine.kt$RTCEngine${ } + EmptyFunctionBlock:Room.kt$Room${ } + EmptyFunctionBlock:SubscriberTransportObserver.kt$SubscriberTransportObserver${ } + EmptyFunctionBlock:TextureViewRenderer.kt$TextureViewRenderer${} + EmptyFunctionBlock:VideoFrameCapturer.kt$VideoFrameCapturer${ } + HasPlatformType:DataChannelManager.kt$DataChannelManager$@get:FlowObservable var state by flowDelegate(dataChannel.state()) private set + HasPlatformType:RTCModule.kt$RTCModule$@Provides fun sdpFactory() + IgnoredReturnValue:BaseStreamReceiver.kt$BaseStreamReceiver$catch { } + InjectDispatcher:CoroutinesModule.kt$CoroutinesModule$Default + InjectDispatcher:CoroutinesModule.kt$CoroutinesModule$IO + InjectDispatcher:CoroutinesModule.kt$CoroutinesModule$Unconfined + InjectDispatcher:NetworkMonitor.kt$NetworkMonitor$IO + InstanceOfCheckForException:LocalParticipant.kt$LocalParticipant$e is RpcError + LargeClass:LocalParticipant.kt$LocalParticipant : ParticipantOutgoingDataStreamManagerRpcManager + LargeClass:RTCEngine.kt$RTCEngine : Listener + LargeClass:Room.kt$Room : ListenerParticipantListenerRpcManagerIncomingDataStreamManager + LargeClass:SignalClient.kt$SignalClient : WebSocketListener + LongMethod:LocalParticipant.kt$LocalParticipant$@Throws(TrackException.PublishException::class) private suspend fun publishTrackImpl( track: Track, options: TrackPublishOptions, requestConfig: AddTrackRequest.Builder.() -> Unit, encodings: List<RtpParameters.Encoding> = emptyList(), publishListener: PublishListener? = null, ): LocalTrackPublication? + LongMethod:LocalParticipant.kt$LocalParticipant$override suspend fun performRpc( destinationIdentity: Identity, method: String, payload: String, responseTimeout: Duration, ): String + LongMethod:LocalParticipant.kt$LocalParticipant$private fun publishAdditionalCodecForTrack(track: LocalVideoTrack, codec: VideoCodec, options: VideoTrackPublishOptions) + LongMethod:LocalParticipant.kt$LocalParticipant$private suspend fun handleIncomingRpcRequest( callerIdentity: Identity, requestId: String, method: String, payload: String, responseTimeout: Duration, version: Int, ) + LongMethod:LocalParticipant.kt$LocalParticipant$private suspend fun setTrackEnabled( source: Track.Source, enabled: Boolean, screenCaptureParams: ScreenCaptureParams? = null, ): Boolean + LongMethod:LocalParticipant.kt$LocalParticipant$suspend fun publishVideoTrack( track: LocalVideoTrack, options: VideoTrackPublishOptions = VideoTrackPublishOptions( null, if (track.options.isScreencast) screenShareTrackPublishDefaults else videoTrackPublishDefaults, ), publishListener: PublishListener? = null, ): Boolean + LongMethod:PeerConnectionTransport.kt$PeerConnectionTransport$private suspend fun createAndSendOffer(constraints: MediaConstraints = MediaConstraints()) + LongMethod:RTCEngine.kt$RTCEngine$@Synchronized @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) fun reconnect() + LongMethod:RTCEngine.kt$RTCEngine$fun onMessage(dataChannel: DataChannel, buffer: DataChannel.Buffer?) + LongMethod:RTCEngine.kt$RTCEngine$private suspend fun configure(joinResponse: JoinResponse, connectOptions: ConnectOptions) + LongMethod:Room.kt$Room$@Synchronized private fun getOrCreateRemoteParticipant( identity: Participant.Identity, info: LivekitModels.ParticipantInfo, ): RemoteParticipant + LongMethod:Room.kt$Room$@Throws(Exception::class) suspend fun connect(url: String, token: String, options: ConnectOptions = ConnectOptions()) + LongMethod:Room.kt$Room$private fun setupLocalParticipantEventHandling() + LongMethod:SignalClient.kt$SignalClient$private fun handleSignalResponseImpl(ws: WebSocket, response: LivekitRtc.SignalResponse) + LongParameterList:AudioBufferCallbackDispatcher.kt$AudioBufferCallback$(buffer: ByteBuffer, audioFormat: Int, channelCount: Int, sampleRate: Int, bytesRead: Int, captureTimeNs: Long) + LongParameterList:KeyProvider.kt$BaseKeyProvider$( ratchetSalt: String = defaultRatchetSalt, uncryptedMagicBytes: String = defaultMagicBytes, ratchetWindowSize: Int = defaultRatchetWindowSize, override var enableSharedKey: Boolean = true, failureTolerance: Int = defaultFailureTolerance, keyRingSize: Int = defaultKeyRingSize, discardFrameWhenCryptorNotReady: Boolean = defaultDiscardFrameWhenCryptorNotReady, keyDerivationAlgorithm: FrameCryptorKeyDerivationAlgorithm = defaultKeyDerivationAlgorithm, ) + LongParameterList:LiveKitOverrides.kt$AudioOptions$( /** * Override the default output [AudioType]. * * This affects the audio routing and how the audio is handled. Default is [AudioType.CallAudioType]. * * Note: if [audioHandler] is also passed, the values from [audioOutputType] will not be reflected in it, * and must be set yourself. */ val audioOutputType: AudioType? = null, /** * Override the default [AudioHandler]. * * Default is [AudioSwitchHandler]. * * Use [NoAudioHandler] to turn off automatic audio handling or * [AudioFocusHandler] to get simple audio focus handling. */ val audioHandler: AudioHandler? = null, /** * Override the default [AudioDeviceModule]. * * If a non-null value is passed, the library does not * take ownership of the object and will not release it upon [Room.release]. * It is the responsibility of the owner to call [AudioDeviceModule.release] when finished * with it to prevent memory leaks. */ val audioDeviceModule: AudioDeviceModule? = null, /** * Called after default setup to allow for customizations on the [JavaAudioDeviceModule]. * * Not used if [audioDeviceModule] is provided. * * Note: We require setting the [JavaAudioDeviceModule.Builder.setSamplesReadyCallback] to provide * support for [LocalAudioTrack.addSink]. If you wish to grab the audio samples * from the local microphone track, use [LocalAudioTrack.addSink] instead of setting your own * callback. */ val javaAudioDeviceModuleCustomizer: ((builder: JavaAudioDeviceModule.Builder) -> Unit)? = null, /** * On Android 11+, the audio mode will reset itself from [AudioManager.MODE_IN_COMMUNICATION] if * there is no audio playback or capture for 6 seconds (for example when joining a room with * no speakers and the local mic is muted.) This mode reset will cause unexpected * behavior when trying to change the volume, causing it to not properly change the volume. * * We use a workaround by playing a silent audio track to keep the communication mode from * resetting. * * Setting this flag to true will disable the workaround. * * This flag is a no-op when the audio mode is set to anything other than * [AudioManager.MODE_IN_COMMUNICATION]. */ val disableCommunicationModeWorkaround: Boolean = false, /** * Options for processing the mic and incoming audio. */ val audioProcessorOptions: AudioProcessorOptions? = null, /** * Devices may take some time initializing the audio stack for recording. * Prewarming allows starting up the underlying audio recording prior to publish, letting * the audio device be ready immediately when the track is fully published. * * If set to true, disables audio recording prewarming (and the related * [LocalAudioTrack.prewarm] function), and audio resources are only used while the * track is connected and published. Defaults to false. */ val disableAudioPrewarming: Boolean = false, ) + LongParameterList:LocalAudioTrack.kt$LocalAudioTrack$( @Assisted name: String, @Assisted mediaTrack: livekit.org.webrtc.AudioTrack, @Assisted private val options: LocalAudioTrackOptions, private val audioProcessingController: AudioProcessingController, @Named(InjectionNames.DISPATCHER_DEFAULT) private val dispatcher: CoroutineDispatcher, @Named(InjectionNames.LOCAL_AUDIO_RECORD_SAMPLES_DISPATCHER) private val audioRecordSamplesDispatcher: AudioRecordSamplesDispatcher, @Named(InjectionNames.LOCAL_AUDIO_BUFFER_CALLBACK_DISPATCHER) private val audioBufferCallbackDispatcher: AudioBufferCallbackDispatcher, private val audioRecordPrewarmer: AudioRecordPrewarmer, rtcThreadToken: RTCThreadToken, ) + LongParameterList:LocalParticipant.kt$LocalParticipant$( @Assisted internal var dynacast: Boolean, internal val engine: RTCEngine, private val peerConnectionFactory: PeerConnectionFactory, private val context: Context, private val eglBase: EglBase, private val screencastVideoTrackFactory: LocalScreencastVideoTrack.Factory, private val videoTrackFactory: LocalVideoTrack.Factory, private val audioTrackFactory: LocalAudioTrack.Factory, private val defaultsManager: DefaultsManager, @Named(InjectionNames.DISPATCHER_DEFAULT) coroutineDispatcher: CoroutineDispatcher, @Named(InjectionNames.SENDER) private val capabilitiesGetter: CapabilitiesGetter, private val outgoingDataStreamManager: OutgoingDataStreamManager, ) + LongParameterList:LocalParticipant.kt$LocalParticipant$( callerIdentity: Identity, requestId: String, method: String, payload: String, responseTimeout: Duration, version: Int, ) + LongParameterList:LocalScreencastVideoTrack.kt$LocalScreencastVideoTrack$( @Assisted capturer: VideoCapturer, @Assisted source: VideoSource, @Assisted name: String, @Assisted options: LocalVideoTrackOptions, @Assisted rtcTrack: livekit.org.webrtc.VideoTrack, @Assisted mediaProjectionCallback: MediaProjectionCallback, peerConnectionFactory: PeerConnectionFactory, context: Context, eglBase: EglBase, defaultsManager: DefaultsManager, videoTrackFactory: LocalVideoTrack.Factory, rtcThreadToken: RTCThreadToken, ) + LongParameterList:LocalScreencastVideoTrack.kt$LocalScreencastVideoTrack.Companion$( mediaProjectionPermissionResultData: Intent, peerConnectionFactory: PeerConnectionFactory, context: Context, name: String, options: LocalVideoTrackOptions, rootEglBase: EglBase, screencastVideoTrackFactory: Factory, videoProcessor: VideoProcessor?, onStop: (Track) -> Unit, ) + LongParameterList:LocalScreencastVideoTrack.kt$LocalScreencastVideoTrack.Factory$( capturer: VideoCapturer, source: VideoSource, name: String, options: LocalVideoTrackOptions, rtcTrack: livekit.org.webrtc.VideoTrack, mediaProjectionCallback: MediaProjectionCallback, ) + LongParameterList:LocalVideoTrack.kt$LocalVideoTrack$( @Assisted capturer: VideoCapturer, @Assisted private var source: VideoSource, @Assisted name: String, @Assisted options: LocalVideoTrackOptions, @Assisted rtcTrack: livekit.org.webrtc.VideoTrack, private val peerConnectionFactory: PeerConnectionFactory, private val context: Context, private val eglBase: EglBase, private val defaultsManager: DefaultsManager, private val trackFactory: Factory, /** * If this is assigned, you must ensure that this observer is associated with the [capturer], * as this will be used to receive frames in [addRenderer]. **/ @Assisted private var dispatchObserver: CaptureDispatchObserver? = null, rtcThreadToken: RTCThreadToken, ) + LongParameterList:LocalVideoTrack.kt$LocalVideoTrack.Companion$( peerConnectionFactory: PeerConnectionFactory, context: Context, name: String, capturer: VideoCapturer, options: LocalVideoTrackOptions = LocalVideoTrackOptions(), rootEglBase: EglBase, trackFactory: Factory, videoProcessor: VideoProcessor? = null, ) + LongParameterList:LocalVideoTrack.kt$LocalVideoTrack.Companion$( peerConnectionFactory: PeerConnectionFactory, context: Context, name: String, options: LocalVideoTrackOptions, rootEglBase: EglBase, trackFactory: Factory, videoProcessor: VideoProcessor? = null, ) + LongParameterList:LocalVideoTrack.kt$LocalVideoTrack.Factory$( capturer: VideoCapturer, source: VideoSource, name: String, options: LocalVideoTrackOptions, rtcTrack: livekit.org.webrtc.VideoTrack, dispatchObserver: CaptureDispatchObserver?, ) + LongParameterList:MixerAudioBufferCallback.kt$MixerAudioBufferCallback$(originalBuffer: ByteBuffer, audioFormat: Int, channelCount: Int, sampleRate: Int, bytesRead: Int, captureTimeNs: Long) + LongParameterList:PeerConnectionTransport.kt$PeerConnectionTransport$( @Assisted config: RTCConfiguration, @Assisted pcObserver: PeerConnection.Observer, @Assisted private val listener: Listener?, @Named(InjectionNames.DISPATCHER_IO) private val ioDispatcher: CoroutineDispatcher, connectionFactory: PeerConnectionFactory, private val sdpFactory: SdpFactory, private val rtcThreadToken: RTCThreadToken, ) + LongParameterList:RTCMetricsManager.kt$( label: MetricLabel, strings: MutableList<String>, samples: List<MetricSample>, identity: Participant.Identity? = null, trackSid: String? = null, rid: String? = null, ) + LongParameterList:RTCModule.kt$RTCModule$( @Named(InjectionNames.OVERRIDE_AUDIO_DEVICE_MODULE) audioDeviceModuleOverride: AudioDeviceModule?, @Named(InjectionNames.OVERRIDE_JAVA_AUDIO_DEVICE_MODULE_CUSTOMIZER) moduleCustomizer: ((builder: JavaAudioDeviceModule.Builder) -> Unit)?, audioOutputAttributes: AudioAttributes, appContext: Context, closeableManager: CloseableManager, communicationWorkaround: CommunicationWorkaround, @Named(InjectionNames.LOCAL_AUDIO_RECORD_SAMPLES_DISPATCHER) audioRecordSamplesDispatcher: AudioRecordSamplesDispatcher, @Named(InjectionNames.LOCAL_AUDIO_BUFFER_CALLBACK_DISPATCHER) audioBufferCallbackDispatcher: AudioBufferCallbackDispatcher, ) + LongParameterList:RTCModule.kt$RTCModule$( @Suppress("UNUSED_PARAMETER") @Named(InjectionNames.LIB_WEBRTC_INITIALIZATION) webrtcInitialization: LibWebrtcInitialization, audioDeviceModule: AudioDeviceModule, videoEncoderFactory: VideoEncoderFactory, videoDecoderFactory: VideoDecoderFactory, @Named(InjectionNames.OVERRIDE_PEER_CONNECTION_FACTORY_OPTIONS) peerConnectionFactoryOptions: PeerConnectionFactory.Options?, memoryManager: CloseableManager, audioProcessingFactory: AudioProcessingFactory, ) + LongParameterList:RTCStatsExt.kt$( trackIdentifier: String, ssrcs: Set<Long?>, codecIds: Set<String?>, localCandidateId: String?, remoteCandidateId: String?, statsMap: Map<String, RTCStats>, ) + LongParameterList:RemoteParticipant.kt$RemoteParticipant$( mediaTrack: MediaStreamTrack, sid: String, statsGetter: RTCStatsGetter, receiver: RtpReceiver, autoManageVideo: Boolean = false, triesLeft: Int = 20, ) + LongParameterList:RemoteParticipant.kt$RemoteParticipant$( sid: Sid, identity: Identity? = null, internal val signalClient: SignalClient, private val ioDispatcher: CoroutineDispatcher, defaultDispatcher: CoroutineDispatcher, private val audioTrackFactory: RemoteAudioTrack.Factory, private val videoTrackFactory: RemoteVideoTrack.Factory, ) + LongParameterList:Room.kt$Room$( @Assisted private val context: Context, internal val engine: RTCEngine, private val eglBase: EglBase, localParticipantFactory: LocalParticipant.Factory, private val defaultsManager: DefaultsManager, @Named(InjectionNames.DISPATCHER_DEFAULT) private val defaultDispatcher: CoroutineDispatcher, @Named(InjectionNames.DISPATCHER_IO) private val ioDispatcher: CoroutineDispatcher, /** * The [AudioHandler] for setting up the audio as need. * * By default, this is an instance of [AudioSwitchHandler]. * * This can be substituted for your own custom implementation through * [LiveKitOverrides.audioOptions] when creating the room with [LiveKit.create]. * * @see [audioSwitchHandler] * @see [AudioSwitchHandler] */ val audioHandler: AudioHandler, private val closeableManager: CloseableManager, private val e2EEManagerFactory: E2EEManager.Factory, private val communicationWorkaround: CommunicationWorkaround, val audioProcessingController: AudioProcessingController, /** * A holder for objects that are used internally within LiveKit. */ val lkObjects: LKObjects, networkCallbackManagerFactory: NetworkCallbackManagerFactory, private val audioDeviceModule: AudioDeviceModule, private val regionUrlProviderFactory: RegionUrlProvider.Factory, private val connectionWarmer: ConnectionWarmer, private val audioRecordPrewarmer: AudioRecordPrewarmer, private val incomingDataStreamManager: IncomingDataStreamManager, private val remoteParticipantFactory: RemoteParticipant.Factory, ) + MapGetWithNotNullAssertionOperator:LocalParticipant.kt$LocalParticipant$sourcePubLocks[source]!! + NestedBlockDepth:ByteStreamSender.kt$@CheckResult suspend fun ByteStreamSender.write(source: Source): Result<Unit> + NestedBlockDepth:LocalParticipant.kt$LocalParticipant$@Throws(TrackException.PublishException::class) private suspend fun publishTrackImpl( track: Track, options: TrackPublishOptions, requestConfig: AddTrackRequest.Builder.() -> Unit, encodings: List<RtpParameters.Encoding> = emptyList(), publishListener: PublishListener? = null, ): LocalTrackPublication? + NestedBlockDepth:LocalParticipant.kt$LocalParticipant$fun cleanup() + NestedBlockDepth:LocalVideoTrack.kt$LocalVideoTrack$internal fun setPublishingCodecs(codecs: List<SubscribedCodec>): List<VideoCodec> + NestedBlockDepth:LocalVideoTrack.kt$LocalVideoTrack$private fun setPublishingLayersForSender( sender: RtpSender, qualities: List<LivekitRtc.SubscribedQuality>, ) + NestedBlockDepth:OutgoingDataStreamManager.kt$OutgoingDataStreamManagerImpl$@CheckResult private suspend fun openStream( info: StreamInfo, destinationIdentities: List<Participant.Identity> = emptyList(), ): Result<Unit> + NestedBlockDepth:PeerConnectionTransport.kt$@VisibleForTesting fun ensureCodecBitrates( media: MediaDescription, trackBitrates: Map<TrackBitrateInfoKey, TrackBitrateInfo>, ) + NestedBlockDepth:RTCEngine.kt$RTCEngine$@CheckResult internal suspend fun sendData(dataPacket: LivekitModels.DataPacket): Result<Unit> + NestedBlockDepth:RTCEngine.kt$RTCEngine$private fun makeRTCConfig( serverResponse: Either<JoinResponse, ReconnectResponse>, connectOptions: ConnectOptions, ): RTCConfiguration + NestedBlockDepth:Room.kt$Room$override suspend fun onPostReconnect(isFullReconnect: Boolean) + NestedBlockDepth:SignalClient.kt$SignalClient$override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) + SwallowedException:EndpointTokenSource.kt$EndpointTokenSource.<no name provided>$e: Exception + SwallowedException:FlowExt.kt$e: CancellationException + SwallowedException:LocalVideoTrack.kt$LocalVideoTrack$e: Exception + SwallowedException:NetworkCallbackManager.kt$NetworkCallbackManagerImpl$e: IllegalArgumentException + SwallowedException:RemoteParticipant.kt$RemoteParticipant$e: Exception + SwallowedException:TextureViewRenderer.kt$TextureViewRenderer$e: NotFoundException + ThrowingExceptionsWithoutMessageOrCause:LKDebugTree.kt$LKDebugTree$Throwable() + ThrowingExceptionsWithoutMessageOrCause:SignalClient.kt$SignalClient$Exception() + TooManyFunctions:CommunicationWorkaround.kt$CommunicationWorkaroundImpl : CommunicationWorkaround + TooManyFunctions:E2EEManager.kt$E2EEManager + TooManyFunctions:IncomingDataStreamManager.kt$IncomingDataStreamManagerImpl : IncomingDataStreamManager + TooManyFunctions:LKLog.kt$LKLog$Companion + TooManyFunctions:LocalParticipant.kt$LocalParticipant : ParticipantOutgoingDataStreamManagerRpcManager + TooManyFunctions:LocalVideoTrack.kt$LocalVideoTrack : VideoTrack + TooManyFunctions:OverridesModule.kt$OverridesModule + TooManyFunctions:Participant.kt$Participant + TooManyFunctions:Participant.kt$ParticipantListener + TooManyFunctions:PeerConnectionTransport.kt$PeerConnectionTransport + TooManyFunctions:PublisherTransportObserver.kt$PublisherTransportObserver : ObserverListenerPeerConnectionStateObservable + TooManyFunctions:RTCEngine.kt$RTCEngine : Listener + TooManyFunctions:RTCEngine.kt$RTCEngine$Listener + TooManyFunctions:RTCMetricsManager.kt$io.livekit.android.room.metrics.RTCMetricsManager.kt + TooManyFunctions:RTCModule.kt$RTCModule + TooManyFunctions:Room.kt$Room : ListenerParticipantListenerRpcManagerIncomingDataStreamManager + TooManyFunctions:SignalClient.kt$SignalClient : WebSocketListener + TooManyFunctions:SignalClient.kt$SignalClient$Listener + TooManyFunctions:SimulcastVideoEncoderFactoryWrapper.kt$SimulcastVideoEncoderFactoryWrapper$StreamEncoderWrapper : VideoEncoder + TooManyFunctions:SubscriberTransportObserver.kt$SubscriberTransportObserver : ObserverPeerConnectionStateObservable + TooManyFunctions:TextureViewRenderer.kt$TextureViewRenderer : TextureViewCallbackSurfaceTextureListenerVideoSinkRendererEventsNotifier + UnnecessaryNotNullOperator:E2EEManager.kt$E2EEManager$room!! + UnnecessaryNotNullOperator:Room.kt$Room$e2eeManager!! + UnnecessarySafeCall:E2EEManager.kt$E2EEManager$(publication.track!! as LocalAudioTrack)?.sender + UnnecessarySafeCall:E2EEManager.kt$E2EEManager$(publication.track!! as LocalVideoTrack)?.sender + UnsafeCallOnNullableType:AudioSwitchHandler.kt$AudioSwitchHandler$thread!! + UnsafeCallOnNullableType:CustomAudioProcessingFactory.kt$CustomAudioProcessingFactory.AudioProcessingBridge$buffer!! + UnsafeCallOnNullableType:DataPacketBuffer.kt$DataPacketBuffer$item!! + UnsafeCallOnNullableType:E2EEManager.kt$E2EEManager$participant.identity!! + UnsafeCallOnNullableType:E2EEManager.kt$E2EEManager$publication.track!! + UnsafeCallOnNullableType:E2EEManager.kt$E2EEManager$rtpReceiver!! + UnsafeCallOnNullableType:E2EEManager.kt$E2EEManager$rtpSender!! + UnsafeCallOnNullableType:E2EEManager.kt$E2EEManager$this.room!! + UnsafeCallOnNullableType:EncodingUtils.kt$EncodingUtils$encodings.first().scalabilityMode!! + UnsafeCallOnNullableType:LocalParticipant.kt$LocalParticipant$options.backupCodec!! + UnsafeCallOnNullableType:LocalParticipant.kt$LocalParticipant$sourcePubLocks[source]!! + UnsafeCallOnNullableType:LocalParticipant.kt$VideoTrackPublishOptions$backupCodec!! + UnsafeCallOnNullableType:LocalScreencastVideoTrack.kt$LocalScreencastVideoTrack.MediaProjectionCallback$track!! + UnsafeCallOnNullableType:LocalVideoTrack.kt$LocalVideoTrack$simulcastInfo.sender!! + UnsafeCallOnNullableType:PeerConnectionTransport.kt$PeerConnectionTransport$executeBlockingOnRTCThread(rtcThreadToken) { connectionFactory.createPeerConnection( config, pcObserver, ) ?: throw IllegalStateException("peer connection creation failed?") }!! + UnsafeCallOnNullableType:RTCEngine.kt$RTCEngine$publisher!! + UnsafeCallOnNullableType:RTCEngine.kt$RTCEngine$subscriber!! + UnsafeCallOnNullableType:RTCEngine.kt$RTCEngine$url!! + UnsafeCallOnNullableType:RTCModule.kt$RTCModule$executeBlockingOnRTCThread(LibWebrtcInitializationThreadToken) { val peerConnectionFactory = PeerConnectionFactory.builder() .setAudioDeviceModule(audioDeviceModule) .setAudioProcessingFactory(audioProcessingFactory) .setVideoEncoderFactory(videoEncoderFactory) .setVideoDecoderFactory(videoDecoderFactory) .apply { if (peerConnectionFactoryOptions != null) { setOptions(peerConnectionFactoryOptions) } } .createPeerConnectionFactory() return@executeBlockingOnRTCThread PeerConnectionFactoryManager(peerConnectionFactory) .apply { memoryManager.registerClosable { executeOnRTCThread(RTCThreadTokenImpl(this)) { dispose() } } } }!! + UnsafeCallOnNullableType:Room.kt$Room$e2eeManager!! + UnsafeCallOnNullableType:Room.kt$Room$publication.track!! + UnsafeCallOnNullableType:SimulcastVideoEncoderFactoryWrapper.kt$SimulcastVideoEncoderFactoryWrapper.StreamEncoderWrapper$streamSettings!! + UnsafeCallOnNullableType:TextureViewRenderer.kt$TextureViewRenderer$rendererEvents!! + + From ac4c80574a302cbaf961814185b17c1546e14f17 Mon Sep 17 00:00:00 2001 From: davidliu Date: Sun, 26 Apr 2026 19:25:36 +0900 Subject: [PATCH 2/2] detekt on release only --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index ac8c4d3a6..f1c765326 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -59,7 +59,7 @@ jobs: run: ./gradlew assembleRelease livekit-android-test:testRelease - name: Run Detekt - run: ./gradlew livekit-android-sdk:detektMain + run: ./gradlew livekit-android-sdk:detektRelease - name: Upload AAR uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0