SystemUI 7.0学习笔记二-状态栏和导航栏

状态栏和导航栏的启动

SystemUI 7.0学习笔记一中SERVICES中类的名字就可以大致猜出来它们的功能,对!本节的主角就是com.android.systemui.statusbar.SystemBars.class。

首先看一张图来个全面的把握,
SystemUI 7.0学习笔记二-状态栏和导航栏_第1张图片

SystemBars的start()会new一个ServiceMonitor对象,接着会调用其start()。

public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {
    ......
    @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
    }
    ......
}

ServiceMonitor的start()发消息给Handler处理,

public void start() {
        ......
        mHandler.sendEmptyMessage(MSG_START_SERVICE);
    }
private final Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case MSG_START_SERVICE:
                    startService();
                    break;
                ......
            }
        }
    };

startService()中mCallbacks.onNoService();的mCallbacks就是创建ServiceMonitor时传入的this(SystemBars)。

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);
        }
    }

回调SystemBars的onNoService()里创建StatusBar,

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

在createStatusBarFromConfig()里会获取一个config_statusBarComponent的字符串值,这个值就是PhoneStatusBar的clasName,

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;
        // start
        mStatusBar.start();
        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
    }
"config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar

所以,这里的mStatusBar是PhoneStatusBar实例。

PhoneStatusBar的start():

public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        HeadsUpManager.OnHeadsUpChangedListener {
    ......
     @Override
    public void start() {
        ......
        super.start(); // calls createAndAddWindows()
        ......
        addNavigationBar();
    }
}

PhoneStatusBar的start()会回调父类BaseStatusBar 的start(),
super.start():

public abstract class BaseStatusBar extends SystemUI implements
        CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
        ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
        ExpandableNotificationRow.OnExpandClickListener,
        OnGutsClosedListener {
    ......
    // 实例化IStatusBarService
    mBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));

    ......

    // Connect in to the status bar manager service
    mCommandQueue = new CommandQueue(this); // 注意上面的注释

    int[] switches = new int[9];
    ArrayList binders = new ArrayList();
    ArrayList iconSlots = new ArrayList<>();
    ArrayList icons = new ArrayList<>();
    Rect fullscreenStackBounds = new Rect();
    Rect dockedStackBounds = new Rect();
    try {
            // register后,StatusBarManagerService(IStatusBarService的实例)就可以和BaseStatusBar亲密交流了,CommandQueue的注释大概就是这个意思。
            mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
                    fullscreenStackBounds, dockedStackBounds);
    } catch (RemoteException ex) {
            // If the system process isn't there we're doomed anyway.
    }
    // 抽象方法
    createAndAddWindows();
}

BaseStatusBar获取了IStatusBarService的实例-StatusBarManagerService,并注册一些信息到StatusBarManagerService中,BaseStatusBar通过CommandQuene间接将自己注册到StatusBarManagerService,而StatusBarManagerService会把操作状态栏和导航栏的请求通过CommandQuene再转发给BaseStatusBar。
另外,为了保证SystemUI意外退出后不会发生信息丢失,StatusBarManagerService保存了所有需要状态栏与导航栏进行显示或处理的信息副本,在上述注册的过程中一并取回了。

StatusBarManagerService的registerStatusBar()就是做一些数据的初始化:

public class StatusBarManagerService extends IStatusBarService.Stub {
    ......

    // ================================================================================
    // Callbacks from the status bar service.
    // ================================================================================
    @Override
    public void registerStatusBar(IStatusBar bar, List iconSlots,
            List iconList, int switches[], List binders,
            Rect fullscreenStackBounds, Rect dockedStackBounds) {
        enforceStatusBarService();

        Slog.i(TAG, "registerStatusBar bar=" + bar);
        mBar = bar;
        synchronized (mIcons) {
            for (String slot : mIcons.keySet()) {
                iconSlots.add(slot);
                iconList.add(mIcons.get(slot));
            }
        }
        synchronized (mLock) {
            switches[0] = gatherDisableActionsLocked(mCurrentUserId, 1);
            switches[1] = mSystemUiVisibility;
            switches[2] = mMenuVisible ? 1 : 0;
            switches[3] = mImeWindowVis;
            switches[4] = mImeBackDisposition;
            switches[5] = mShowImeSwitcher ? 1 : 0;
            switches[6] = gatherDisableActionsLocked(mCurrentUserId, 2);
            switches[7] = mFullscreenStackSysUiVisibility;
            switches[8] = mDockedStackSysUiVisibility;
            binders.add(mImeToken);
            fullscreenStackBounds.set(mFullscreenStackBounds);
            dockedStackBounds.set(mDockedStackBounds);
        }
    }

    ......
}

用一张图表示下这几者的关系:
SystemUI 7.0学习笔记二-状态栏和导航栏_第2张图片

让我们回到抽象方法createAndAddWindows(),

    /**
     * Create all windows necessary for the status bar (including navigation, overlay panels, etc)
     * and add them to the window manager.
     */
    protected abstract void createAndAddWindows();

PhoneStatusBar实现了父类BaseStatusBar中的createAndAddWindows(),

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

继续看下addStatusBarWindow()实现:

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

接着看makeStatusBarView()的实现,发现调用了 inflateStatusBarWindow(context):

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

inflate完布局后,就会添加mStatusBarWindow 到WindowManager里。到这里,状态栏就启动完毕了。后面会抽时间补充下布局相关的代码说明。。。

下面看下导航栏的启动
PhoneStatusBar.addNavigationBar():

    protected void addNavigationBar() {
        if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);
        if (mNavigationBarView == null) return;

        ......

        prepareNavigationBarView();

        mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
    }

在这个方法里先初始化导航栏,然后把导航栏添加到WindowManager,prepareNavigationBarView()对三个按键做了事件监听。

    private void prepareNavigationBarView() {
        mNavigationBarView.reorient();

        ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
        recentsButton.setOnClickListener(mRecentsClickListener);
        recentsButton.setOnTouchListener(mRecentsPreloadOnTouchListener);
        recentsButton.setLongClickable(true);
        recentsButton.setOnLongClickListener(mRecentsLongClickListener);

        ButtonDispatcher backButton = mNavigationBarView.getBackButton();
        backButton.setLongClickable(true);
        backButton.setOnLongClickListener(mLongPressBackListener);

        ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
        homeButton.setOnTouchListener(mHomeActionListener);
        homeButton.setOnLongClickListener(mLongPressHomeListener);

        mAssistManager.onConfigurationChanged();
    }

参考文章

  1. http://blog.csdn.net/qq_31530015/article/details/53507968
  2. http://blog.csdn.net/zhudaozhuan/article/details/50817180
  3. http://blog.csdn.net/yj934672573/article/details/54571704
  4. http://blog.csdn.net/Picasso_L/article/details/69388919
  5. … …

你可能感兴趣的:(android,SystemUI)