Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4688fd89 authored by Jorge Gil's avatar Jorge Gil
Browse files

Provide @ShellMainThread dispatcher as MainCoroutineDispatcher

Changes the CoroutineDispatcher (and thus scope) for shell.main to a
MainCoroutineDispatcher backed by a Handler. This is because
Executor#asCoroutineDispatcher assumes the #execute will post the
runnable but ShellExecutor actually runs it immediately if already on
the same thread. Using Handler#asCoroutinesDispatcher doesn't have the
same problem because the backing Handler always uses #post to run the
Runnable.
CoroutineDispatchers already have this immediate vs posted functionality
built-in (see CoroutineDispatcher#isDispatchNeeded), and
MainCoroutineDispatcher#immediate is available to callers that want to
explicitly run coroutines in an immediate (non-dispatching) way.

Bug: None
Flag: EXEMPT bugfix
Test: m
Change-Id: I516351b93d103b59f8fa8d191f300122acdf9001
parent ec252cbd
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.dagger

import android.os.Handler
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.shared.annotations.ShellBackgroundThread
import com.android.wm.shell.shared.annotations.ShellMainThread
@@ -24,22 +25,37 @@ import dagger.Provides
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainCoroutineDispatcher
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.android.asCoroutineDispatcher
import kotlinx.coroutines.asCoroutineDispatcher

/** Providers for various WmShell-specific coroutines-related constructs. */
/**
 * Providers for various WmShell-specific coroutines-related constructs.
 *
 * Providers of [MainCoroutineDispatcher] intentionally creates the dispatcher with a [Handler]
 * backing it instead of a [ShellExecutor] because [ShellExecutor.asCoroutineDispatcher] will
 * create a [CoroutineDispatcher] whose [CoroutineDispatcher.isDispatchNeeded] is effectively never
 * dispatching. This is because even if dispatched, the backing [ShellExecutor.execute] always runs
 * the [Runnable] immediately if called from the same thread, whereas
 * [Handler.asCoroutineDispatcher] will create a [MainCoroutineDispatcher] that correctly
 * dispatches (queues) when [CoroutineDispatcher.isDispatchNeeded] is true using [Handler.post].
 * For callers that do need a non-dispatching version, [MainCoroutineDispatcher.immediate] is
 * available.
 */
@Module
class WMShellCoroutinesModule {
  @Provides
  @ShellMainThread
  fun provideMainDispatcher(@ShellMainThread mainExecutor: ShellExecutor): CoroutineDispatcher =
      mainExecutor.asCoroutineDispatcher()
  fun provideMainDispatcher(
    @ShellMainThread mainHandler: Handler
  ): MainCoroutineDispatcher = mainHandler.asCoroutineDispatcher()

  @Provides
  @ShellBackgroundThread
  fun provideBackgroundDispatcher(
      @ShellBackgroundThread backgroundExecutor: ShellExecutor
  ): CoroutineDispatcher = backgroundExecutor.asCoroutineDispatcher()
      @ShellBackgroundThread backgroundHandler: Handler
  ): MainCoroutineDispatcher = backgroundHandler.asCoroutineDispatcher()

  @Provides
  @WMSingleton