SystemUI源码分析三(StatusBar的加载流程)

SystemServer中调用startsystemui函数启动SystemUIService,在SystemUIService的onCreate()函数中执行一下这个语句

((SystemUIApplication) getApplication()).startServicesIfNeeded();

SystemBar继承SystemUI,因此被启动了。

那接下来就进入SystemBar这个类中看onStart()函数

public void start(){
    if(DEBUG)Log.d(TAG,"start");
    //创建监听器对象
    mServiceMonitor = new ServiceMonitor(TAG,DEBUG,mContext,Settings.Secure.BAR_SERVICE_COMPONENT,this);
    //开始监听
    mServiceMonitor.start();
}

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

    //发送消息给主线程,启动Service
    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;
            case MSG_CONTINUE_START_SERVICE:
                continueStartService();
                break;
            case MSG_STOP_SERVICE:
                stopService();
                break;
            case MSG_PACKAGE_INTENT:
                packageIntent((Intent)msg.obj);
                break;
            case MSG_CHECK_BOUND:
                checkBound();
                break;
            case MSG_SERVICE_DISCONNECTED:
                serviceDisconnected((ComponentName)msg.obj);
                break;
        }
    }
};

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

先获取Service的componentName,如果为null则回调onNoService方法。如果不为null,则通过mHandler发送消息给主线程。

private void continueStartService() {
    if (mDebug) Log.d(mTag, "continueStartService");
    Intent intent = new Intent().setComponent(mServiceName);
    try {
        mServiceConnection = new SC();
        mBound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        if (mDebug) Log.d(mTag, "mBound: " + mBound);
    } catch (Throwable t) {
        Log.w(mTag, "Error binding to service: " + mServiceName, t);
    }
    if (!mBound) {
        mCallbacks.onNoService();
    }
}

获取的componentName不管是不是空,最终都会回调onNoService()。

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

private void createStatusBarFromConfig() {
    if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
    //取出className
    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 {
        //动态加载class文件
        cls = mContext.getClassLoader().loadClass(clsName);
    } catch (Throwable t) {
        throw andLog("Error loading status bar component: " + clsName, t);
    }
    try {
        //创建BaseStatusBar实例
        mStatusBar = (BaseStatusBar) cls.newInstance();
    } catch (Throwable t) {
        throw andLog("Error creating status bar component: " + clsName, t);
    }
    mStatusBar.mContext = mContext;
    mStatusBar.mComponents = mComponents;
    //启动BaseStatusBar
    mStatusBar.start();
    if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}

frameworks\base\packages\SystemUI\res\values\config.xml
R.string.config_statusBarComponent的值是:

"config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar

PhoneStatusBar继承自BaseStatusBar

启动BaseStatusBar,那就接着来看BaseStatusBar.java,这个类继承自SystemUI

