SytemUI流程分析

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/TabletStatusBarPowerUI是在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:

你可能感兴趣的:(android系统开发)