对于Phone来说SystemUI指的是:StatusBar(状态栏)、NavigationBar(导航栏)、Keyguard(锁屏)等等。
启动后Phone界面上的信号,蓝牙标志,Wifi标志等等这些状态显示标志都会在StatusBar上显示。当我们的设备开机后,首先需要给用户呈现的就是各种界面同时也包括了我们的SystemUI,因此对于整个Android系统来说,SystemUI都有举足轻重的作用。
本篇主要解析SystemUI中StatusBar的代码流程。
SystemServer.java
从AndroidManifest.xml中可以看到SystemUIService,
<service android:name="SystemUIService"
android:exported="true"
/>
上面的SystemUIService是在SystemServer中启动的
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);
}
4.2、启动相应的服务
SystemUIService.java
在SystemUIService中的onCreate()方法中调用了SystemUIApplication的startServicesIfNeeded()方法.
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
}
而在SystemUIApplication中,首先把需要启动的services添加到一个数组中
private final Class>[] SERVICES = new Class[] {
com.android.systemui.keyguard.KeyguardViewMediator.class,
com.android.systemui.recent.Recents.class,
com.android.systemui.volume.VolumeUI.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
};
然后实例化一个对象:
private final SystemUI[] mServices = new SystemUI[SERVICES.length];
然后正式启动需要的服务:
public void startServicesIfNeeded() {
.....
Log.v(TAG, "Starting SystemUI services.");
final int N = SERVICES.length;
for (int i=0; i Class> cl = SERVICES[i]; if (DEBUG) Log.d(TAG, "loading: " + cl); try { mServices[i] = (SystemUI)cl.newInstance(); } ........ mServices[i].mContext = this; mServices[i].mComponents = mComponents; if (DEBUG) Log.d(TAG, "running: " + mServices[i]); mServices[i].start(); ...... } 4.3、启动SystemBar SystemBars.java 已com.android.systemui.statusbar.SystemBars.class为例: 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.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.addDataScheme("package"); mContext.registerReceiver(mBroadcastReceiver, filter); mHandler.sendEmptyMessage(MSG_START_SERVICE); } 主线程接受消息后调用startService启动服务. private final Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch(msg.what) { case MSG_START_SERVICE: startService(); 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); } } private ComponentName getComponentNameFromSetting() { String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(), mSettingKey, UserHandle.USER_CURRENT); return cn == null ? null : ComponentName.unflattenFromString(cn); } SystemBars.java @Override public void onNoService() { if (DEBUG) Log.d(TAG, "onNoService"); createStatusBarFromConfig(); // fallback to using an in-process implementation } private void 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); } ..... try { mStatusBar = (BaseStatusBar) cls.newInstance(); } .... mStatusBar.mContext = mContext; mStatusBar.mComponents = mComponents; //这里是调用的BaseStatusBar的start()方法,当有子类继承时,直接调用. mStatusBar.start(); } PhoneBar.java @Override public void start() { mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); updateDisplaySize(); mScrimSrcModeEnabled = mContext.getResources().getBoolean( R.bool.config_status_bar_scrim_behind_use_src); //PhoneBar继承了BaseStatusBar,所以也需要重写基类的方法,同时调用基类的start(). super.start(); // calls createAndAddWindows() mMediaSessionManager= (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE); // TODO: use MediaSessionManager.SessionListener to hook us up to future updates // in session state addNavigationBar(); // Lastly, call to the icon policy to install/update all the icons. mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController); mSettingsObserver.onChange(false); // set up mHeadsUpObserver.onChange(true); // set up } BaseStatusBar.java public void start() { ........ mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); ....... // Connect in to the status bar manager service StatusBarIconList iconList = new StatusBarIconList(); mCommandQueue = new CommandQueue(this, iconList); int[] switches = new int[8]; ArrayList try { mBarService.registerStatusBar(mCommandQueue, iconList, switches, binders); } createAndAddWindows(); ...... // Set up the initial icon state int N = iconList.size(); int viewIndex = 0; for (int i=0; i StatusBarIcon icon = iconList.getIcon(i); if (icon != null) { addIcon(iconList.getSlot(i), i, viewIndex, icon); viewIndex++; } } ......... } BaseStatusBar.java这里的createAndAddWindows和addIcon等的实现是在BaseStatusBar的子类中,以PhoneStatusBar.java为例: public void createAndAddWindows() { addStatusBarWindow(); } private void addStatusBarWindow() { makeStatusBarView(); mStatusBarWindowManager = new StatusBarWindowManager(mContext); mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); } protected PhoneStatusBarView makeStatusBarView() { ....... //定义StatusBarWindow 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); }}); //定义StatusBarView mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar); mStatusBarView.setBar(this); PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder); mStatusBarView.setPanelHolder(holder); mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById( R.id.notification_panel); mNotificationPanel.setStatusBar(this); ........ //定义expanded status bar mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label); mShowCarrierInPanel = (mCarrierLabel != null); ......... return mStatusBarView; } 前面提到,在BaseStatusBar.start()中调用addIcon去加载icon,其实现也在PhoneStatusBar.java中。 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { //初始化StatusBarIconView StatusBarIconView view = new StatusBarIconView(mContext, slot, null); view.set(icon);//加载icon //将设置好icon的StatusBarIconView加载到mStatusIcons布局中 mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, mIconSize)); view = new StatusBarIconView(mContext, slot, null); view.set(icon); mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, mIconSize)); } 通过查看StatusBarIconView的继承关系我们可以发现public class StatusBarIconView extends AnimatedImageView ,继续跟踪可以看到public class AnimatedImageView extends ImageView,也就是说我们的StatusBarIconView其实就是一个封装过的ImageView,这样自然能够盛放我们的Icons了. PhoneStatusBarPolicy.java 在前面的PhoneStatusBar.start()中, 开始icon加载: // Lastly, call to the icon policy to install/update all the icons. mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController); 从PhoneStatusBarPolicy的构造参数中,可以看到: public PhoneStatusBarPolicy(Context context, CastController cast, HotspotController hotspot) { mContext = context; mCast = cast; mHotspot = hotspot; mService =(StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE); // listen for broadcasts IntentFilter filter = new IntentFilter(); filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED); filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED); filter.addAction(Intent.ACTION_USER_SWITCHED); // SPRD: fixbug421569 ADD headset icon in statusbar filter.addAction(Intent.ACTION_HEADSET_PLUG); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); // TTY status mService.setIcon(SLOT_TTY, R.drawable.stat_sys_tty_mode, 0, null); mService.setIconVisibility(SLOT_TTY, false); ......... } 对象mService属于StatusBarManager的实例,所以会进入StatusBarManager类: StatusBarManager.java 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); } } StatusBarManagerService.java public class StatusBarManagerService extends IStatusBarService.Stub { private volatile IStatusBar mBar; private StatusBarIconList mIcons = new StatusBarIconList(); public void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription) { enforceStatusBar(); synchronized (mIcons) { int index = mIcons.getSlotIndex(slot); StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.OWNER, iconId, iconLevel, 0,contentDescription); mIcons.setIcon(index, icon); if (mBar != null) { try { mBar.setIcon(index, icon); } catch (RemoteException ex) { } } } } StatusBarIconList.java public void setIcon(int index, StatusBarIcon icon) { mIcons[index] = icon.clone(); } CommandQueue.java public class CommandQueue extends IStatusBar.Stub { private StatusBarIconList mList; private Callbacks mCallbacks; private Handler mHandler = new H(); ... 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(); } } } 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 { List.setIcon(index, icon); mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex,old, icon); } break; } 接下来又是回到BaseStatusBar.java中,接着回到PhoneStatusBar中执行addIcon(): public abstract class BaseStatusBar extends SystemUI implements CommandQueue{ public class PhoneStatusBar extends BaseStatusBar implements DemoMode{ public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { StatusBarIconView view = new StatusBarIconView(mContext, slot, null); view.set(icon); mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, mIconSize)); view = new StatusBarIconView(mContext, slot, null); view.set(icon); mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, mIconSize)); } 最后,将图标添加至状态栏上. 补充: StatusBarManagerService.java public StatusBarManagerService(Context context, WindowManagerService windowManager) { mContext = context; mWindowManager = windowManager; //这里加载了系统预置的所有icon,路径在:./frameworks/base/core/res/res/values/config.xml final Resources res = context.getResources(); mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.config_statusBarIcons)); LocalServices.addService(StatusBarManagerInternal.class, mInternalService); } StatusBarManagerService是在SystemServer中启动的. if (!disableSystemUI) { try { Slog.i(TAG, "Status Bar"); statusBar = new StatusBarManagerService(context, wm); ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar); } catch (Throwable e) { reportWtf("starting StatusBarManagerService", e); } } 以上是详细的对SystemUI 中的最重要的 StatusBar代码流程分析。 代码位置:/frameworks/base/packages/SystemUI 初出江湖,希望各路大神&&前辈多多指点,晚辈拜谢~~~6、相关资源位置