public void start(){
    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,那我们来看下PhoneStatusBar

 public void start() {
    ……
    super.start(); // calls createAndAddWindows()
}

果然是PhoneStatusBar启动时调用了父类(BaseStatusBar)的createAndAddWindows(),这里PhoneStatusBar实现了父类的抽象方法。主要是添加状态栏、添加导航栏、更新图标

一、添加状态栏

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

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

这个函数做了两件事

(1)创建PhoneStatusBarView并初始化PhoneStatusBarView中的控件。

(2)创建StatusBarWindowManager对象,调用它的add()函数为PhoneStatusBarView创建窗口,包括窗口的大小、位置、是否透明等属性。

先来分析makeStatusBarView()函数。

protected PhoneStatusBarView makeStatusBarView() {
    final Context context = mContext;

    Resources res = context.getResources();

    //获取屏幕参数
    updateDisplaySize(); // populates mDisplayMetrics
    //更新Panels资源数据,statusbar包含很多panel,在创建PhoneStatusBarView时需要更新panel数据
    updateResources();

    //引入StatusBarWindowView布局
    mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
            R.layout.super_status_bar, null);
    //statusbarwindow
    mStatusBarWindow.setService(this);
    //设置触摸事件监听器
    mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            checkUserAutohide(v, event);
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                if (mExpandedVisible) {
                    animateCollapsePanels();
                }
            }
            return mStatusBarWindow.onTouchEvent(event);
        }
    });

    //初始化statusbarview
    mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
    mStatusBarView.setBar(this);

    //初始化panelholder
    PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
    mStatusBarView.setPanelHolder(holder);

    //初始化通知panel
    mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
            R.id.notification_panel);
    mNotificationPanel.setStatusBar(this);


    if (!mHighEnd) {
        mStatusBarWindow.setBackground(null);
        //设置notificationpanel背景
        mNotificationPanel.setBackground(new FastColorDrawable(context.getColor(
                R.color.notification_panel_solid_background)));
    }

    //通知样式
    mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow);
    mHeadsUpManager.setBar(this);
    mHeadsUpManager.addListener(this);
    mHeadsUpManager.addListener(mNotificationPanel);
    mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
    mNotificationData.setHeadsUpManager(mHeadsUpManager);

    if (MULTIUSER_DEBUG) {
        mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
                R.id.header_debug_info);
        mNotificationPanelDebugText.setVisibility(View.VISIBLE);
    }

    try {
        boolean showNav = mWindowManagerService.hasNavigationBar();
        //检查是否显示导航栏
        if (showNav) {
            //引入导航栏navigationbarview的布局
            mNavigationBarView =
                (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);

            mNavigationBarView.setDisabledFlags(mDisabled1);
            mNavigationBarView.setBar(this);
            mNavigationBarView.setOnVerticalChangedListener(
                    new NavigationBarView.OnVerticalChangedListener() {
                @Override
                public void onVerticalChanged(boolean isVertical) {
                    if (mAssistManager != null) {
                        mAssistManager.onConfigurationChanged();
                    }
                    mNotificationPanel.setQsScrimEnabled(!isVertical);
                }
            });、
            //设置导航栏的触摸监听事件
            mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    checkUserAutohide(v, event);
                    return false;
                }});
        }
    } catch (RemoteException ex) {
        // no window manager? good luck with that
    }

    mAssistManager = new AssistManager(this, context);

    // figure out which pixel-format to use for the status bar.
    //状态栏使用的像素格式
    mPixelFormat = PixelFormat.OPAQUE;

    //status_bar_expanded.xml布局的控件
    mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
            R.id.notification_stack_scroller);
    mStackScroller.setLongPressListener(getNotificationLongClicker());
    mStackScroller.setPhoneStatusBar(this);
    mStackScroller.setGroupManager(mGroupManager);
    mStackScroller.setHeadsUpManager(mHeadsUpManager);
    mGroupManager.setOnGroupChangeListener(mStackScroller);

    //引入NotificationOverflowContainer的布局
    mKeyguardIconOverflowContainer =
            (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
                    R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
    mKeyguardIconOverflowContainer.setOnActivatedListener(this);
    mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);
    mStackScroller.setOverflowContainer(mKeyguardIconOverflowContainer);

    //引入SpeedBump的布局
    SpeedBumpView speedBump = (SpeedBumpView) LayoutInflater.from(mContext).inflate(
                    R.layout.status_bar_notification_speed_bump, mStackScroller, false);
    mStackScroller.setSpeedBumpView(speedBump);

    //引入EmptyShadeView的布局
    mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate(
            R.layout.status_bar_no_notifications, mStackScroller, false);
    mStackScroller.setEmptyShadeView(mEmptyShadeView);

    //引入DismissView的布局
    mDismissView = (DismissView) LayoutInflater.from(mContext).inflate(
            R.layout.status_bar_notification_dismiss_all, mStackScroller, false);
    mDismissView.setOnButtonClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            MetricsLogger.action(mContext, MetricsLogger.ACTION_DISMISS_ALL_NOTES);
            clearAllNotifications();
        }
    });
    mStackScroller.setDismissView(mDismissView);
    mExpandedContents = mStackScroller;

    //初始化控件
    mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop);
    mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
    mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);

    ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
    ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
    View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
    mScrimController = new ScrimController(scrimBehind, scrimInFront, headsUpScrim,
            mScrimSrcModeEnabled);


    mHeadsUpManager.addListener(mScrimController);
    mStackScroller.setScrimController(mScrimController);
    mScrimController.setBackDropView(mBackdrop);
    mStatusBarView.setScrimController(mScrimController);
    mDozeScrimController = new DozeScrimController(mScrimController, context);

    mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
    mHeader.setActivityStarter(this);
    mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
    mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
    mKeyguardBottomArea =
            (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
    mKeyguardBottomArea.setActivityStarter(this);
    mKeyguardBottomArea.setAssistManager(mAssistManager);
    mKeyguardIndicationController = new KeyguardIndicationController(mContext,
            (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
                    R.id.keyguard_indication_text));
    mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);

    // set the inital view visibility
    setAreThereNotifications();

    //创建IconController对象
    mIconController = new StatusBarIconController(
            mContext, mStatusBarView, mKeyguardStatusBar, this);

    // Background thread for any controllers that need it.
    //创建线程并启动线程
    mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
    mHandlerThread.start();

    // Other icons
    //位置控制器
    mLocationController = new LocationControllerImpl(mContext,
            mHandlerThread.getLooper()); // will post a notification

    //电池控制器
    mBatteryController = new BatteryController(mContext);
    mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
        @Override
        public void onPowerSaveChanged() {
            mHandler.post(mCheckBarModes);
            if (mDozeServiceHost != null) {
                mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());
            }
        }
        @Override
        public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
            // noop
        }
    });

    //网络控制器
    mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
    //热点控制器
    mHotspotController = new HotspotControllerImpl(mContext);
    //蓝牙控制器
    mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper());

    mBluetoothController.setbar(this);

    mHotspotController.setbar(this);
    //安全控制器
    mSecurityController = new SecurityControllerImpl(mContext);
    if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {
        //旋转锁控制?
        mRotationLockController = new RotationLockControllerImpl(mContext);
    }
    //用户信息控制器
    mUserInfoController = new UserInfoController(mContext);
    mVolumeComponent = getComponent(VolumeComponent.class);
    if (mVolumeComponent != null) {
        //
        mZenModeController = mVolumeComponent.getZenController();
    }
    //投射控制器
    mCastController = new CastControllerImpl(mContext);
    final SignalClusterView signalCluster =
            (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
    final SignalClusterView signalClusterKeyguard =
            (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);
    final SignalClusterView signalClusterQs =
            (SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
    mNetworkController.addSignalCallback(signalCluster);
    mNetworkController.addSignalCallback(signalClusterKeyguard);
    mNetworkController.addSignalCallback(signalClusterQs);
    signalCluster.setSecurityController(mSecurityController);
    signalCluster.setNetworkController(mNetworkController);
    signalClusterKeyguard.setSecurityController(mSecurityController);
    signalClusterKeyguard.setNetworkController(mNetworkController);
    signalClusterQs.setSecurityController(mSecurityController);
    signalClusterQs.setNetworkController(mNetworkController);
    final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
    if (isAPhone) {
        mNetworkController.addEmergencyListener(mHeader);
    }


    mCarrierLabel = (LinearLayout) mStatusBarWindow.findViewById(R.id.carrier_label_group_ex);
    //手电筒控制器
    mFlashlightController = new FlashlightController(mContext);
    mKeyguardBottomArea.setFlashlightController(mFlashlightController);
    mKeyguardBottomArea.setPhoneStatusBar(this);
    mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
    mAccessibilityController = new AccessibilityController(mContext);
    mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
    mNextAlarmController = new NextAlarmController(mContext);
    //创建锁屏监听器
    mKeyguardMonitor = new KeyguardMonitor(mContext);
    if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) {
        mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
                mHandler);
    }
    mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
            (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher),
            mKeyguardStatusBar, mNotificationPanel, mUserSwitcherController);


    // Set up the quick settings tile panel
    mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
    if (mQSPanel != null) {
        final QSTileHost qsh = new QSTileHost(mContext, this,
                mBluetoothController, mLocationController, mRotationLockController,
                mNetworkController, mZenModeController, mHotspotController,
                mCastController, mFlashlightController,
                mUserSwitcherController, mKeyguardMonitor,
                mSecurityController);
        mQSPanel.setHost(qsh);
        mQSPanel.setTiles(qsh.getTiles());
        mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
        mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
        mHeader.setQSPanel(mQSPanel);
        qsh.setCallback(new QSTileHost.Callback() {
            @Override
            public void onTilesChanged() {
                mQSPanel.setTiles(qsh.getTiles());
            }
        });
    }

    // User info. Trigger first load.
    mHeader.setUserInfoController(mUserInfoController);
    mKeyguardStatusBar.setUserInfoController(mUserInfoController);
    mKeyguardStatusBar.setUserSwitcherController(mUserSwitcherController);
    mUserInfoController.reloadUserInfo();

    mHeader.setBatteryController(mBatteryController);
    ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
            mBatteryController);
    mKeyguardStatusBar.setBatteryController(mBatteryController);
    mHeader.setNextAlarmController(mNextAlarmController);

    PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    mBroadcastReceiver.onReceive(mContext,
            new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));


    // receive broadcasts
    //注册广播接收者,接收关闭系统对话框、screen on/off消息
    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);

    IntentFilter demoFilter = new IntentFilter();
    if (DEBUG_MEDIA_FAKE_ARTWORK) {
        demoFilter.addAction(ACTION_FAKE_ARTWORK);
    }
    demoFilter.addAction(ACTION_DEMO);
    context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
            android.Manifest.permission.DUMP, null);

    // listen for USER_SETUP_COMPLETE setting (per-user)
    resetUserSetupObserver();

    // disable profiling bars, since they overlap and clutter the output on app windows
    ThreadedRenderer.overrideProperty("disableProfileBars", "true");

    // Private API call to make the shadows look better for Recents
    ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));

    return mStatusBarView;
}

