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 /** Background Looper */ 57 @Provides 58 @SysUISingleton 59 @Background provideBgLoopernull60 fun provideBgLooper(): Looper { 61 val thread = HandlerThread("SysUiBg", Process.THREAD_PRIORITY_BACKGROUND) 62 thread.start() 63 thread 64 .getLooper() 65 .setSlowLogThresholdMs(BG_SLOW_DISPATCH_THRESHOLD, BG_SLOW_DELIVERY_THRESHOLD) 66 return thread.getLooper() 67 } 68 69 /** BroadcastRunning Looper (for sending and receiving broadcasts) */ 70 @Provides 71 @SysUISingleton 72 @BroadcastRunning provideBroadcastRunningLoopernull73 fun provideBroadcastRunningLooper(): Looper { 74 val thread = HandlerThread("BroadcastRunning", Process.THREAD_PRIORITY_BACKGROUND) 75 thread.start() 76 thread 77 .getLooper() 78 .setSlowLogThresholdMs( 79 BROADCAST_SLOW_DISPATCH_THRESHOLD, 80 BROADCAST_SLOW_DELIVERY_THRESHOLD 81 ) 82 return thread.getLooper() 83 } 84 85 /** Long running tasks Looper */ 86 @Provides 87 @SysUISingleton 88 @LongRunning provideLongRunningLoopernull89 fun provideLongRunningLooper(): Looper { 90 val thread = HandlerThread("SysUiLng", Process.THREAD_PRIORITY_BACKGROUND) 91 thread.start() 92 thread 93 .getLooper() 94 .setSlowLogThresholdMs(LONG_SLOW_DISPATCH_THRESHOLD, LONG_SLOW_DELIVERY_THRESHOLD) 95 return thread.getLooper() 96 } 97 98 /** Notification inflation Looper */ 99 @Provides 100 @SysUISingleton 101 @NotifInflation provideNotifInflationLoopernull102 fun provideNotifInflationLooper(@Background bgLooper: Looper): Looper { 103 if (!Flags.dedicatedNotifInflationThread()) { 104 return bgLooper 105 } 106 val thread = HandlerThread("NotifInflation", Process.THREAD_PRIORITY_BACKGROUND) 107 thread.start() 108 val looper = thread.getLooper() 109 looper.setSlowLogThresholdMs( 110 NOTIFICATION_INFLATION_SLOW_DISPATCH_THRESHOLD, 111 NOTIFICATION_INFLATION_SLOW_DELIVERY_THRESHOLD 112 ) 113 return looper 114 } 115 116 @Provides 117 @SysUISingleton 118 @BackPanelUiThread provideBackPanelUiThreadContextnull119 fun provideBackPanelUiThreadContext( 120 @Main mainLooper: Looper, 121 @Main mainHandler: Handler, 122 @Main mainExecutor: Executor 123 ): UiThreadContext { 124 return if (Flags.edgeBackGestureHandlerThread()) { 125 val thread = 126 HandlerThread("BackPanelUiThread", Process.THREAD_PRIORITY_DISPLAY).apply { 127 start() 128 looper.setSlowLogThresholdMs( 129 LONG_SLOW_DISPATCH_THRESHOLD, 130 LONG_SLOW_DELIVERY_THRESHOLD 131 ) 132 } 133 UiThreadContext( 134 thread.looper, 135 thread.threadHandler, 136 thread.threadExecutor, 137 thread.threadHandler.runWithScissors { Choreographer.getInstance() } 138 ) 139 } else { 140 UiThreadContext( 141 mainLooper, 142 mainHandler, 143 mainExecutor, 144 mainHandler.runWithScissors { Choreographer.getInstance() } 145 ) 146 } 147 } 148 149 /** 150 * Background Handler. 151 * 152 * Prefer the Background Executor when possible. 153 */ 154 @Provides 155 @Background provideBgHandlernull156 fun provideBgHandler(@Background bgLooper: Looper): Handler = Handler(bgLooper) 157 158 /** Provide a BroadcastRunning Executor (for sending and receiving broadcasts). */ 159 @Provides 160 @SysUISingleton 161 @BroadcastRunning 162 fun provideBroadcastRunningExecutor(@BroadcastRunning looper: Looper): Executor = 163 ExecutorImpl(looper) 164 165 /** Provide a Long running Executor. */ 166 @Provides 167 @SysUISingleton 168 @LongRunning 169 fun provideLongRunningExecutor(@LongRunning looper: Looper): Executor = ExecutorImpl(looper) 170 171 /** Provide a Long running Executor. */ 172 @Provides 173 @SysUISingleton 174 @LongRunning 175 fun provideLongRunningDelayableExecutor(@LongRunning looper: Looper): DelayableExecutor = 176 ExecutorImpl(looper) 177 178 /** Provide a Background-Thread Executor. */ 179 @Provides 180 @SysUISingleton 181 @Background 182 fun provideBackgroundExecutor(@Background looper: Looper): Executor = ExecutorImpl(looper) 183 184 /** Provide a Background-Thread Executor. */ 185 @Provides 186 @SysUISingleton 187 @Background 188 fun provideBackgroundDelayableExecutor(@Background looper: Looper): DelayableExecutor = 189 ExecutorImpl(looper) 190 191 /** Provide a Background-Thread Executor. */ 192 @Provides 193 @SysUISingleton 194 @Background 195 fun provideBackgroundRepeatableExecutor( 196 @Background exec: DelayableExecutor 197 ): RepeatableExecutor = RepeatableExecutorImpl(exec) 198 199 /** Provide a Main-Thread Executor. */ 200 @Provides 201 @SysUISingleton 202 @Main 203 fun provideMainRepeatableExecutor(@Main exec: DelayableExecutor): RepeatableExecutor = 204 RepeatableExecutorImpl(exec) 205 206 /** */ 207 @Provides 208 @Main 209 fun providesMainMessageRouter(@Main executor: DelayableExecutor): MessageRouter = 210 MessageRouterImpl(executor) 211 212 /** */ 213 @Provides 214 @Background 215 fun providesBackgroundMessageRouter(@Background executor: DelayableExecutor): MessageRouter = 216 MessageRouterImpl(executor) 217 218 /** */ 219 @Provides 220 @SysUISingleton 221 @Named(Dependency.TIME_TICK_HANDLER_NAME) 222 fun provideTimeTickHandler(): Handler { 223 val thread = HandlerThread("TimeTick") 224 thread.start() 225 return Handler(thread.getLooper()) 226 } 227 228 /** */ 229 @Provides 230 @SysUISingleton 231 @NotifInflation provideNotifInflationExecutornull232 fun provideNotifInflationExecutor(@NotifInflation looper: Looper): Executor = 233 ExecutorImpl(looper) 234 } 235