SystemUI 7.0学习笔记一中SERVICES中类的名字就可以大致猜出来它们的功能,对!本节的主角就是com.android.systemui.statusbar.SystemBars.class。
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);
}
}
......
}
让我们回到抽象方法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();
}