插入分析加载的布局super_status_bar.xml

mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
        R.layout.super_status_bar, null);

1、include layout = “@layout/status_bar”

status_bar.xml

这里写图片描述

notification包括Usb、T卡等通知项

这里写图片描述

system_icons.xml包括wifi、SIM卡、电池、时间等

这里写图片描述

2、include layout=”@layout/quick_settings_brightness_dialog”亮度调节对话框

3、panelholder:include layout=”@layout/status_bar_expanded”

SystemUI源码分析三(StatusBar的加载流程)_第1张图片

NotificationPanelView

3.1、include layout=”@layout/keyguard_status_view” gone

锁屏时显示的是时间和日期部分以及owner_info

SystemUI源码分析三(StatusBar的加载流程)_第2张图片

3.2、NotificationsQuickSettingsContainer

3.2.1、include layout=”@layout/qs_panel”

SystemUI源码分析三(StatusBar的加载流程)_第3张图片

3.2.2、include layout=”@layout/keyguard_user_switcher”

3.2.3、include layout=”@layout/keyguard_status_bar” invisible

显示的是锁屏时多用户MultiUserSwitch、system_icons battery_level、(CarrierText、CarriersTextLayout gone)

这里写图片描述

3.3、include layout=”@layout/keyguard_bottom_area” gone

