• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.systemui.wmshell;
18 
19 import static android.os.Process.THREAD_PRIORITY_DISPLAY;
20 import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
21 
22 import android.animation.AnimationHandler;
23 import android.content.Context;
24 import android.os.Build;
25 import android.os.Handler;
26 import android.os.HandlerThread;
27 import android.os.Trace;
28 
29 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
30 import com.android.systemui.R;
31 import com.android.systemui.dagger.WMSingleton;
32 import com.android.systemui.dagger.qualifiers.Main;
33 import com.android.wm.shell.common.HandlerExecutor;
34 import com.android.wm.shell.common.ShellExecutor;
35 import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
36 import com.android.wm.shell.common.annotations.ShellAnimationThread;
37 import com.android.wm.shell.common.annotations.ShellMainThread;
38 import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
39 
40 import dagger.Module;
41 import dagger.Provides;
42 
43 /**
44  * Provides basic concurrency-related dependencies from {@link com.android.wm.shell}, these
45  * dependencies are only accessible from components within the WM subcomponent.
46  */
47 @Module
48 public abstract class WMShellConcurrencyModule {
49 
50     private static final int MSGQ_SLOW_DELIVERY_THRESHOLD_MS = 30;
51     private static final int MSGQ_SLOW_DISPATCH_THRESHOLD_MS = 30;
52 
53     /**
54      * Returns whether to enable a separate shell thread for the shell features.
55      */
enableShellMainThread(Context context)56     private static boolean enableShellMainThread(Context context) {
57         return context.getResources().getBoolean(R.bool.config_enableShellMainThread);
58     }
59 
60     //
61     // Shell Concurrency - Components used for managing threading in the Shell and SysUI
62     //
63 
64     /**
65      * Provide a SysUI main-thread Executor.
66      */
67     @WMSingleton
68     @Provides
69     @Main
provideSysUIMainExecutor(@ain Handler sysuiMainHandler)70     public static ShellExecutor provideSysUIMainExecutor(@Main Handler sysuiMainHandler) {
71         return new HandlerExecutor(sysuiMainHandler);
72     }
73 
74     /**
75      * Shell main-thread Handler, don't use this unless really necessary (ie. need to dedupe
76      * multiple types of messages, etc.)
77      */
78     @WMSingleton
79     @Provides
80     @ShellMainThread
provideShellMainHandler(Context context, @Main Handler sysuiMainHandler)81     public static Handler provideShellMainHandler(Context context, @Main Handler sysuiMainHandler) {
82         if (enableShellMainThread(context)) {
83              HandlerThread mainThread = new HandlerThread("wmshell.main", THREAD_PRIORITY_DISPLAY);
84              mainThread.start();
85              if (Build.IS_DEBUGGABLE) {
86                  mainThread.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
87                  mainThread.getLooper().setSlowLogThresholdMs(MSGQ_SLOW_DISPATCH_THRESHOLD_MS,
88                          MSGQ_SLOW_DELIVERY_THRESHOLD_MS);
89              }
90              return Handler.createAsync(mainThread.getLooper());
91         }
92         return sysuiMainHandler;
93     }
94 
95     /**
96      * Provide a Shell main-thread Executor.
97      */
98     @WMSingleton
99     @Provides
100     @ShellMainThread
provideShellMainExecutor(Context context, @ShellMainThread Handler mainHandler, @Main ShellExecutor sysuiMainExecutor)101     public static ShellExecutor provideShellMainExecutor(Context context,
102             @ShellMainThread Handler mainHandler, @Main ShellExecutor sysuiMainExecutor) {
103         if (enableShellMainThread(context)) {
104             return new HandlerExecutor(mainHandler);
105         }
106         return sysuiMainExecutor;
107     }
108 
109     /**
110      * Provide a Shell animation-thread Executor.
111      */
112     @WMSingleton
113     @Provides
114     @ShellAnimationThread
provideShellAnimationExecutor()115     public static ShellExecutor provideShellAnimationExecutor() {
116          HandlerThread shellAnimationThread = new HandlerThread("wmshell.anim",
117                  THREAD_PRIORITY_DISPLAY);
118          shellAnimationThread.start();
119         if (Build.IS_DEBUGGABLE) {
120             shellAnimationThread.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
121             shellAnimationThread.getLooper().setSlowLogThresholdMs(MSGQ_SLOW_DISPATCH_THRESHOLD_MS,
122                     MSGQ_SLOW_DELIVERY_THRESHOLD_MS);
123         }
124          return new HandlerExecutor(Handler.createAsync(shellAnimationThread.getLooper()));
125     }
126 
127     /**
128      * Provides a Shell splashscreen-thread Executor
129      */
130     @WMSingleton
131     @Provides
132     @ShellSplashscreenThread
provideSplashScreenExecutor()133     public static ShellExecutor provideSplashScreenExecutor() {
134         HandlerThread shellSplashscreenThread = new HandlerThread("wmshell.splashscreen",
135                 THREAD_PRIORITY_TOP_APP_BOOST);
136         shellSplashscreenThread.start();
137         return new HandlerExecutor(shellSplashscreenThread.getThreadHandler());
138     }
139 
140     /**
141      * Provide a Shell main-thread AnimationHandler.  The AnimationHandler can be set on
142      * {@link android.animation.ValueAnimator}s and will ensure that the animation will run on
143      * the Shell main-thread with the SF vsync.
144      */
145     @WMSingleton
146     @Provides
147     @ChoreographerSfVsync
provideShellMainExecutorSfVsyncAnimationHandler( @hellMainThread ShellExecutor mainExecutor)148     public static AnimationHandler provideShellMainExecutorSfVsyncAnimationHandler(
149             @ShellMainThread ShellExecutor mainExecutor) {
150         try {
151             AnimationHandler handler = new AnimationHandler();
152             mainExecutor.executeBlocking(() -> {
153                 // This is called on the animation thread since it calls
154                 // Choreographer.getSfInstance() which returns a thread-local Choreographer instance
155                 // that uses the SF vsync
156                 handler.setProvider(new SfVsyncFrameCallbackProvider());
157             });
158             return handler;
159         } catch (InterruptedException e) {
160             throw new RuntimeException("Failed to initialize SfVsync animation handler in 1s", e);
161         }
162     }
163 }
164