• 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 package com.android.systemui.util.concurrency
17 
18 import android.os.Handler
19 import android.os.HandlerThread
20 import android.os.Looper
21 import android.os.Process
22 import android.view.Choreographer
23 import com.android.systemui.Dependency
24 import com.android.systemui.Flags
25 import com.android.systemui.dagger.SysUISingleton
26 import com.android.systemui.dagger.qualifiers.Background
27 import com.android.systemui.dagger.qualifiers.BroadcastRunning
28 import com.android.systemui.dagger.qualifiers.LongRunning
29 import com.android.systemui.dagger.qualifiers.Main
30 import com.android.systemui.dagger.qualifiers.NotifInflation
31 import dagger.Module
32 import dagger.Provides
33 import java.util.concurrent.Executor
34 import javax.inject.Named
35 import javax.inject.Qualifier
36 
37 @Qualifier
38 @MustBeDocumented
39 @Retention(AnnotationRetention.RUNTIME)
40 annotation class BackPanelUiThread
41 
42 /** Dagger Module for classes found within the concurrent package. */
43 @Module
44 object SysUIConcurrencyModule {
45     // Slow BG executor can potentially affect UI if UI is waiting for an updated state from this
46     // thread
47     private const val BG_SLOW_DISPATCH_THRESHOLD = 1000L
48     private const val BG_SLOW_DELIVERY_THRESHOLD = 1000L
49     private const val LONG_SLOW_DISPATCH_THRESHOLD = 2500L
50     private const val LONG_SLOW_DELIVERY_THRESHOLD = 2500L
51     private const val BROADCAST_SLOW_DISPATCH_THRESHOLD = 1000L
52     private const val BROADCAST_SLOW_DELIVERY_THRESHOLD = 1000L
53     private const val NOTIFICATION_INFLATION_SLOW_DISPATCH_THRESHOLD = 1000L
54     private const val NOTIFICATION_INFLATION_SLOW_DELIVERY_THRESHOLD = 1000L
55 
56     /**
57      * Choreographer instance for the main thread.
58      * TODO(b/395887935): Lets move this to @Main and provide thread-local references
59      */
60     @Provides
61     @SysUISingleton
providesChoreographernull62     fun providesChoreographer(): Choreographer = Choreographer.getInstance()
63 
64     /** Background Looper */
65     @Provides
66     @SysUISingleton
67     @Background
68     fun provideBgLooper(): Looper {
69         val thread = HandlerThread("SysUiBg", Process.THREAD_PRIORITY_BACKGROUND)
70         thread.start()
71         thread
72             .getLooper()
73             .setSlowLogThresholdMs(BG_SLOW_DISPATCH_THRESHOLD, BG_SLOW_DELIVERY_THRESHOLD)
74         return thread.getLooper()
75     }
76 
77     /** BroadcastRunning Looper (for sending and receiving broadcasts) */
78     @Provides
79     @SysUISingleton
80     @BroadcastRunning
provideBroadcastRunningLoopernull81     fun provideBroadcastRunningLooper(): Looper {
82         val thread = HandlerThread("BroadcastRunning", Process.THREAD_PRIORITY_BACKGROUND)
83         thread.start()
84         thread
85             .getLooper()
86             .setSlowLogThresholdMs(
87                 BROADCAST_SLOW_DISPATCH_THRESHOLD,
88                 BROADCAST_SLOW_DELIVERY_THRESHOLD
89             )
90         return thread.getLooper()
91     }
92 
93     /** Long running tasks Looper */
94     @Provides
95     @SysUISingleton
96     @LongRunning
provideLongRunningLoopernull97     fun provideLongRunningLooper(): Looper {
98         val thread = HandlerThread("SysUiLng", Process.THREAD_PRIORITY_BACKGROUND)
99         thread.start()
100         thread
101             .getLooper()
102             .setSlowLogThresholdMs(LONG_SLOW_DISPATCH_THRESHOLD, LONG_SLOW_DELIVERY_THRESHOLD)
103         return thread.getLooper()
104     }
105 
106     /** Notification inflation Looper */
107     @Provides
108     @SysUISingleton
109     @NotifInflation
provideNotifInflationLoopernull110     fun provideNotifInflationLooper(): Looper {
111         val thread = HandlerThread("NotifInflation", Process.THREAD_PRIORITY_BACKGROUND)
112         thread.start()
113         val looper = thread.getLooper()
114         looper.setSlowLogThresholdMs(
115             NOTIFICATION_INFLATION_SLOW_DISPATCH_THRESHOLD,
116             NOTIFICATION_INFLATION_SLOW_DELIVERY_THRESHOLD
117         )
118         return looper
119     }
120 
121     @Provides
122     @SysUISingleton
123     @BackPanelUiThread
provideBackPanelUiThreadContextnull124     fun provideBackPanelUiThreadContext(
125         @Main mainLooper: Looper,
126         @Main mainHandler: Handler,
127         @Main mainExecutor: Executor
128     ): UiThreadContext {
129         return if (Flags.edgeBackGestureHandlerThread()) {
130             val thread =
131                 HandlerThread("BackPanelUiThread", Process.THREAD_PRIORITY_DISPLAY).apply {
132                     start()
133                     looper.setSlowLogThresholdMs(
134                         LONG_SLOW_DISPATCH_THRESHOLD,
135                         LONG_SLOW_DELIVERY_THRESHOLD
136                     )
137                 }
138             UiThreadContext(
139                 thread.looper,
140                 thread.threadHandler,
141                 thread.threadExecutor,
142                 thread.threadHandler.runWithScissors { Choreographer.getInstance() }
143             )
144         } else {
145             UiThreadContext(
146                 mainLooper,
147                 mainHandler,
148                 mainExecutor,
149                 mainHandler.runWithScissors { Choreographer.getInstance() }
150             )
151         }
152     }
153 
154     /**
155      * Background Handler.
156      *
157      * Prefer the Background Executor when possible.
158      */
159     @Provides
160     @Background
provideBgHandlernull161     fun provideBgHandler(@Background bgLooper: Looper): Handler = Handler(bgLooper)
162 
163     /** Provide a BroadcastRunning Executor (for sending and receiving broadcasts). */
164     @Provides
165     @SysUISingleton
166     @BroadcastRunning
167     fun provideBroadcastRunningExecutor(@BroadcastRunning looper: Looper): Executor =
168         ExecutorImpl(looper)
169 
170     /** Provide a Long running Executor. */
171     @Provides
172     @SysUISingleton
173     @LongRunning
174     fun provideLongRunningExecutor(@LongRunning looper: Looper): Executor = ExecutorImpl(looper)
175 
176     /** Provide a Long running Executor. */
177     @Provides
178     @SysUISingleton
179     @LongRunning
180     fun provideLongRunningDelayableExecutor(@LongRunning looper: Looper): DelayableExecutor =
181         ExecutorImpl(looper)
182 
183     /** Provide a Background-Thread Executor. */
184     @Provides
185     @SysUISingleton
186     @Background
187     fun provideBackgroundExecutor(@Background looper: Looper): Executor = ExecutorImpl(looper)
188 
189     /** Provide a Background-Thread Executor. */
190     @Provides
191     @SysUISingleton
192     @Background
193     fun provideBackgroundDelayableExecutor(@Background looper: Looper): DelayableExecutor =
194         ExecutorImpl(looper)
195 
196     /** Provide a Background-Thread Executor. */
197     @Provides
198     @SysUISingleton
199     @Background
200     fun provideBackgroundRepeatableExecutor(
201         @Background exec: DelayableExecutor
202     ): RepeatableExecutor = RepeatableExecutorImpl(exec)
203 
204     /** Provide a Main-Thread Executor. */
205     @Provides
206     @SysUISingleton
207     @Main
208     fun provideMainRepeatableExecutor(@Main exec: DelayableExecutor): RepeatableExecutor =
209         RepeatableExecutorImpl(exec)
210 
211     /**  */
212     @Provides
213     @Main
214     fun providesMainMessageRouter(@Main executor: DelayableExecutor): MessageRouter =
215         MessageRouterImpl(executor)
216 
217     /**  */
218     @Provides
219     @Background
220     fun providesBackgroundMessageRouter(@Background executor: DelayableExecutor): MessageRouter =
221         MessageRouterImpl(executor)
222 
223     /**  */
224     @Provides
225     @SysUISingleton
226     @Named(Dependency.TIME_TICK_HANDLER_NAME)
227     fun provideTimeTickHandler(): Handler {
228         val thread = HandlerThread("TimeTick")
229         thread.start()
230         return Handler(thread.getLooper())
231     }
232 
233     /**  */
234     @Provides
235     @SysUISingleton
236     @NotifInflation
provideNotifInflationExecutornull237     fun provideNotifInflationExecutor(@NotifInflation looper: Looper): Executor =
238         ExecutorImpl(looper)
239 }
240