SystemUI源码分析三(StatusBar的加载流程)_第4张图片

3.4、include layout=”@layout/status_bar_expanded_header”

SystemUI源码分析三(StatusBar的加载流程)_第5张图片

布局就分析到这里吧,大概了解了各个模块对应的布局文件。

二、添加导航栏

// For small-screen devices (read: phones) that lack hardware navigation buttons
private void addNavigationBar() {
    if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);
    if (mNavigationBarView == null) return;

    prepareNavigationBarView();

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

1、判断mNavigationBarView为空就不返回不再继续执行。

2、导航栏布局分析及加载;

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

    mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
    mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
    mNavigationBarView.getRecentsButton().setLongClickable(true);
    mNavigationBarView.getRecentsButton().setOnLongClickListener(mLongPressBackRecentsListener);
    mNavigationBarView.getBackButton().setLongClickable(true);
    mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener);
    mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);
    mNavigationBarView.getHomeButton().setOnLongClickListener(mLongPressHomeListener);
    mAssistManager.onConfigurationChanged();
}
public void reorient() {
    //获取屏幕方向(横向、竖向)
    final int rot = mDisplay.getRotation();
    //隐藏导航栏布局
    for (int i=0; i<4; i++) {
        mRotatedViews[i].setVisibility(View.GONE);
    }
    //根据屏幕方向显示导航栏布局
    mCurrentView = mRotatedViews[rot];
    mCurrentView.setVisibility(View.VISIBLE);
    setLayoutTransitionsEnabled(mLayoutTransitionsEnabled);

    getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);

    mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);

    // force the low profile & disabled states into compliance
    mBarTransitions.init();
    setDisabledFlags(mDisabledFlags, true /* force */);
    setMenuVisibility(mShowMenu, true /* force */);

    if (DEBUG) {
        Log.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
    }

    updateTaskSwitchHelper();

    setNavigationIconHints(mNavigationIconHints, true);
}

