Android 狀態欄Statusbar的啓動與顯示信號欄的過程

啓動Statusbar並顯示信號欄圖標的過程

Systemserver在啓動系統服務的時候啓動了Systemui。

try {
    startSystemUi(context, windowManagerF);
} catch (Throwable e) {
    reportWtf("starting System UI", e);
}
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

@Override
public void onCreate() {
    super.onCreate();
    ((SystemUIApplication) getApplication()).startServicesIfNeeded();
}

接着使用反射的方式來啓動SystemUIFactory.

    public void startServicesIfNeeded() {
        startServicesIfNeeded(SERVICES);
    }

這裏的SERVICES對應的是靜態數組

    private final Class<?>[] SERVICES = new Class[] {
            Dependency.class,
            NotificationChannels.class,
            CommandQueue.CommandQueueStart.class,
            KeyguardViewMediator.class,
            Recents.class,
            VolumeUI.class,
            Divider.class,
            SystemBars.class,   /////////////狀態欄
            StorageNotification.class,
            PowerUI.class,
            RingtonePlayer.class,
            KeyboardUI.class,
            PipUI.class,
            ShortcutKeyDispatcher.class,
            VendorServices.class,
            GarbageMonitor.Service.class,
            LatencyTester.class,
            GlobalActionsComponent.class,
            RoundedCorners.class,
    };

startServicesIfNeeded

private void startServicesIfNeeded(Class<?>[] services) {
    ...
for (int i = 0; i < N; i++) {
    Class<?> cl = services[i];
    if (DEBUG) Log.d(TAG, "loading: " + cl);
    log.traceBegin("StartServices" + cl.getSimpleName());
    long ti = System.currentTimeMillis();
    try {

        Object newService = SystemUIFactory.getInstance().createInstance(cl);
        mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
    } catch (IllegalAccessException ex) {
        throw new RuntimeException(ex);
    } catch (InstantiationException ex) {
        throw new RuntimeException(ex);
    }

上面的newService返回的是null,所以會去調用SERVICES的類名去初始化。

其中SystemBars就是包含了頂部狀態欄Statusbar和底部導航欄Navigationbar。

SystemBars

public class SystemBars extends SystemUI
@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());
}

然後這裏也是使用反射的方式來啓動statusbar,

R.string.config_statusBarComponent對應的內容是

<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>

也就是說,到這裏纔是正式啓動StatusBar。

進入到StatusBar.start();

@Override
public void start() {
    ....
    createAndAddWindows();
    ....
}          

start裏做了很多其他初始化處理,但是最關鍵的是添加view和window的過程。

public void createAndAddWindows() {
    addStatusBarWindow();
}

private void addStatusBarWindow() {
    makeStatusBarView();
    mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
    mRemoteInputController = new RemoteInputController(mHeadsUpManager);
    mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
protected void makeStatusBarView() {
    final Context context = mContext;
    updateDisplaySize(); // populates mDisplayMetrics
    updateResources();
    updateTheme();

    inflateStatusBarWindow(context);
    ....
        FragmentHostManager.get(mStatusBarWindow)
        .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
            CollapsedStatusBarFragment statusBarFragment =
                (CollapsedStatusBarFragment) fragment;
            statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
            mStatusBarView = (PhoneStatusBarView) fragment.getView();
            mStatusBarView.setBar(this);
            mStatusBarView.setPanel(mNotificationPanel);
            mStatusBarView.setScrimController(mScrimController);
            mStatusBarView.setBouncerShowing(mBouncerShowing);
            setAreThereNotifications();
            checkBarModes();
            /// M: add for plmn display feature @{
            attachPlmnPlugin();
            ///@}
        }).getFragmentManager()
        .beginTransaction()
        .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
                 CollapsedStatusBarFragment.TAG)
        .commit();
    ....
        try {
            boolean showNav = mWindowManagerService.hasNavigationBar();
            if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
            if (showNav) {
                createNavigationBar();
            }
        } catch (RemoteException ex) {
            // no window manager? good luck with that
        }
    ....
}

makeStatusBarView裏有也有很多view的處理流程。後面還去判斷是否啓動NavigationBar。

其中有一段是把status_bar_container啓動了一個CollapsedStatusBarFragment。

status_bar_container這個view是顯示衆多statusbar view的地方。

CollapsedStatusBarFragment

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                         Bundle savedInstanceState) {
    return inflater.inflate(R.layout.status_bar, container, false);
}

這裏加載了statusbar的layout

R.layout.status_bar這個layout裝載了許多的view。

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    mStatusBar = (PhoneStatusBarView) view;
    mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
    mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
    carrierText = (CarrierText)mStatusBar.findViewById(R.id.system_carrier_text);
    mSignalClusterView = mStatusBar.findViewById(R.id.signal_cluster);
    // Default to showing until we know otherwise.
    showSystemIconArea(false);
    initEmergencyCryptkeeperText();
}

在onViewCreated裏則是幾個重要view的初始化。

分別有

mSystemIconArea用來顯示狀態欄左邊圖標的區域

carrierText用來顯示網絡供應商的名稱

mSignalClusterView則是用來顯示信號相關的信息


以上就是信號欄初始化的流程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章