Skip to content

Commit

Permalink
Bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
dkrivoruchko committed Aug 20, 2022
1 parent 4daf915 commit e3ee332
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import android.annotation.SuppressLint
import android.app.Service
import android.content.Context
import android.content.Intent
import android.hardware.display.DisplayManager
import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.os.RemoteException
import android.view.Display
import android.view.LayoutInflater
import android.view.WindowManager
import android.widget.Toast
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.ContextCompat
Expand Down Expand Up @@ -43,20 +46,20 @@ class ForegroundService : Service() {
}

internal object ForegroundServiceBinder : Binder() {
private val serviceMessageStateFlow = MutableStateFlow<ServiceMessage?>(null)
private val serviceMessageSharedFlow = MutableSharedFlow<ServiceMessage>()

internal val serviceMessageFlow: StateFlow<ServiceMessage?> = serviceMessageStateFlow.asStateFlow()
internal val serviceMessageFlow: SharedFlow<ServiceMessage> = serviceMessageSharedFlow.asSharedFlow()

internal fun sendMessage(serviceMessage: ServiceMessage) = try {
serviceMessageStateFlow.tryEmit(serviceMessage)
internal suspend fun sendMessage(serviceMessage: ServiceMessage) = try {
serviceMessageSharedFlow.emit(serviceMessage)
} catch (cause: RemoteException) {
XLog.d(getLog("sendMessage", "Failed to send message: $serviceMessage: $cause"))
XLog.e(getLog("sendMessage", "Failed to send message: $serviceMessage"), cause)
}
}

private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
private val effectFlow = MutableStateFlow<AppStateMachine.Effect?>(null)
private val effectFlow = MutableSharedFlow<AppStateMachine.Effect>(extraBufferCapacity = 8)

private val settings: Settings by inject()
private val notificationHelper: NotificationHelper by inject()
Expand All @@ -81,7 +84,7 @@ class ForegroundService : Service() {
notificationHelper.createNotificationChannel()
notificationHelper.showForegroundNotification(this, NotificationHelper.NotificationType.START)

effectFlow.filterNotNull().onEach { effect ->
effectFlow.onEach { effect ->
if (effect !is AppStateMachine.Effect.Statistic)
XLog.d(this@ForegroundService.getLog("onEffect", "Effect: $effect"))

Expand Down Expand Up @@ -150,7 +153,7 @@ class ForegroundService : Service() {

notificationHelper.hideErrorNotification()
stopForeground(true)
ForegroundServiceBinder.sendMessage(ServiceMessage.FinishActivity)
coroutineScope.launch { ForegroundServiceBinder.sendMessage(ServiceMessage.FinishActivity) }
this@ForegroundService.stopSelf()
}

Expand Down Expand Up @@ -184,11 +187,11 @@ class ForegroundService : Service() {

isRunning = false

coroutineScope.cancel()

appStateMachine?.destroy()
appStateMachine = null

coroutineScope.cancel()

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
stopForeground(STOP_FOREGROUND_REMOVE)
} else {
Expand All @@ -212,14 +215,27 @@ class ForegroundService : Service() {
}
}

@Suppress("DEPRECATION")
private val windowContext: Context by lazy(LazyThreadSafetyMode.NONE) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
this
} else {
val display = ContextCompat.getSystemService(this, DisplayManager::class.java)!!
.getDisplay(Display.DEFAULT_DISPLAY)

this.createDisplayContext(display)
.createWindowContext(WindowManager.LayoutParams.TYPE_TOAST, null)
}
}

@Suppress("DEPRECATION")
private fun showSlowConnectionToast() {
coroutineScope.launch {
val layoutInflater = ContextCompat.getSystemService(this@ForegroundService, LayoutInflater::class.java)!!
val layoutInflater = ContextCompat.getSystemService(windowContext, LayoutInflater::class.java)!!
val binding = ToastSlowConnectionBinding.inflate(layoutInflater)
val drawable = AppCompatResources.getDrawable(this@ForegroundService, R.drawable.ic_notification_small_24dp)
val drawable = AppCompatResources.getDrawable(windowContext, R.drawable.ic_notification_small_24dp)
binding.ivToastSlowConnection.setImageDrawable(drawable)
Toast(this@ForegroundService).apply { view = binding.root; duration = Toast.LENGTH_LONG }.show()
Toast(windowContext).apply { view = binding.root; duration = Toast.LENGTH_LONG }.show()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,10 @@ import com.elvishew.xlog.XLog
import info.dvkr.screenstream.R
import info.dvkr.screenstream.data.other.getLog
import info.dvkr.screenstream.service.helper.IntentAction
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch

@TargetApi(Build.VERSION_CODES.N)
class TileActionService : TileService() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,16 @@ import info.dvkr.screenstream.service.ForegroundService
import info.dvkr.screenstream.service.ServiceMessage
import info.dvkr.screenstream.service.helper.IntentAction
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch

abstract class ServiceActivity(@LayoutRes contentLayoutId: Int) : AppUpdateActivity(contentLayoutId) {

private var isBound: Boolean = false
private var serviceMessageFlowJob: Job? = null

private val _serviceMessageFlow = MutableStateFlow<ServiceMessage?>(null)
internal val serviceMessageFlow: StateFlow<ServiceMessage?> = _serviceMessageFlow.asStateFlow()
private val _serviceMessageFlow = MutableSharedFlow<ServiceMessage>()
internal val serviceMessageFlow: SharedFlow<ServiceMessage> = _serviceMessageFlow.asSharedFlow()

private val serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, binder: IBinder) {
Expand All @@ -45,8 +38,10 @@ abstract class ServiceActivity(@LayoutRes contentLayoutId: Int) : AppUpdateActiv

serviceMessageFlowJob = lifecycleScope.launch {
foregroundServiceBinder.serviceMessageFlow
.filterNotNull()
.onEach { serviceMessage -> onServiceMessage(serviceMessage) }
.onEach { serviceMessage ->
_serviceMessageFlow.emit(serviceMessage)
onServiceMessage(serviceMessage)
}
.catch { cause ->
XLog.e(this@ServiceActivity.getLog("onServiceConnected.serviceMessageFlow: $cause"))
XLog.e(this@ServiceActivity.getLog("onServiceConnected.serviceMessageFlow"), cause)
Expand Down Expand Up @@ -104,8 +99,6 @@ abstract class ServiceActivity(@LayoutRes contentLayoutId: Int) : AppUpdateActiv
open fun onServiceMessage(serviceMessage: ServiceMessage) {
XLog.v(getLog("onServiceMessage", "$serviceMessage"))

_serviceMessageFlow.tryEmit(serviceMessage)

if (serviceMessage is ServiceMessage.FinishActivity) {
finishAndRemoveTask()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import info.dvkr.screenstream.service.helper.IntentAction
import info.dvkr.screenstream.ui.activity.ServiceActivity
import info.dvkr.screenstream.ui.enableDisableViewWithChildren
import info.dvkr.screenstream.ui.viewBinding
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
Expand All @@ -44,7 +43,6 @@ class SettingsSecurityFragment : Fragment(R.layout.fragment_settings_security) {

(requireActivity() as ServiceActivity).serviceMessageFlow
.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED)
.filterNotNull()
.onEach { serviceMessage ->
if (serviceMessage is ServiceMessage.ServiceState) {
isStreaming = serviceMessage.isStreaming
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,7 @@ import info.dvkr.screenstream.data.model.AppError
import info.dvkr.screenstream.data.model.FatalError
import info.dvkr.screenstream.data.model.FixableError
import info.dvkr.screenstream.data.model.HttpClient
import info.dvkr.screenstream.data.other.asString
import info.dvkr.screenstream.data.other.bytesToMbit
import info.dvkr.screenstream.data.other.getLog
import info.dvkr.screenstream.data.other.getQRBitmap
import info.dvkr.screenstream.data.other.setColorSpan
import info.dvkr.screenstream.data.other.setUnderlineSpan
import info.dvkr.screenstream.data.other.*
import info.dvkr.screenstream.data.settings.SettingsReadOnly
import info.dvkr.screenstream.databinding.FragmentStreamBinding
import info.dvkr.screenstream.databinding.ItemClientBinding
Expand All @@ -43,7 +38,6 @@ import info.dvkr.screenstream.service.ServiceMessage
import info.dvkr.screenstream.service.helper.IntentAction
import info.dvkr.screenstream.ui.activity.ServiceActivity
import info.dvkr.screenstream.ui.viewBinding
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
Expand Down Expand Up @@ -83,7 +77,6 @@ class StreamFragment : AdFragment(R.layout.fragment_stream) {

(requireActivity() as ServiceActivity).serviceMessageFlow
.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED)
.filterNotNull()
.onEach { serviceMessage ->
when (serviceMessage) {
is ServiceMessage.ServiceState -> onServiceStateMessage(serviceMessage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import info.dvkr.screenstream.data.model.FatalError
import info.dvkr.screenstream.data.other.getLog
import info.dvkr.screenstream.data.other.randomString
import io.ktor.http.*
import io.ktor.http.cio.*
import io.ktor.http.cio.internals.*
import io.ktor.http.content.*
import io.ktor.server.application.*
import io.ktor.server.cio.*
Expand Down Expand Up @@ -85,8 +83,7 @@ internal fun Application.appModule(
if (cause is IOException) return@exception
if (cause is CancellationException) return@exception
if (cause is IllegalArgumentException) return@exception
val headers = CIOHeadersResearch.getHeadersAsString(call.request.headers as CIOHeaders)
XLog.e(this@appModule.getLog("exception<Throwable>", headers))
XLog.e(this@appModule.getLog("exception<Throwable>", cause.toString()))
XLog.e(this@appModule.getLog("exception"), cause)
sendEvent(HttpServer.Event.Error(FatalError.HttpServerException))
call.respond(HttpStatusCode.InternalServerError)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import android.content.Intent
import android.graphics.Bitmap
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.os.PowerManager
Expand All @@ -32,7 +31,7 @@ import java.util.concurrent.LinkedBlockingDeque
class AppStateMachineImpl(
private val serviceContext: Context,
private val settings: Settings,
private val effectSharedFlow: MutableStateFlow<AppStateMachine.Effect?>,
private val effectSharedFlow: MutableSharedFlow<AppStateMachine.Effect>,
private val onSlowConnectionDetected: () -> Unit
) : AppStateMachine {

Expand Down Expand Up @@ -99,7 +98,7 @@ class AppStateMachineImpl(
XLog.e(getLog("sendEvent", "Pending events => $eventDeque"), cause)
coroutineScope.launch(NonCancellable) {
streamState = componentError(streamState, FatalError.ChannelException, true)
effectSharedFlow.tryEmit(streamState.toPublicState())
effectSharedFlow.emit(streamState.toPublicState())
}
}
}
Expand Down Expand Up @@ -140,7 +139,7 @@ class AppStateMachineImpl(
else -> throw IllegalArgumentException("Unknown AppStateMachine.Event: $event")
}

if (streamState.isPublicStatePublishRequired(previousStreamState)) effectSharedFlow.tryEmit(streamState.toPublicState())
if (streamState.isPublicStatePublishRequired(previousStreamState)) effectSharedFlow.emit(streamState.toPublicState())

XLog.i(this@AppStateMachineImpl.getLog("eventSharedFlow.onEach", "New state:${streamState.state}"))
}
Expand All @@ -150,7 +149,7 @@ class AppStateMachineImpl(
.catch { cause ->
XLog.e(this@AppStateMachineImpl.getLog("eventSharedFlow.catch"), cause)
streamState = componentError(streamState, FatalError.CoroutineException, true)
effectSharedFlow.tryEmit(streamState.toPublicState())
effectSharedFlow.emit(streamState.toPublicState())
}
.collect()
}
Expand Down Expand Up @@ -209,13 +208,13 @@ class AppStateMachineImpl(
is HttpServer.Event.Statistic ->
when (event) {
is HttpServer.Event.Statistic.Clients -> {
effectSharedFlow.emit(AppStateMachine.Effect.Statistic.Clients(event.clients))
if (settings.autoStartStopFlow.first()) checkAutoStartStop(event.clients)
if (settings.notifySlowConnectionsFlow.first()) checkForSlowClients(event.clients)
effectSharedFlow.tryEmit(AppStateMachine.Effect.Statistic.Clients(event.clients))
}

is HttpServer.Event.Statistic.Traffic ->
effectSharedFlow.tryEmit(AppStateMachine.Effect.Statistic.Traffic(event.traffic))
effectSharedFlow.emit(AppStateMachine.Effect.Statistic.Traffic(event.traffic))
}

is HttpServer.Event.Error -> onError(event.error)
Expand Down Expand Up @@ -423,13 +422,13 @@ class AppStateMachineImpl(

when (reason) {
is RestartReason.ConnectionChanged ->
effectSharedFlow.tryEmit(AppStateMachine.Effect.ConnectionChanged)
effectSharedFlow.emit(AppStateMachine.Effect.ConnectionChanged)

is RestartReason.SettingsChanged ->
bitmapStateFlow.tryEmit(notificationBitmap.getNotificationBitmap(NotificationBitmap.Type.RELOAD_PAGE))
bitmapStateFlow.emit(notificationBitmap.getNotificationBitmap(NotificationBitmap.Type.RELOAD_PAGE))

is RestartReason.NetworkSettingsChanged ->
bitmapStateFlow.tryEmit(notificationBitmap.getNotificationBitmap(NotificationBitmap.Type.NEW_ADDRESS))
bitmapStateFlow.emit(notificationBitmap.getNotificationBitmap(NotificationBitmap.Type.NEW_ADDRESS))
}

withTimeoutOrNull(300) { httpServer.stop().await() }
Expand Down Expand Up @@ -463,7 +462,7 @@ class AppStateMachineImpl(
private suspend fun requestPublicState(streamState: StreamState): StreamState {
XLog.d(getLog("requestPublicState"))

effectSharedFlow.tryEmit(streamState.toPublicState())
effectSharedFlow.emit(streamState.toPublicState())
return streamState
}

Expand Down

This file was deleted.

0 comments on commit e3ee332

Please sign in to comment.