• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.android.wm.shell.dagger
18 
19 import android.os.Handler
20 import com.android.wm.shell.common.ShellExecutor
21 import com.android.wm.shell.shared.annotations.ShellBackgroundThread
22 import com.android.wm.shell.shared.annotations.ShellMainThread
23 import dagger.Module
24 import dagger.Provides
25 import kotlin.coroutines.CoroutineContext
26 import kotlinx.coroutines.CoroutineDispatcher
27 import kotlinx.coroutines.CoroutineScope
28 import kotlinx.coroutines.MainCoroutineDispatcher
29 import kotlinx.coroutines.SupervisorJob
30 import kotlinx.coroutines.android.asCoroutineDispatcher
31 import kotlinx.coroutines.asCoroutineDispatcher
32 
33 /**
34  * Providers for various WmShell-specific coroutines-related constructs.
35  *
36  * Providers of [MainCoroutineDispatcher] intentionally creates the dispatcher with a [Handler]
37  * backing it instead of a [ShellExecutor] because [ShellExecutor.asCoroutineDispatcher] will
38  * create a [CoroutineDispatcher] whose [CoroutineDispatcher.isDispatchNeeded] is effectively never
39  * dispatching. This is because even if dispatched, the backing [ShellExecutor.execute] always runs
40  * the [Runnable] immediately if called from the same thread, whereas
41  * [Handler.asCoroutineDispatcher] will create a [MainCoroutineDispatcher] that correctly
42  * dispatches (queues) when [CoroutineDispatcher.isDispatchNeeded] is true using [Handler.post].
43  * For callers that do need a non-dispatching version, [MainCoroutineDispatcher.immediate] is
44  * available.
45  */
46 @Module
47 class WMShellCoroutinesModule {
48   @Provides
49   @ShellMainThread
provideMainDispatchernull50   fun provideMainDispatcher(
51     @ShellMainThread mainHandler: Handler
52   ): MainCoroutineDispatcher = mainHandler.asCoroutineDispatcher()
53 
54   @Provides
55   @ShellBackgroundThread
56   fun provideBackgroundDispatcher(
57       @ShellBackgroundThread backgroundHandler: Handler
58   ): MainCoroutineDispatcher = backgroundHandler.asCoroutineDispatcher()
59 
60   @Provides
61   @WMSingleton
62   @ShellMainThread
63   fun provideApplicationScope(
64       @ShellMainThread applicationDispatcher: MainCoroutineDispatcher,
65   ): CoroutineScope = CoroutineScope(applicationDispatcher)
66 
67   @Provides
68   @WMSingleton
69   @ShellBackgroundThread
70   fun provideBackgroundCoroutineScope(
71       @ShellBackgroundThread backgroundDispatcher: MainCoroutineDispatcher,
72   ): CoroutineScope = CoroutineScope(backgroundDispatcher)
73 
74   @Provides
75   @WMSingleton
76   @ShellBackgroundThread
77   fun provideBackgroundCoroutineContext(
78       @ShellBackgroundThread backgroundDispatcher: MainCoroutineDispatcher
79   ): CoroutineContext = backgroundDispatcher + SupervisorJob()
80 }
81