Android SystemUI 启动流程和状态栏视图
SystemServer会启动SystemUiService
系统启动入口:frameworks/base/services/java/com/android/server/SystemServer.java
ActivitManagerService准备好之后,启动SystemUI
static final void startSystemUi(Context context) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.OWNER);
}
SystemUIService 通过反射机制启动各个SystemUI组件
/**
* The classes of the stuff to start.
*/
private final Class<?>[] SERVICES = new Class[] {
com.android.systemui.recent.Recents.class,
com.android.systemui.statusbar.SystemBars.class,
com.android.systemui.usb.StorageNotification.class,
com.android.systemui.power.PowerUI.class,
com.android.systemui.media.RingtonePlayer.class,
com.android.systemui.settings.SettingsUI.class,
};
/**
* Hold a reference on the stuff we start.
*/
private final SystemUI[] mServices = new SystemUI[SERVICES.length];
@Override
public void onCreate() {
HashMap<Class<?>, Object> components = new HashMap<Class<?>, Object>();
final int N = SERVICES.length;
for (int i=0; i<N; i++) {
Class<?> cl = SERVICES[i];
Log.d(TAG, "loading: " + cl);
try {
mServices[i] = (SystemUI)cl.newInstance();
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
}
mServices[i].mContext = this;
mServices[i].mComponents = components;
Log.d(TAG, "running: " + mServices[i]);
mServices[i].start();
}
}
StatusBar 会启动ServiceMonitor
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会启动Service,调用onNoService
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.addDataScheme("package");
mContext.registerReceiver(mBroadcastReceiver, filter);
mHandler.sendEmptyMessage(MSG_START_SERVICE);
}
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);
}
}
noService中 会去从配置文件中启动相应的statusrBar
@Override
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");
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());
}
<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string>
最终启动PhoneStatusBar
PhoneStatusBar 启动时调用父类BaseStatusBar start,创建window
createAndAddWindows();紧接着调用子类addStatusBarWindow
@Override
public void createAndAddWindows() {
addStatusBarWindow();
}
之后继续调用makeStatusBarView创建Bar的视图
private void addStatusBarWindow() {
// Put up the view
final int height = getStatusBarHeight();
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, height,
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,
PixelFormat.TRANSLUCENT);
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
lp.gravity = getStatusBarGravity();
lp.setTitle("StatusBar");
lp.packageName = mContext.getPackageName();
makeStatusBarView();
mWindowManager.addView(mStatusBarWindow, lp);
}
makeStatusBarView 会加载布局xml
protected PhoneStatusBarView makeStatusBarView() {
final Context context = mContext;
Resources res = context.getResources();
updateDisplaySize(); // populates mDisplayMetrics
loadDimens();
mIconSize = res
.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
R.layout.super_status_bar, null);
mStatusBarWindow.mService = 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);
}
});
mStatusBarView = (PhoneStatusBarView) mStatusBarWindow
.findViewById(R.id.status_bar);
mStatusBarView.setBar(this);
// volButton = (KeyButtonView) mStatusBarView.findViewById(R.id.volum);
PanelHolder holder = (PanelHolder) mStatusBarWindow
.findViewById(R.id.panel_holder);
mStatusBarView.setPanelHolder(holder);
mNotificationPanel = (NotificationPanelView) mStatusBarWindow
.findViewById(R.id.notification_panel);
mNotificationPanel.setStatusBar(this);
mNotificationPanelIsFullScreenWidth = (mNotificationPanel
.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT);
// make the header non-responsive to clicks
mNotificationPanel.findViewById(R.id.header).setOnTouchListener(
new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true; // e eats everything
}
});
if (!ActivityManager.isHighEndGfx()) {
mStatusBarWindow.setBackground(null);
mNotificationPanel.setBackground(new FastColorDrawable(context
.getResources().getColor(
R.color.notification_panel_solid_background)));
}
if (ENABLE_HEADS_UP) {
mHeadsUpNotificationView = (HeadsUpNotificationView) View.inflate(
context, R.layout.heads_up, null);
mHeadsUpNotificationView.setVisibility(View.GONE);
mHeadsUpNotificationView.setBar(this);
}
if (MULTIUSER_DEBUG) {
mNotificationPanelDebugText = (TextView) mNotificationPanel
.findViewById(R.id.header_debug_info);
mNotificationPanelDebugText.setVisibility(View.VISIBLE);
}
updateShowSearchHoldoff();
}
顶层View:super_status_bar.xml: 内含 status_bar.xml 和 PanelHolder
所以如果只是一般修改顶层状态栏的视图,修改status_bar.xml和PhoneStatusBar这两个类即可。
浙公网安备 33010602011771号