• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.sysui;
18 
19 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_INIT;
20 
21 import android.os.Build;
22 import android.os.SystemClock;
23 import android.util.Pair;
24 import android.view.SurfaceControl;
25 
26 import androidx.annotation.VisibleForTesting;
27 
28 import com.android.internal.protolog.ProtoLog;
29 import com.android.wm.shell.common.ShellExecutor;
30 import com.android.wm.shell.protolog.ShellProtoLogGroup;
31 
32 import java.util.ArrayList;
33 
34 /**
35  * The entry point implementation into the shell for initializing shell internal state.  Classes
36  * which need to initialize on start of the host SysUI should inject an instance of this class and
37  * add an init callback.
38  */
39 public class ShellInit {
40     private static final String TAG = ShellInit.class.getSimpleName();
41 
42     private final ShellExecutor mMainExecutor;
43 
44     // An ordered list of init callbacks to be made once shell is first started
45     private final ArrayList<Pair<String, Runnable>> mInitCallbacks = new ArrayList<>();
46     private boolean mHasInitialized;
47 
48 
ShellInit(ShellExecutor mainExecutor)49     public ShellInit(ShellExecutor mainExecutor) {
50         mMainExecutor = mainExecutor;
51         ProtoLog.init(ShellProtoLogGroup.values());
52     }
53 
54     /**
55      * Adds a callback to the ordered list of callbacks be made when Shell is first started.  This
56      * can be used in class constructors when dagger is used to ensure that the initialization order
57      * matches the dependency order.
58      *
59      * @param r the callback to be made when Shell is initialized
60      * @param instance used for debugging only
61      */
addInitCallback(Runnable r, T instance)62     public <T extends Object> void addInitCallback(Runnable r, T instance) {
63         if (mHasInitialized) {
64             if (Build.isDebuggable()) {
65                 // All callbacks must be added prior to the Shell being initialized
66                 throw new IllegalArgumentException("Can not add callback after init");
67             }
68             return;
69         }
70         final String className = instance.getClass().getSimpleName();
71         mInitCallbacks.add(new Pair<>(className, r));
72         ProtoLog.v(WM_SHELL_INIT, "Adding init callback for %s", className);
73     }
74 
75     /**
76      * Calls all the init callbacks when the Shell is first starting.
77      */
78     @VisibleForTesting
init()79     public void init() {
80         ProtoLog.v(WM_SHELL_INIT, "Initializing Shell Components: %d", mInitCallbacks.size());
81         SurfaceControl.setDebugUsageAfterRelease(true);
82         // Init in order of registration
83         for (int i = 0; i < mInitCallbacks.size(); i++) {
84             final Pair<String, Runnable> info = mInitCallbacks.get(i);
85             final long t1 = SystemClock.uptimeMillis();
86             info.second.run();
87             final long t2 = SystemClock.uptimeMillis();
88             ProtoLog.v(WM_SHELL_INIT, "\t%s init took %dms", info.first, (t2 - t1));
89         }
90         mInitCallbacks.clear();
91         mHasInitialized = true;
92     }
93 }
94