设置最近应用、后退键、Home键监听事件。RotatedViews代表的是不同方向的导航栏布局,有4种

View[] mRotatedViews = new View[4];
/*布局加载完成后会调用这个方法*/
@Override
public void onFinishInflate() {
    mRotatedViews[Surface.ROTATION_0] =
    mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);

    mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);

    mRotatedViews[Surface.ROTATION_270] = mRotatedViews[Surface.ROTATION_90];

    mCurrentView = mRotatedViews[Surface.ROTATION_0];

    getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);

    updateRTLOrder();
}

3、把导航栏添加到窗口。LayoutParames决定了导航栏在窗体的大小(受父布局影响)和显示的位置效果。

三、最终调用PhoneStatusBarPolicy这个类来安装或更新icon,那icon的初始化是什么时候完成的呢,我们在上面分析PhoneStatusBar的构造方法中有提到调用了它的父类BaseStatusBar的start()方法,那么我们再来看一次BaseStatusBar的start()方法中与icon相关的代码。

public void start(){
    ……
    // Connect in to the status bar manager service
    StatusBarIconList iconList = new StatusBarIconList();
    mCommandQueue = new CommandQueue(this, iconList);

    int[] switches = new int[8];
    ArrayList binders = new ArrayList();
    try {
        mBarService.registerStatusBar(mCommandQueue, iconList, switches, binders);
    } catch (RemoteException ex) {
        // If the system process isn't there we're doomed anyway.
    }
    ……
    // Set up the initial icon state
    int N = iconList.size();
    int viewIndex = 0;
    for (int i=0; iif (icon != null) {
            addIcon(iconList.getSlot(i), i, viewIndex, icon);
            viewIndex++;
        }
    }
}

BaseStatusBar实现了CommandQueue.Callbacks接口,CommandQueue继承自IStatusBar.Stub,是一个IBinder对象。PhoneStatusBar实现了BaseStatusBar这个抽象类并真正实现了CommandQueue.Callbacks接口定义的方法。mBarService是StatusBarService的对象,通过registerStatusBar函数将CommandQueue注册到了StatusBarManagerSerivice中

@Override
public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
        int switches[], List binders) {
    enforceStatusBarService();

    Slog.i(TAG, "registerStatusBar bar=" + bar);
    mBar = bar;
    synchronized (mIcons) {
        //把icon拷贝到传入的参数iconList中
        iconList.copyFrom(mIcons);
    }
    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);
        binders.add(mImeToken);
    }
}

把StatusBarManager中的mIcons复制到传入的参数iconList中之后,在BaseStatusBar中就可以初始化icon state了

// Set up the initial icon state
int N = iconList.size();
int viewIndex = 0;
for (int i=0; iif (icon != null) {
        addIcon(iconList.getSlot(i), i, viewIndex, icon);
        viewIndex++;
    }
}

回调PhoneStatusBar的addIcon()函数,加载图标的布局

public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
    mIconController.addSystemIcon(slot, index, viewIndex, icon);
}

StatusBarIconController.java

public void addSystemIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
    boolean blocked = mIconBlacklist.contains(slot);
    StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
    view.set(icon);
    mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
    view = new StatusBarIconView(mContext, slot, null, blocked);
    view.set(icon);
    mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
    applyIconTint();
}

