StatusBar Loading Process of Android P System UI

Keywords: Android Java xml Windows

Related source code:
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\StatusBar.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\StatusBarWindowManager.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\StatusBarWindowView.java
\frameworks\base\services\java\com\android\server\SystemServer.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\SystemUIService.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\SystemUIApplication.java
\frameworks\base\packages\SystemUI\src\com\android\systemui\SystemBars.java

SystemServer.java

\frameworks\base\services\java\com\android\server\SystemServer.java
In the Zeyote process startup, we said that after Zeyote starts, it will execute System Server and start System UI Service in System Server.

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

SystemUIService.java

System UI Service initializes a series of components of System UI.

@Override
public void onCreate() {
    super.onCreate();
    ((SystemUIApplication) getApplication()).startServicesIfNeeded();
    //A part of the code has been omitted
    //...
}

SystemUIApplication.java

Initialize the components in config_system UIService Components:

public void startServicesIfNeeded() {
    String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
    startServicesIfNeeded(names);
}

Source: frameworks base packages SystemUI res values config. XML
Definition of config_system UI Service Components:

<!-- SystemUI Services: The classes of the stuff to start. -->
<string-array name="config_systemUIServiceComponents" translatable="false">
    <item>com.android.systemui.Dependency</item>
    <item>com.android.systemui.util.NotificationChannels</item>
    <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
    <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
    <item>com.android.systemui.recents.Recents</item>
    <item>com.android.systemui.volume.VolumeUI</item>
    <item>com.android.systemui.stackdivider.Divider</item>
    <item>com.android.systemui.SystemBars</item>		//Start status bar and navigation bar
    <item>com.android.systemui.usb.StorageNotification</item>
    <item>com.android.systemui.power.PowerUI</item>
    <item>com.android.systemui.media.RingtonePlayer</item>
    <item>com.android.systemui.keyboard.KeyboardUI</item>
    <item>com.android.systemui.pip.PipUI</item>
    <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
    <item>@string/config_systemUIVendorServiceComponent</item>
    <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
    <item>com.android.systemui.LatencyTester</item>
    <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
    <item>com.android.systemui.ScreenDecorations</item>
    <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
    <item>com.android.systemui.SliceBroadcastRelayHandler</item>
</string-array>

This includes SystemBars, SystemBar includes StatusBar and Navigation Bar.

private void startServicesIfNeeded(String[] services) {
    //A part of the code has been omitted
    //...
        log.traceBegin("StartServices");
        final int N = services.length;
        for (int i = 0; i < N; i++) {
            String clsName = services[i];
            if (DEBUG) Log.d(TAG, "loading: " + clsName);
            log.traceBegin("StartServices" + clsName);
            long ti = System.currentTimeMillis();
            Class cls;
            try {
                cls = Class.forName(clsName);
                mServices[i] = (SystemUI) cls.newInstance();
            } catch(ClassNotFoundException ex){
                throw new RuntimeException(ex);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InstantiationException ex) {
                throw new RuntimeException(ex);
            }

            mServices[i].mContext = this;
            mServices[i].mComponents = mComponents;
            if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
            mServices[i].start();
            log.traceEnd();

            // Warn if initialization of component takes too long
            ti = System.currentTimeMillis() - ti;
            if (ti > 1000) {
                Log.w(TAG, "Initialization of " + cls.getName() + " took " + ti + " ms");
            }
            if (mBootCompleted) {
                mServices[i].onBootCompleted();
            }
        }
        log.traceEnd();
    //A part of the code has been omitted
    //...
}

Key points: mServices[i].start(); start each service in config_system UIService Components in turn.

Regarding the status bar and navigation bar, we mainly focus on System Bar.

SystemBars.java

@Override
public void start() {
    if (DEBUG) Log.d(TAG, "start");
    createStatusBarFromConfig();
}

private void createStatusBarFromConfig() {
    if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
    final String clsName = mContext.getString(R.string.config_statusBarComponent);
    if (clsName == null || clsName.length() == 0) {
        throw andLog("No status bar component configured", null);
    }
    Class<?> cls = null;
    try {
        cls = mContext.getClassLoader().loadClass(clsName);
    } catch (Throwable t) {
        throw andLog("Error loading status bar component: " + clsName, t);
    }
    try {
        mStatusBar = (SystemUI) cls.newInstance();
    } catch (Throwable t) {
        throw andLog("Error creating status bar component: " + clsName, t);
    }
    mStatusBar.mContext = mContext;
    mStatusBar.mComponents = mComponents;
    mStatusBar.start();
    if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}

Decide to load the StatusBar object according to the config_statusBarComponent configuration.
Source: frameworks base packages SystemUI res values config. XML
Definition of config_status BarComponent:

<!-- Component to be used as the status bar service.  Must implement the IStatusBar
 interface.  This name is in the ComponentName flattened format (package/class)  -->
<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>

So, start() in StatusBar is executed to perform a series of StatusBar loads.

StatusBar.java

1. Load super_status_bar.xml

protected StatusBarWindowView mStatusBarWindow;
protected void inflateStatusBarWindow(Context context) {
    mStatusBarWindow = (StatusBarWindowView) View.inflate(context,R.layout.super_status_bar, null);
}

2. Create mStatusBarWindow
Key points: mStatusBar Windows Manager. add (mStatusBarWindow, getStatusBarHeight ());

private void addStatusBarWindow() {
    makeStatusBarView();
    mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
    mRemoteInputManager.setUpWithPresenter(this, mEntryManager, this,
            new RemoteInputController.Delegate() {
                public void setRemoteInputActive(NotificationData.Entry entry,
                        boolean remoteInputActive) {
                    mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive);
                    entry.row.notifyHeightChanged(true /* needsAnimation */);
                    updateFooter();
                }
                public void lockScrollTo(NotificationData.Entry entry) {
                    mStackScroller.lockScrollTo(entry.row);
                }
                public void requestDisallowLongPressAndDismiss() {
                    mStackScroller.requestDisallowLongPress();
                    mStackScroller.requestDisallowDismiss();
                }
            });
    mRemoteInputManager.getController().addCallback(mStatusBarWindowManager);
    mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}

3. Add the status bar view to the window manager
In StatusBar Windows Manager. java:

public void add(View statusBarView, int barHeight) {

    // Now that the status bar window encompasses the sliding panel and its
    // translucent backdrop, the entire thing is made TRANSLUCENT and is
    // hardware-accelerated.
    mLp = new WindowManager.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            barHeight,
            WindowManager.LayoutParams.TYPE_STATUS_BAR,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                    | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
            PixelFormat.TRANSLUCENT);
    mLp.token = new Binder();
    mLp.gravity = Gravity.TOP;
    mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
    mLp.setTitle("StatusBar");
    mLp.packageName = mContext.getPackageName();
    mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
    mStatusBarView = statusBarView;
    mBarHeight = barHeight;
    mWindowManager.addView(mStatusBarView, mLp);
    mLpChanged = new WindowManager.LayoutParams();
    mLpChanged.copyFrom(mLp);
}

Posted by luketheduck on Wed, 02 Oct 2019 08:15:10 -0700