Categories
Uncategorized

[Sound systems] SystemUI articles (a) SystemUI boot process Detailed

Foreword

Please reprint the statement, carried https://www.cnblogs.com/andy-songwei/p/11471355.html [], thank you!

SystemUI system startup is the first application user visible, its all-inclusive features, such as the boot after seeing the lock screen, charging charging interface, status bar, navigation bar, multi-tasking bar, are with the Android mobile phone users closely related functions. So more than SystemUI developers, common application developers is also necessary to find out SystemUI. This series of articles will be based on Android P and Android Q to introduce various aspects of SystemUI herein, this as the first of this series of articles, we introduce the SystemUI the startup process, as well as major profiles.

The main contents are as follows:

 

 

A, SystemUI Profile

SystemUI, as the name suggests is a system-level information system to provide users with a set of UI components interact with the display, so its function all-inclusive. Such as lock screen, status bar, navigation bar at the bottom, such as a list of recently used App, most of the functions are independent, on-demand start, the text will continue to list more. In the system source code, its location is: frameworks / base / package / SystemUI. Although performance formal point of view, SystemUI and general Android APP have a greater difference, but its nature and general APP did not make any difference, but also in the form of apk, as shown below:

 

The current test machine, for example, that it is preset in the system specified directory. Also through the four major components of the Android in the Activity, Service, BroadcastReceiver to accept the request of the outside world and perform related operations, but they accepted requests from all major system services only.

 

Two, Lambda Expressions Introduction

For the latter there is a process used in the Lambda expressions, in order to facilitate the later explanation, here we briefly explain it, and simple demonstration of its use, not to explore in depth here, are interested can study on their own.

Lambda expressions is an anonymous function, that function is not a function name, is based on the mathematics of λ calculus named. In java, as introduced java8, use it to design code will be more concise. Two examples in the Android project to an intuitive feel for the Lambda syntax.

The following is a very common example set click event, take a look at the case when not Lambda Expressions:

1 mTextView.setOnClickListener(new View.OnClickListener() {
2     @Override
3     public void onClick(View v) {
4         Log.i("songzheweiwang", "test lambda");
5     }
6 });

After adopting Lambda expressions, this is the case:

1 mTextView.setOnClickListener(onClickListener -> {
2             Log.i("songzheweiwang", "test lambda");
3     });

Wherein “onClickListener” is a random string taken, when we named it easier to identify. Seen a lot of the entire code is simple, it is also very easy to read.

Also look at a more obvious example, when not in use Lambda expressions like this:

1 Runnable runnable = new Runnable() {
2     @Override
3     public void run() {
4         Log.i("songzheweiwang", "test lambda");
5     }
6 };

After using Lambda expressions, it would be this:

1 Runnable runnable2 = () -> Log.i("songzheweiwang", "test lambda");

As the “->” symbol can be read as “go to”. Lambda expressions instead of using an anonymous inner class is indeed very convenient, but when used to note the version number of java, said earlier, is in java8 was introduced, or at compile time error will be reported as follows:

As the contents of reference [Lambda expressions _ Baidu Encyclopedia]

 

Three, SystemUI start timing

In the wind and waves [[]] Android system startup articles, I introduced the general flow of the Android system, talked about the process of starting SystemServer in step 6. When SystemServer process starts, execute the following code:

 1 //=========SystemServer.java=========
 2 public static void main(String[] args) {
 3     new SystemServer().run();
 4 }
 5 private void run() {
 6     ......
 7     //

Create a message Looper

8 Looper.prepareMainLooper(); 9 //

Dynamic load library libandroid_servers.so, initialization native service

10 System.loadLibrary("android_servers"); 11 ...... 12 //

Initializing the system context

13 createSystemContext(); 14 //

Creating SystemServiceManager

15 mSystemServiceManager = new SystemServiceManager(mSystemContext); 16 ...... 17 //

Boot services, such as AMS, etc.

18 startBootstrapServices(); 19 //

Start core services

20 startCoreServices(); 21 //

Start other services, such as WMS, SystemUI etc.

22 startOtherServices(); 23 .... 24 }

After the first 18, 20 lines of code execution finished, it will boot service and a number of core services, such as AMS, etc., then line 22 will start other services, SystemUI on one of them.

 1 //======SystemServer.java======
 2 private void startOtherServices() {
 3         ......
 4         // We now tell the activity manager it is okay to run third party
 5         // code.  It will call back into us once it has gotten to the state
 6         // where third party code can really run (but before it has actually
 7         // started launching the initial applications), for us to complete our
 8         // initialization.
 9         mActivityManagerService.systemReady(() -> {
10             ......
11             traceBeginAndSlog("StartSystemUI");
12             try {
13                 startSystemUi(context, windowManagerF);
14             } catch (Throwable e) {
15                 reportWtf("starting System UI", e);
16             }
17             traceEnd();
18             ......
19         }, BOOT_TIMINGS_TRACE_LOG);
20         ......
21 }

In line 9, said earlier AMS first started, mActivityManagerService call systemReady method here uses described earlier Lambda expressions, the source systemReady method are as follows:

1 public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
2       ......
3       if (goingCallback != null) {
4           goingCallback.run();
5       }
6       ......
7 }

Previously described herein with reference to use Lambda expressions is easy to understand, actually perform the callback Runnable only, here in fact is equivalent to the following code:

1 mActivityManagerService.systemReady(new Runnable(){
2    new Runnable() {
3         @Override
4         public void run() {
5            //

Lambda expressions callback code

6 } 7 } 8 },BOOT_TIMINGS_TRACE_LOG);

Lambda expressions has not actually introduced before, i.e. code is so early wording.

When everything is ready, the callback started, it started startSystemUI method on line 13 a. The source of the method are as follows:

1 static final void startSystemUi(Context context, WindowManagerService windowManager) {
2     Intent intent = new Intent();
3     intent.setComponent(new ComponentName("com.android.systemui",
4                 "com.android.systemui.SystemUIService"));
5     intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
6     //Slog.d(TAG, "Starting service: " + intent);
7     context.startServiceAsUser(intent, UserHandle.SYSTEM);
8     windowManager.onSystemUiStarted();
9 }

The third and fourth line gives the package and class names, so SystemUI started up. We can see from this code, SystemUI through the Service to start, but in the capacity of the system to start it.

 

Four, Service Analysis process starts

The section startSystemUI process started SystemUIService, Service startup process is more complex, do not do a detailed analysis here, and only a brief introduction in which this section is closely related to the key processes.

 

The caller of the StartSysteMUI method on line 7 of the previous section’s code looks like the context type, Context is an abstract class, the actual executor is the ContextimPL. The calling process jumps from the ContextimPL to AMS via Binder and then binder to the ScheduleReateService method in the internal class ApplicationThread in ActivityThread. In this method it will be sent to Handler H for processing. Ininstantiation of Handler H is the Looper of the main thread used, so its callback method HandLemEssage is executed in the main thread. At this point, the HandleCatereService method is called in the method.

 1 private void handleCreateService(CreateServiceData data) {
 2     ......
 3     Service service = null;
 4     try {
 5         ......
 6         service = packageInfo.getAppFactory()
 7                 .instantiateService(cl, data.info.name, data.intent);
 8     } catch (Exception e) {
 9         ......
10     }
11     try {
12         ......
13         ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
14         context.setOuterContext(service);
15         Application app = packageInfo.makeApplication(false, mInstrumentation);
16         service.attach(context, this, data.info.name, data.token, app,
17                 ActivityManager.getService());
18         service.onCreate();
19         ......
20     } catch (Exception e) {
21         ......
22     }
23 }

Line 6 creates an instance of the service, create a context, line 13, line 15 create the Application, the Application and wherein performing the onCreate method, line 18 is executed onCreate method of service. Here makeApplication Method 15 proceeds to row. The following intercepts the key code:

 1 public Application makeApplication(boolean forceDefaultAppClass,
 2         Instrumentation instrumentation) {
 3     ......
 4     Application app = null;
 5     String appClass = mApplicationInfo.className;
 6     if (forceDefaultAppClass || (appClass == null)) {
 7         appClass = "android.app.Application";
 8     }
 9     try {
10         ......
11         ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
12         app = mActivityThread.mInstrumentation.newApplication(
13                 cl, appClass, appContext);
14         appContext.setOuterContext(app);
15     } catch (Exception e) {
16         ......
17     }
18     mActivityThread.mAllApplications.add(app);
19     ......
20     if (instrumentation != null) {
21         try {
22             instrumentation.callApplicationOnCreate(app);
23         } catch (Exception e) {
24             ......
25         }
26     }
27     ......
28     return app;
29 }

Since the initial launch, it will come on line 7. newApplication source line 12 as follows:

1 public Application newApplication(ClassLoader cl, String className, Context context)
2             throws InstantiationException, IllegalAccessException, 
3             ClassNotFoundException {
4         Application app = getFactory(context.getPackageName())
5                 .instantiateApplication(cl, className);
6         app.attach(context);
7         return app;
8     }

Continue to track instantiateApplication method:

1 public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
2         @NonNull String className)
3         throws InstantiationException, IllegalAccessException, ClassNotFoundException {
4     return (Application) cl.loadClass(className).newInstance();
5 }

An instance of the Application is created in the form of a classloader. You can see that the role of the previous MakeApplication method line 12 is to create the Application instance, then go to line 22 of the method and go to the method:

1 public void callApplicationOnCreate(Application app) {
2     app.onCreate();
3 }

In this method, Application executes the onCreate method.

Service here generally start the process to understand, here we need to remember an executive order (because I read a lot of information is easy to make mistakes here, he said that the Application will first instantiate ratio Service, through this process we can see this kinds of argument is wrong, it is highlighted here):

(1) Example-Service;

(2) Examples of the Application;

(3) Application Examples onCreate method performed;

(4) Service instance to perform onCrate method.

 

Five, SystemUIApplication onCreate method of processing logic

On the one we analyzed, we will first perform the onCreate method of the Application of the onCreate method of execution Service, where the first analysis of the implementation logic SystemUIApplication in onCreate method.

 1 //============SystemUIApplication.java========
 2 private SystemUI[] mServices;
 3 @Override
 4 public void onCreate() {
 5     super.onCreate();
 6     ......
 7     //

Set Theme

8 setTheme(R.style.Theme_SystemUI); 9 ...... 10 if (Process.myUserHandle().equals(UserHandle.SYSTEM)) { 11 IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); 12 bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 13 registerReceiver(new BroadcastReceiver() { 14 @Override 15 public void onReceive(Context context, Intent intent) { 16 if (mBootCompleted) return; 17 18 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received"); 19 unregisterReceiver(this); 20 mBootCompleted = true; 21 if (mServicesStarted) { 22 final int N = mServices.length; 23 for (int i = 0; i < N; i++) { 24 mServices[i].onBootCompleted(); 25 } 26 } 27 } 28 }, bootCompletedFilter); 29 30 IntentFilter localeChangedFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED); 31 registerReceiver(new BroadcastReceiver() { 32 @Override 33 public void onReceive(Context context, Intent intent) { 34 if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) { 35 if (!mBootCompleted) return; 36 // Update names of SystemUi notification channels 37 NotificationChannels.createAll(context); 38 } 39 } 40 }, localeChangedFilter); 41 } else { 42 ...... 43 startSecondaryUserServicesIfNeeded(); 44 } 45 }

Here to talk about if-else logic line 9, we know that Linux is a multiuser operating system, so the if-else statement is to determine the system user, or switch to other users. SystemUI most of the features are the same for all users, only a small part of the function because different users is not the same performance, such as notifications, multi-tasking capabilities, etc., will be back here again talked about. If the users of the system will go if in the process, where registered two broadcast receiver for listening Intent.ACTION_BOOT_COMPLETED and Intent.ACTION_LOCALE_CHANGED.

Intent.Action_Boot_Completed is to listen to boot boot, analyze the Android9.0 system source code, the current system is using FBE encryption method (reader, please check the FBE encryption method, here do not detail), this way, to wait until the system boot and lock screen unlock, after entering the desktop During the journey, the system will send the broadcast, so the processing logic for receiving the broadcast is delayed. As you can see from lines 15 and 18, the broadcast will only be processed once, it will be anti-registered and will no longer be received. In this logic, lines 20 to 25, determine the MServicesStarts variable, which indicates whether SystemuiServer has been started, in fact, because the timing of the broadcast reception is delayed, will receive the broadcast after SystemuiServer has started, so the code will be executed at this time. The MService [] array on line 23 stores the SysteMUI subservices. When the whole system is started, each subservice will execute the OnBootComplete () method, let each subservice know that the system has been started. The assignment of MService [] and the SytemUI subservice it stores will be explained in detail in the next section. All we need to know is that this process takes place during the startup phase of SystemuiServer.

Intent.Action_Locale_Changed broadcast is a broadcast that listens when the device’s current locale has been changed, simply speaking when the language is modified (it is not known if other actions will also send the broadcast).

Line 42 is the case when the current user is not a system user, i.e. the scene after switching the user, the action occurs when the system is already started and the intent.Action_Boot_Completed broadcast will no longer be triggered. Here’s a look at how it executes:

1 void startSecondaryUserServicesIfNeeded() {
2     String[] names =
3               getResources().getStringArray(R.array.config_systemUIServiceComponentsPerUser);
4     startServicesIfNeeded(names);
5 }

Line 2 and line 4 are actually starting the function specified in the resource file, as follows:

1 <string-array name="config_systemUIServiceComponentsPerUser" translatable="false">
2     <item>com.android.systemui.Dependencyitem>
3     <item>com.android.systemui.util.NotificationChannelsitem>
4     <item>com.android.systemui.recents.Recentsitem>
5 string-array>

You can see that notifications (line 3) and multitasking (line 4) are included. These functions vary from user to user. In addition, we will find that in fact these several subservices, in the next section of Config_SystemuiervicoComposers array resources are also included, which corresponds to the earlier said, after switching to individual users these features will behave differently depending on the user and need to be reloaded. The processing logic of StartsecondaryUserServicesifNeeded method will be discussed in detail in the next section, here we just need to be clear about this piece of functionality.

 

6. OnCreate method processing logic in Systemuiervice

As mentioned above, SystemUI started by “com.android.systemui.SystemUIService” the service, the onCreate method of the Application of the implementation of the latter, it will perform its own onCreate method. Let’s look at SystemUIService startup process what had been done:

1 public class SystemUIService extends Service {
2    @Override
3    public void onCreate() {
4       super.onCreate();
5       ((SystemUIApplication) getApplication()).startServicesIfNeeded();
6        ......
7    }
8   ......
9 }

The key code for this class is the first 5 lines of code, there is no other important logic, continue to track startServicesIfNeeded () method:

1 //===========SystemUIApplication==========
2 public void startServicesIfNeeded() {
3       String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
4       startServicesIfNeeded(names);
5 }

Third line in the resource file corresponding array as shown below, each of which corresponds to a sub-service (this does not mean that they are Service, but rather a function module), in fact, Android O and previous versions these classes are stored in an array in the code.

 1 <string-array name="config_systemUIServiceComponents" translatable="false">
 2     <item>com.android.systemui.Dependencyitem>
 3     <item>com.android.systemui.util.NotificationChannelsitem>
 4     <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStartitem>
 5     <item>com.android.systemui.keyguard.KeyguardViewMediatoritem>
 6     <item>com.android.systemui.recents.Recentsitem>
 7     <item>com.android.systemui.volume.VolumeUIitem>
 8     <item>com.android.systemui.stackdivider.Divideritem>
 9     <item>com.android.systemui.SystemBarsitem>
10     <item>com.android.systemui.usb.StorageNotificationitem>
11     <item>com.android.systemui.power.PowerUIitem>
12     <item>com.android.systemui.media.RingtonePlayeritem>
13     <item>com.android.systemui.keyboard.KeyboardUIitem>
14     <item>com.android.systemui.pip.PipUIitem>
15     <item>com.android.systemui.shortcut.ShortcutKeyDispatcheritem>
16     <item>@string/config_systemUIVendorServiceComponentitem>
17     <item>com.android.systemui.util.leak.GarbageMonitor$Serviceitem>
18     <item>com.android.systemui.LatencyTesteritem>
19     <item>com.android.systemui.globalactions.GlobalActionsComponentitem>
20     <item>com.android.systemui.ScreenDecorationsitem>
21     <item>com.android.systemui.fingerprint.FingerprintDialogImplitem>
22     <item>com.android.systemui.SliceBroadcastRelayHandleritem>
23 string-array>

In line 21 Android Q on the modified order

1 <item>com.android.systemui.biometrics.BiometricDialogImplitem>

It is to change the fingerprint recognition biometrics features, beginning on the Android Q, in addition to fingerprint recognition, face recognition also increased. In addition, based on the original add the 3:

1 <item>com.android.systemui.SizeCompatModeActivityControlleritem>
2 <item>com.android.systemui.statusbar.notification.InstantAppNotifieritem>
3 <item>com.android.systemui.theme.ThemeOverlayControlleritem> 

After opening each of these categories, you will find that they are inherited from SystemUI class, SystemUI class is an abstract class that provides the following interfaces:

 1 public abstract class SystemUI implements SysUiServiceProvider {
 2     ......
 3     public abstract void start();
 4 
 5     protected void onConfigurationChanged(Configuration newConfig) {
 6     }
 7 
 8     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
 9     }
10 
11     protected void onBootCompleted() {
12     }
13     ......
14     }
15 }

startServicesIfNeeded (names) Method source as follows:

 1 private SystemUI[] mServices;
 2 private void startServicesIfNeeded(String[] services) {
 3     ......
 4     mServices = new SystemUI[services.length];
 5     ......
 6     final int N = services.length;
 7     for (int i = 0; i < N; i++) {
 8         String clsName = services[i];
 9         Class cls;
10         try {
11             cls = Class.forName(clsName);
12             mServices[i] = (SystemUI) cls.newInstance();
13         } catch (ClassNotFoundException ex) {
14             throw new RuntimeException(ex);
15         } catch (IllegalAccessException ex) {
16             throw new RuntimeException(ex);
17         } catch (InstantiationException ex) {
18             throw new RuntimeException(ex);
19         }
20         ......
21         mServices[i].mContext = this;
22         mServices[i].mComponents = mComponents;
23         ......
24         mServices[i].start();
25         ......
26         if (mBootCompleted) {
27             mServices[i].onBootCompleted();
28         }
29     }
30 }

is actually instantiating the preceding subservice classes by reflection, and executing the start () method in those objects to start the services. This way, even if the whole SysteMUI is started, the above logic is relatively simple.

We need to note that the use of a template pattern here. SystemUI is a base class, which defines four abstract or empty method as template specifies behavior subclass. Many sub-service resource class defined in the file are subclasses SystemUI, since SystemUI are inherited from class, then these subclasses have some common patterns of behavior that at some point there should be no performance, just exactly how performance varies subclasses vary. For example, in the above code, line 24 and line 27 respectively provide a method SystemUI subclasses are executed at startup Start (), the system starts to execute onBootCompleted () method, so in these subclasses are rewritten these two methods, to a certain stage will be to execute a callback way, but specifically what to do in these methods, subclass themselves have the final say. This is a typical pattern template to use, the specific introduction and use template pattern, do not start speaking here, readers can find information on their own, which uses the Android system is still very common, it is best to take the reader to grasp.

So far, the start-up process of SysteMUI has been introduced, and summarized here is the following stages:

(1) When the system is ready to start, the SystemServer process issues the command to start SystemuiServer;

SystemUiApplication (2) SystemUI onCreate method of execution, the registration system and regional settings to change start broadcasting broadcast.

(3) Execute the OnCreate method in SystemuiServer of SysteMUI, start the various services of public users, and perform the onStart () callback method for each subservice.

(4) the system starts, the second step of registration will receive broadcast system starts broadcasting, then each sub-service execution onBootCompleted () callback method.

(5) when switching users are personal, individualized sub-load services again.

 

Seven function module contains SystemUI

On a listed SystemUI sub-class service through an array of these classes are represented, respectively, what function do? Now I simply introduce a few of them, the reader can be condemnation by name. For a more detailed introduction, there is a special need, then will write an article to make an introduction.

(1) Status bars (status bar)

(2) Navigation bars (navigation bar)

(3) Notification (notification)

(4) Keyguard (lock screen)

(5) Quick settings (Quick Setup)

(6) Recent task panel (recently task pane)

(7) VolumeUI (volume UI)

(8) Screenshot (screenshot)

(9) PowerUI (electricity UI)

(10) RingtonePlayer (ringtone player)

(11) StackDivider (split screen)

(12) PipUI (PIP UI)

(13) Biometrics (biometric unlock features, such as fingerprint to unlock, face unlock, unlock iris, etc.)

  

Epilogue

SystemUI start the process described here, due speaks fairly detailed, so a lot of content and details involved, we will describe some inaccurate or wrong place, if found, the reader is taken under the wing. In addition, as space is limited, or in some places, or only mentioned briefly only, such as FBE encryption, template mode, Lambda expressions, etc., are often encountered in the normal development of the system, readers can continue to expand in-depth study.

Leave a Reply