1. SystemUI的一些功能:
1.1. StatusBar显示系统当前状态,包括信号强度,电池电量,时间,通知图标等。
1.2. 状态栏下拉菜单,包括快捷开关,通知栏,运营商显示,日期,设置按钮,清除按钮等。
1.3. Application历史记录。
1.4. 截图。
1.5. 静态壁纸的draw处理。
1.6. CPU显示情况。
1.7. Android版本显示。
1.8. 低电量提示。
1.9. 移动数据流量超出提示。
1.10. USB提示界面。
2. SystemUI一些流程:
2.1. SystemUI启动流程
2.1.1. 解析AndroidManifest.xml,发现注册了SystemUIService
AndroidManifest.xml |
<service android:name="SystemUIService" android:exported="true" /> |
2.1.2. 对开机启动流程有一定了解的话,可以知道SystemUIService是在SystemServer中被启动的。
SystemServer.java |
staticfinalvoid 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.startService(intent); } |
2.1.3. 在SystemUIService代码分析看出,PhoneStatusBar/TabletStatusBar,PowerUI是在SystemUIService创建的时候被启动的。
SystemUIService.java |
public void onCreate() { // Pick status bar or system bar. IWindowManager wm = IWindowManager.Stub.asInterface( ServiceManager.getService(Context.WINDOW_SERVICE)); try { SERVICES[0] = wm.canStatusBarHide() ? R.string.config_statusBarComponent : R.string.config_systemBarComponent; } catch (RemoteException e) { log.w(TAG, "Failing checking whether status bar can hide", e); }
final int N = SERVICES.length; mServices = new SystemUI[N]; for (int i=0; i Class cl = chooseClass(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; Slog.d(TAG, "running: " + mServices[i]); mServices[i].start(); } } |
其中:
SERVICES[1]是com.android.systemui.power.PowerUI
从config.xml中,我们能够看到对应关系:
config_statusBarComponent– PhoneStatusBar – 手机
config_systemBarComponent– TabletStatusBar –平板电脑
wm.canStatusBarHide()这个接口,实际上是根据屏幕密度来判断的,如果屏幕密度小于600,说明设备是手机;反之,说明设备是平板电脑。
2.1.4. PhoneStatusBar启动过程中,调用它的父类,而StatusBar就是它的父类。
PhoneStatusBar.java |
public void start() { mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay();
mWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Context.WINDOW_SERVICE));
super.start(); // calls makeStatusBarView()
addNavigationBar();
//addIntruderView();
// Lastly, call to the icon policy to install/update all the icons. mIconPolicy = new PhoneStatusBarPolicy(mContext); } |
2.1.5. 当StatusBar和Notification都配置完成以后,WindowManager加载这些资源,然后画上去。
StatusBar.java |
public void start() { ...... lp.gravity = getStatusBarGravity(); lp.setTitle("StatusBar"); lp.packageName = mContext.getPackageName(); lp.windowAnimations = R.style.Animation_StatusBar; WindowManagerImpl.getDefault().addView(sb, lp); …… } |
2.2. Notification启动流程
2.2.1. application将需要在StatusBar显示的信息封装好,调用NotificationManager的notify接口。
需要进行封装的信息都存储在Notification.java里面,包括需要显示的时间,图标,内容等。
2.2.2. NotificationManagerService判断是增加/更新/删除Notification,来调用StatusBarManagerService里面相应的接口。
NotificationManagerService.java |
publicvoid enqueueNotificationInternal(String pkg, int callingUid, int callingPid, String tag, int id, int priority, Notification notification, int[] idOut){ …… if ((notification.flags&Notification.FLAG_FOREGROUND_SERVICE) != 0) { notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR; }
if (notification.icon != 0) { StatusBarNotification n = new StatusBarNotification(pkg, id, tag, r.uid, r.initialPid, notification); n.priority = r.priority;
if (old != null && old.statusBarKey != null) { r.statusBarKey = old.statusBarKey; long identity = Binder.clearCallingIdentity(); try { mStatusBar.updateNotification(r.statusBarKey, n); } finally { Binder.restoreCallingIdentity(identity); } } else { long identity = Binder.clearCallingIdentity(); try { r.statusBarKey = mStatusBar.addNotification(n); if ((n.notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0) { mAttentionLight.pulse(); } } finally { Binder.restoreCallingIdentity(identity); } } sendAccessibilityEvent(notification, pkg); } else { Slog.e(TAG, "Ignoring notification with icon==0: " + notification); if (old != null && old.statusBarKey != null) { long identity = Binder.clearCallingIdentity(); try { mStatusBar.removeNotification(old.statusBarKey); } finally { Binder.restoreCallingIdentity(identity); } } } …… } |
2.2.3. StatusBarManagerService通过aidl实现和PhoneStatusBar之间的通信,调用CommandQueue的接口。
2.2.4. CommandQueue是抽象类,它的实现是在PhoneStatusBar。
PhoneStatusBar.java |
publicvoid addNotification(IBinder key, StatusBarNotification notification) { StatusBarIconView iconView = addNotificationViews(key, notification); …… } else { // usual case: status bar visible & not immersive
// show the ticker tick(notification); } // Recalculate the position of the sliding windows and the titles. setAreThereNotifications(); updateExpandedViewPos(EXPANDED_LEAVE_ALONE); }
publicvoid updateNotification(IBinder key, StatusBarNotification notification) { …… if (contentsUnchanged && (orderUnchanged || isFirstAnyway)) { if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key); oldEntry.notification = notification; try { // Reapply the RemoteViews contentView.reapply(mContext, oldEntry.content); // update the contentIntent final PendingIntent contentIntent = notification.notification.contentIntent; if (contentIntent != null) { final View.OnClickListener listener = new NotificationClicker(contentIntent, notification.pkg, notification.tag, notification.id); oldEntry.largeIcon.setOnClickListener(listener); oldEntry.content.setOnClickListener(listener); } else { oldEntry.largeIcon.setOnClickListener(null); oldEntry.content.setOnClickListener(null); } // Update the icon. final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon, notification.notification.iconLevel, notification.notification.number, notification.notification.tickerText); if (!oldEntry.icon.set(ic)) { handleNotificationError(key, notification, "Couldn't update icon: " + ic); return; } // Update the large icon if (notification.notification.largeIcon != null) { oldEntry.largeIcon.setImageBitmap( notification.notification.largeIcon); } else { oldEntry.largeIcon.getLayoutParams().width = 0; oldEntry.largeIcon.setVisibility(View.INVISIBLE); } …… // Restart the ticker if it's still running if (updateTicker) { mTicker.halt(); tick(notification); }
// Recalculate the position of the sliding windows and the titles. setAreThereNotifications(); updateExpandedViewPos(EXPANDED_LEAVE_ALONE); }
public void removeNotification(IBinder key) { if (SPEW) Slog.d(TAG, "removeNotification key=" + key); StatusBarNotification old = removeNotificationViews(key);
if (old != null) { // Cancel the ticker if it's still running mTicker.removeEntry(old);
// Recalculate the position of the sliding windows and the titles. updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0 && !mAnimating) { animateCollapse(); } }
setAreThereNotifications(); } |
2.3. StatusBar系统图标显示流程:
和notification显示在StatusBar上面图标的流程相似。
3. SytemUI代码架构说明:
3.1. com.android.systemui
l BootReceiver:负责接收android.intent.action.BOOT_COMPLETED广播,启动LoadAverageService服务,而该广播是在开机启动结束后收到的。
l ImageWallpaper:继承WallpaperService主要负责静态壁纸的draw处理。
l LoadAverageService:在状态栏右上位置显示CPU使用情况。
l Nyandroid:设置->关于手机->Android版本,快速点击版本,画出一个小机器人,点击有提示Android 4.0: Ice CreamSandwich。
l SwipeHelper:通知栏的滑动消除通知,最近使用app情况的滑动消除,都是使用这个功能。
l SystemUI:抽象类,StatusBar的父类。
l SystemUIService:StatusBar的UI服务,负责启动低电量提示的PowerUI和PhoneStatusBar/TabletStatusBar。其中PhoneStatusBar是手机的StatusBar,而TabletStatusBar是平板电脑的StatusBar。判断依据是以density(屏幕密度)决定,如果density<600,认为是手机;反之,认为是平板电脑。
3.2. com.android.systemui.net
l NetworkOverLimitActivity:当数据流量超出settings里面的限制值,StatusBar负责弹出提示框,提醒用户流量超出限制,操作是否关闭移动数据。
3.3. com.android.systemui.power
l PowerUI:低电量提示,在电量低于20%,15%,4%的时候,分别给出提示,并播放告警提示音。
3.4. com.android.systemui.recent(application使用历史记录)
l Choreographer:
l Constants:
l RecentsCallback:
l RecentsHorizontalScrollView:
l RecentsPanelView:
l RecentsScrollViewPerformanceHelper:
l RecentsVerticalScrollView:
l RecentTasksLoader:
l TaskDescription:
3.5. com.android.systemui.screenshot
l GlobalScreenshot:按键截屏。
l TakeScreenshotService:按键截屏的服务。
3.6. com.android.systemui.statusbar
l AllPageLinearLayout:StatusBar下拉菜单快捷开关所有页面的线性布局,包括页面和指示情况。
l AnimatedImageView:StatusBar对icon的刷新,包括动态和静态icon。
l CommandQueue:
l CUMSimSignalClusterView:信号栏双卡信号和wifi的刷新,高通关于联通定制需求的修改。
l DoNotDisturb:
l LatestItemView:
l MSimSignalClusterView:信号栏双卡信号和wifi的刷新,高通原始双卡设计。
l NotificationData:通知的信息处理,包括存储和删除。
l PageLinearLayout:StatusBar下拉菜单快捷开关单页的线性布局。
l QuickSettingsViewControlor:StatusBar下拉菜单快捷开关的控制。
l QuickSettingsViewControlorCY:StatusBar下拉菜单快捷开关的控制。
l ScrollLayout:从Launcher的Workspace中提取出来,用于StatusBar的多页滑动操作。
l SignalClusterView:信号栏单卡信号和wifi的刷新,google原始设计。
l StatusBar:抽象类,具体实现在PhoneStatusBar/TabletStatusBar。
l StatusBarIconView:StatusBar对icon的处理,包括icon的缩放,绘制及通知中个数的显示。
3.7. com.android.systemui.statusbar.phone
l CarrierLabel:运营商显示。
l CloseDragHandle:打开下拉菜单的拖动处理。
l ExpandedView:下拉菜单的绘制。
l IconMerger:icon的绘制。
l NavigationBarView:
l PhoneStatusBar:手机StatusBar的整体处理,包括下拉拖动,清除按键处理,通知点击处理,StatusBar和通知icon的添加/删除/更新,新来通知的提示等等。
l PhoneStatusBarPolicy:StatusBar右边系统状态icon的指示。
l PhoneStatusBarView:PhoneStatusBar的绘制。
l Ticker:通知提示的处理,包括进来和消退。
l TickerView:通知提示的绘制。
l TrackingPatternView:没有用途。
l TrackingView:下拉条的绘制。
3.8. com.android.systemui.statusbar.policy
l AccessibilityContentDescriptions:信号,移动数据,wifi,wimax的强度值对应的文字内容描述。
l AirplaneModeController:TabletStatusBar控制飞行模式更新。
l AutoRotateController:TabletStatusBar控制自动选择屏幕选择。
l BatteryController:StatusBar控制电池刷新。
l BluetoothController:TabletStatusBar控制蓝牙状态刷新。
l BrightnessController:TabletStatusBar控制屏幕亮度。
l Clock:StatusBar控制时间刷新。
l CompatModeButton:TabletStatusBar显示兼容模式按钮。
l DateView:StatusBar控制下拉菜单日期刷新。
l DoNotDisturbController:TabletStatusBar控制防打扰。
l EventHole:
l FixedSizeDrawable:
l KeyButtonView:
l LocationController:
l MSimNetworkController:StatusBar控制双卡信号和wifi刷新。
l NetworkController:StatusBar控制单卡信号和wifi刷新。
l NotificationRowLayout:通知栏中每行通知的布局。
l Prefs:
l TelephonyIcons:信号icon的资源和定义。
l ToggleSlider:
l VolumeController:
l WifiIcons:wifi icon的资源和定义。
l WimaxIcons:wimax icon的资源和定义。
3.9. com.android.systemui.statusbar.tablet(平板电脑显示)
l CompatModePanel:
l HeightReceiver:
l HoloClock:
l InputMethodButton:
l InputMethodsPanel:
l NotificationArea:
l NotificationIconArea:
l NotificationLinearLayout:
l NotificationPanel:
l NotificationPanelTitle:
l NotificationPeekPanel:
l PanelBackgroundView:
l SettingsView:
l ShirtPocket:
l StatusBarPanel:
l TabletStatusBar:
l TabletStatusBarView:
l TabletTicker:
3.10. com.android.systemui.usb(usb显示界面)
l StorageNotification:
l UsbAccessoryUriActivity:
l UsbConfirmActivity:
l UsbDisconnectedReceiver:
l UsbPermissionActivity:
l UsbResolverActivity:
l UsbStorageActivity: