android 6.0 SystemUI源码分析(4)-StatusBar显示流程

1.StatusBar启动

StatusBar继承于SystemUI,在SystemUIApplication会启动SysteBar.

mServices[i].start();

SystemBar.java

 @Override
    public void start() {
        if (DEBUG) Log.d(TAG, "start");
        mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
                mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
        mServiceMonitor.start();  // will call onNoService if no remote service is found
    }

在start函数会实例化ServiceMonitor以及start ServieMonitor。

ServiceMonitor.java

  public void start() {
        // listen for setting changes
        ContentResolver cr = mContext.getContentResolver();
        cr.registerContentObserver(Settings.Secure.getUriFor(mSettingKey),
                false /*notifyForDescendents*/, mSettingObserver, UserHandle.USER_ALL);

        // listen for package/component changes
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        filter.addDataScheme("package");
        mContext.registerReceiver(mBroadcastReceiver, filter);

        mHandler.sendEmptyMessage(MSG_START_SERVICE);
    }

这个函数主要做两件事情: 1)监听apk的安装卸载,即apk变化事件 2)发送MSG_START_SERVICE,启动service

ServiceMonitor.java

 private void startService() {
        mServiceName = getComponentNameFromSetting();
        if (mDebug) Log.d(mTag, "startService mServiceName=" + mServiceName);
        if (mServiceName == null) {
            mBound = false;
            mCallbacks.onNoService();
        } else {
            long delay = mCallbacks.onServiceStartAttempt();
            mHandler.sendEmptyMessageDelayed(MSG_CONTINUE_START_SERVICE, delay);
        }
    }

当ServiceName为NULL时,会call到callbacks的onNoService函数。 不等于NULL,在下面的Handler消息也会call到callBacks的onNoService函数。

从SystemBars.java的继承关系可以看到: public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks

最终会call到SystemBars.java的onNoService函数

SystemBars.java

 @Override
    public void onNoService() {
        if (DEBUG) Log.d(TAG, "onNoService");
        createStatusBarFromConfig();  // fallback to using an in-process implementation
    }

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 = (BaseStatusBar) 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());
    }

会call到BaseStatusBar的start函数

BaseStatusBars.java public void start() { … //各种实例化和初始化 createAndAddWindows(); }

2.StatusBars创建

在BaseStausBars中,createAndAddWindows函数是抽象函数,看来是call到子类的createAndAddWindows函数。 在SysemUI中,继承BaseStatusBars的类有:PhoneStatusBar和TvStatusBar,其中TvStatusBar是空实现,因此主要看PhoneStatusBar

PhoneStatusBar.java

@Override
    public void createAndAddWindows() {
        addStatusBarWindow();
    }

    private void addStatusBarWindow() {
        makeStatusBarView();
        mStatusBarWindowManager = new StatusBarWindowManager(mContext);
        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
    }

1)makeStatusBarView函数代码很长,因为PhoneStatusBarView除了状态栏那一条之外,还包含Notification Panel,Heads up Panel以及包含drag行为。 主要还是实例化PhoneStatusBarView中各种UI控件。 2)StatusBarWindowManager类的add函数负责为PhoneStatusBarView新建Window,包括window大小,位置,是否透明等属性。

这里先分析一下makeStatusBarView函数,代码太长,不全部粘贴。

(1)获取系统显示参数 updateDisplaySize();

    // called by makeStatusbar and also by PhoneStatusBarView
    void updateDisplaySize() {
        mDisplay.getMetrics(mDisplayMetrics);
        mDisplay.getSize(mCurrentDisplaySize);
        if (DEBUG_GESTURES) {
            mGestureRec.tag("display",
                    String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
        }
    }

获取系统分辨率,屏幕密度,便于根据不同的显示参数计算响应的值进行显示。 (2)更新Panels资源数据 StatusBar这个图层包含很多的Panel,在创建PhoneStatusBarView时需要更新Panels数据。 updateResources();

    /**
     * Reload some of our resources when the configuration changes.
     *
     * We don't reload everything when the configuration changes -- we probably
     * should, but getting that smooth is tough.  Someday we'll fix that.  In the
     * meantime, just update the things that we know change.
     */
    void updateResources() {
        // Update the quick setting tiles
        if (mQSPanel != null) {
            mQSPanel.updateResources();
        }

        loadDimens();

        if (mNotificationPanel != null) {
            mNotificationPanel.updateResources();
        }
        if (mBrightnessMirrorController != null) {
            mBrightnessMirrorController.updateResources();
        }
    }

QSPanel是快捷设置panel,一些主要应用,可以通过点击QSPanel的Button去进入apk,android和iphone都有这样的设计。 NotificationPanel是通知消息显示的Panel,在有消息(系统或apk发送Notification),会在Panel里面显示,用户可以删除,或点击消息进入apk。 BrightnessMirrorController是控制亮度的Panel

(3)注册系统的事件广播  // receive broadcasts

        IntentFilter filter = new IntentFilter();

        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);

        filter.addAction(Intent.ACTION_SCREEN_OFF);

        filter.addAction(Intent.ACTION_SCREEN_ON);

        context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);

(4)Panels & Views实例化以及事件注册

3.StatusBar显示

显示主要是call StatusBarWindowManager类的add函数。 StatusBarWindowManager.java

 /**
     * Adds the status bar view to the window manager.
     *
     * @param statusBarView The view to add.
     * @param barHeight The height of the status bar in collapsed state.
     */
    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.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
        mLp.gravity = Gravity.TOP;
        mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
        mLp.setTitle("StatusBar");
        mLp.packageName = mContext.getPackageName();
        mStatusBarView = statusBarView;
        mBarHeight = barHeight;
        mWindowManager.addView(mStatusBarView, mLp);
        mLpChanged = new WindowManager.LayoutParams();
        mLpChanged.copyFrom(mLp);
    }

barHeight表示状态栏的宽度,在dimen里面可以配置:  public int getStatusBarHeight() {

        if (mNaturalBarHeight < 0) {

            final Resources res = mContext.getResources();

            mNaturalBarHeight =

                    res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);

        }

        return mNaturalBarHeight;

    }

若不想显示,可以设置为0






    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/zhudaozhuan/article/details/50829736
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