mStatusBarIcons的初始化是在StatusBarIconController的构造方法中初始化的

public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
        PhoneStatusBar phoneStatusBar) {
    mContext = context;
    mPhoneStatusBar = phoneStatusBar;
    mNotificationColorUtil = NotificationColorUtil.getInstance(context);
    mSystemIconArea = (LinearLayout) statusBar.findViewById(R.id.system_icon_area);
    mStatusIcons = (LinearLayout) statusBar.findViewById(R.id.statusIcons);
    mSignalCluster = (SignalClusterView) statusBar.findViewById(R.id.signal_cluster);
    mNotificationIconArea = statusBar.findViewById(R.id.notification_icon_area_inner);
    mNotificationIcons = (IconMerger) statusBar.findViewById(R.id.notificationIcons);
    mMoreIcon = (ImageView) statusBar.findViewById(R.id.moreIcon);
    mNotificationIcons.setOverflowIndicator(mMoreIcon);
    mStatusIconsKeyguard = (LinearLayout) keyguardStatusBar.findViewById(R.id.statusIcons);
    mBatteryMeterView = (BatteryMeterView) statusBar.findViewById(R.id.battery);
    mClock = (TextView) statusBar.findViewById(R.id.clock);
    mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext,
            android.R.interpolator.linear_out_slow_in);
    mFastOutSlowIn = AnimationUtils.loadInterpolator(mContext,
            android.R.interpolator.fast_out_slow_in);
    mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
    mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
    mHandler = new Handler();
    updateResources();

    TunerService.get(mContext).addTunable(this, ICON_BLACKLIST);
}

而StatusBarIconController的初始化是在PhoneStatusBar这个类的makeStatusBarView中初始化的

protected PhoneStatusBarView makeStatusBarView() {
    ……
    mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
                R.layout.super_status_bar, null);
    mIconController = new StatusBarIconController(
                mContext, mStatusBarView, mKeyguardStatusBar, this);
    ……
}

那么上面提到的mStatusIcons控件就是从R.layout.super_status_bar.xml中取出来的。这就是icon布局的加载过程了。

现在继续分析PhoneStatusBar.java中的 mIconPolicy = new
PhoneStatusBarPolicy(mContext, mCastController, mHotspotController)。

PhoneStatusBarPolicy.java

public PhoneStatusBarPolicy(Context context, CastController cast, HotspotController hotspot,
        UserInfoController userInfoController, BluetoothController bluetooth) {
    mContext = context;
    mCast = cast;
    mHotspot = hotspot;
    mBluetooth = bluetooth;
    mBluetooth.addStateChangedCallback(this);
    mService = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE);
    mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    mUserInfoController = userInfoController;

    // listen for broadcasts
    IntentFilter filter = new IntentFilter();
    filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
    filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
    filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
    filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
    filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
    // add headset icon in statusbar
    filter.addAction(Intent.ACTION_HEADSET_PLUG);
    mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);

    // listen for user / profile change.
    try {
        ActivityManagerNative.getDefault().registerUserSwitchObserver(mUserSwitchListener);
    } catch (RemoteException e) {
        // Ignore
    }

    // TTY status
    mService.setIcon(SLOT_TTY,  R.drawable.stat_sys_tty_mode, 0, null);
    mService.setIconVisibility(SLOT_TTY, false);

    // bluetooth status
    updateBluetooth();

    // Alarm clock
    mService.setIcon(SLOT_ALARM_CLOCK, R.drawable.stat_sys_alarm, 0, null);
    mService.setIconVisibility(SLOT_ALARM_CLOCK, false);

    // zen
    mService.setIcon(SLOT_ZEN, R.drawable.stat_sys_zen_important, 0, null);
    mService.setIconVisibility(SLOT_ZEN, false);

    // volume
    mService.setIcon(SLOT_VOLUME, R.drawable.stat_sys_ringer_vibrate, 0, null);
    mService.setIconVisibility(SLOT_VOLUME, false);
    updateVolumeZen();

    // cast
    mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0, null);
    mService.setIconVisibility(SLOT_CAST, false);
    mCast.addCallback(mCastCallback);

    // hotspot
    if (!HOTSPOT_ENABLED){
        mService.setIcon(SLOT_HOTSPOT, R.drawable.stat_sys_hotspot, 0,
                mContext.getString(R.string.accessibility_status_bar_hotspot));
        mService.setIconVisibility(SLOT_HOTSPOT, mHotspot.isHotspotEnabled());
        mHotspot.addCallback(mHotspotCallback);
    }
    // managed profile
    mService.setIcon(SLOT_MANAGED_PROFILE, R.drawable.stat_sys_managed_profile_status, 0,
            mContext.getString(R.string.accessibility_managed_profile));
    mService.setIconVisibility(SLOT_MANAGED_PROFILE, false);

    /*  add headset icon in statusbar */
    mService.setIcon("headset", R.drawable.stat_sys_headset, 0, null);
    mService.setIconVisibility("headset", false);
}

mService是StatusBarManager的对象,这里注册广播接收消息更新icon状态,设置icon和icon的可见性

StatusBarManager.java的setIcon()函数

public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) {
    try {
        final IStatusBarService svc = getService();
        if (svc != null) {
            svc.setIcon(slot, mContext.getPackageName(), iconId, iconLevel,
                contentDescription);
        }
    } catch (RemoteException ex) {
        // system process is dead anyway.
        throw new RuntimeException(ex);
    }
}

StatusManagerService继承IStatusBarServicer.Stub,那么svc就是StatusManagerService的对象,即调用到StatusBarManagerService.java中的setIcon()函数

@Override
public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
        String contentDescription) {
    enforceStatusBar();

    synchronized (mIcons) {
        int index = mIcons.getSlotIndex(slot);
        if (index < 0) {
            throw new SecurityException("invalid status bar icon slot: " + slot);
        }

        StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.OWNER, iconId,
                iconLevel, 0,
                contentDescription);
        //Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon);
        mIcons.setIcon(index, icon);

        if (mBar != null) {
            try {
                //加载到布局中
                mBar.setIcon(index, icon);
            } catch (RemoteException ex) {
            }
        }
    }
}

mBar.setIcon(),mBar就是通过BaseStatusBar.java类调用StatusBarManagerService的registerStatusBar()传进来的CommandQueue对象,既然这样就来分析CommandQueue.java

public void setIcon(int index, StatusBarIcon icon) {
    synchronized (mList) {
        int what = MSG_ICON | index;
        mHandler.removeMessages(what);
        mHandler.obtainMessage(what, OP_SET_ICON, 0, icon.clone()).sendToTarget();
    }
}

通过mHandler发送消息到主线程

private final class H extends Handler {
    public void handleMessage(Message msg) {
        final int what = msg.what & MSG_MASK;
        switch (what) {
            case MSG_ICON: {
                final int index = msg.what & INDEX_MASK;
                final int viewIndex = mList.getViewIndex(index);
                switch (msg.arg1) {
                    case OP_SET_ICON: {
                        StatusBarIcon icon = (StatusBarIcon)msg.obj;
                        StatusBarIcon old = mList.getIcon(index);
                        if (old == null) {
                            mList.setIcon(index, icon);
                            mCallbacks.addIcon(mList.getSlot(index), index, viewIndex, icon);
                        } else {
                            mList.setIcon(index, icon);
                            mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex,
                                    old, icon);
                        }
                        break;
                    }
                    case OP_REMOVE_ICON:
                        if (mList.getIcon(index) != null) {
                            mList.removeIcon(index);
                            mCallbacks.removeIcon(mList.getSlot(index), index, viewIndex);
                        }
                        break;
            }
            break;
        }
    }

mCallBacks是CommandQueue.Callbacks的对象,BaseStatusBar实现了这个接口,PhoneStatusBar是BaseStatusBar的子类,在这个子类中才实现了接口定义的方法,那么就得到PhoneStatusbar.java中看下这个方法

public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
        mIconController.addSystemIcon(slot, index, viewIndex, icon);
    }

这个函数上面已经分析过了,就是加载icon到布局中。

你可能感兴趣的:(SystemUI源码分析三(StatusBar的加载流程))