Android4.4 systemui 启动流程

Android4.4SystemUI代码启动流程

转载http://blog.csdn.net/yihongyuelan

      1.初始SystemUI

      什么是SystemUI?你或许会觉得这个问题很幼稚,界面上的布局UI显示?系统的UI?如果你是这么想的,那么就大错特错了。我们知道Android4.4ICS同时适用于PhoneTablet(TV),因此,对于Phone来说SystemUI指的是:StatusBar(状态栏)NavigationBar(导航栏)。而对于Tablet或者是TV来说SystemUI指的是:CombinedBar(包括了StatusBarNavigationBar)

      根据上面的介绍,我想大家应该知道SystemUI的具体作用了吧!也就是说我们的Phone的信号,蓝牙标志,Wifi标志等等这些状态显示标志都会在StatusBar上显示。当我们的设备开机后,首先需要给用户呈现的就是各种界面同时也包括了我们的SystemUI,因此对于整个Android系统来说,SystemUI都有举足轻重的作用,那接下来就来看看它的启动流程吧!

       2.启动流程

      这里只是单单的分析启动流程,实际上SystemUI启动过程中涉及到很多东西的调用,这里暂时不分支去介绍,后续会有相关文章的详细分析。那么对于这种分析我还是将自己的分析思路写出来,而不是直接展现已经分析好的结果,当然结果会在最后展示出来。这样做一方面有利于锻炼自己的分析能力,另一方面各位看官也可以找出分析中的利与弊从而更好的取舍。

      首先来看看SystemUI的代码位置,路径:SourceCode/frameworks/base/packages/SystemUI;其次看看它的代码梗概:

2.1

      Android4.4中,Google整合了PhoneTablet(TV)SystemUI,也就说可以根据设备的类型自动匹配相应的SystemUI。这一点是在Android2.3中是没有的。那么接下来怎么分析呢?打开AndroidManifest.xml可以看到:

[html]viewplaincopyprint?

  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  

  2.         package="com.android.systemui"  

  3.         coreApp="true"  

  4.         android:sharedUserId="android.uid.system"  

  5.         android:process="system"  

  6.         >  

  7.   

  8.     <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />  

  9.     <uses-permission android:name="android.permission.BLUETOOTH" />  

  10.     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />  

  11.     <uses-permission android:name="android.permission.GET_TASKS" />  

  12.     <uses-permission android:name="android.permission.MANAGE_USB" />  

  13.   

  14.     <application  

  15.         android:persistent="true"  

  16.         android:allowClearUserData="false"  

  17.         android:allowBackup="false"  

  18.         android:hardwareAccelerated="true"  

  19.         android:label="@string/app_label"  

  20.         android:icon="@drawable/ic_launcher_settings">  

  21.   

  22.         <!-- Broadcast receiver that gets the broadcast at boot time and starts  

  23.              up everything else.  

  24.              TODO: Should have an android:permission attribute  

  25.              -->  

  26.         <service android:name="SystemUIService"  

  27.             android:exported="true"  

  28.             />  

  29.   

  30.         <!-- started from PhoneWindowManager  

  31.              TODO: Should have an android:permission attribute -->  

  32.         <service android:name=".screenshot.TakeScreenshotService"  

  33.             android:process=":screenshot"  

  34.             android:exported="false" />  

  35.   

  36.         <service android:name=".LoadAverageService"  

  37.                 android:exported="true" />  

  38.   

  39.         <service android:name=".ImageWallpaper"  

  40.                 android:permission="android.permission.BIND_WALLPAPER"  

  41.                 android:exported="true" />  

  42.   

  43.         <receiver android:name=".BootReceiver" >  

  44.             <intent-filter>  

  45.                 <action android:name="android.intent.action.BOOT_COMPLETED" />  

  46.             </intent-filter>  

  47.         </receiver>  

  48.         ... ...  

  49.     </application>  

  50. </manifest>  

<manifestxmlns:android="http://schemas.android.com/apk/res/android"

package="com.android.systemui"

coreApp="true"

android:sharedUserId="android.uid.system"

android:process="system"

>


<uses-permissionandroid:name="android.permission.STATUS_BAR_SERVICE" />

<uses-permissionandroid:name="android.permission.BLUETOOTH" />

<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" />

<uses-permissionandroid:name="android.permission.GET_TASKS" />

<uses-permissionandroid:name="android.permission.MANAGE_USB" />


<application

android:persistent="true"

android:allowClearUserData="false"

android:allowBackup="false"

android:hardwareAccelerated="true"

android:label="@string/app_label"

android:icon="@drawable/ic_launcher_settings">


<!--Broadcast receiver that gets the broadcast at boot time and starts

upeverything else.

TODO:Should have an android:permission attribute

-->

<serviceandroid:name="SystemUIService"

android:exported="true"

/>


<!--started from PhoneWindowManager

TODO:Should have an android:permission attribute -->

<serviceandroid:name=".screenshot.TakeScreenshotService"

android:process=":screenshot"

android:exported="false"/>


<serviceandroid:name=".LoadAverageService"

android:exported="true"/>


<serviceandroid:name=".ImageWallpaper"

android:permission="android.permission.BIND_WALLPAPER"

android:exported="true"/>


<receiverandroid:name=".BootReceiver" >

<intent-filter>

<actionandroid:name="android.intent.action.BOOT_COMPLETED" />

</intent-filter>

</receiver>

......

</application>

</manifest>


 

      根据以上代码我们可以发现这其中注册了很多Service,同时也包括了广播。但这里我们只关注SystemUIService,这才是本文的主旨啊。那么首先要找到SystemUIService是如何启动的。对于Service的启动,在我以前的博文中已有提到,这里就不多说了,不外乎startService(intent)bindService(intent),它们都是以intent为对象,那intent的声明也需要SystemUIService啊,因此我们可以据此搜索关键词"SystemUIService"

      经过漫长的搜索和比对之后发现,原来,SystemUIService是在SystemServer.java中被启动的,如下所示:

[java]viewplaincopyprint?

  1. static final void startSystemUi(Context context) {  

  2.     Intent intent = new Intent();  

  3.     intent.setComponent(new ComponentName("com.android.systemui",  

  4.                 "com.android.systemui.SystemUIService"));  

  5.     Slog.d(TAG, "Starting service: " + intent);  

  6.     context.startService(intent);  

  7. }  

staticfinal void startSystemUi(Context context) {

Intentintent = new Intent();

intent.setComponent(newComponentName("com.android.systemui",

"com.android.systemui.SystemUIService"));

Slog.d(TAG,"Starting service: " + intent);

context.startService(intent);

}


这里的startSystemUi()方法则在ServerThreadrun()方法中被调用。这里提到SystemServer就不得不提及Android的启动流程,这里不会展开详细讨论具体的流程,只是简单的介绍一下大概流程,用以表明SystemServer所处的位置。

       Android的启动分为内核启动、Android启动、launcher启动,我们的SystemServer就处于Android启动中,以下是大致流程图:

                                                           init->ServiceManager->Zygote->SystemServer->......

SystemServer中,初始化了Android系统中的Java层服务,如PowerManagerServiceWindowManagerService等等,当然也包括了SystemUIService,它们通过ServiceManageraddService()方法,添加到ServiceManager的管理中。实际上,根据后面的分析这里add了一个很重要的StatusBarManagerService。这个Service在后面会用到的。

      既然到这里SystemUIService已经启动,那么我们就继续跟踪该Service吧。

      1).首先查看其onCreate()方法,如下:

[java]viewplaincopyprint?

  1. public void onCreate() {  

  2.     // Pick status bar or system bar.  

  3.     IWindowManager wm = IWindowManager.Stub.asInterface(  

  4.             ServiceManager.getService(Context.WINDOW_SERVICE));  

  5.     try {  

  6.         SERVICES[0] = wm.canStatusBarHide()//根据wm.canStatusBarHide()判断设备类型  

  7.                 ? R.string.config_statusBarComponent  

  8.                 : R.string.config_systemBarComponent;  

  9.     } catch (RemoteException e) {  

  10.         Slog.w(TAG, "Failing checking whether status bar can hide", e);  

  11.     }  

  12.   

  13.     final int N = SERVICES.length;  

  14.     mServices = new SystemUI[N];  

  15.     for (int i=0; i<N; i++) {  

  16.         Class cl = chooseClass(SERVICES[i]);  

  17.         Slog.d(TAG, "loading: " + cl);  

  18.         try {  

  19.             mServices[i] = (SystemUI)cl.newInstance();  

  20.         } catch (IllegalAccessException ex) {  

  21.             throw new RuntimeException(ex);  

  22.         } catch (InstantiationException ex) {  

  23.             throw new RuntimeException(ex);  

  24.         }  

  25.         mServices[i].mContext = this;  

  26.         Slog.d(TAG, "running: " + mServices[i]);  

  27.         mServices[i].start();  

  28.     }  

  29. }  

publicvoid onCreate() {

//Pick status bar or system bar.

IWindowManagerwm = IWindowManager.Stub.asInterface(

ServiceManager.getService(Context.WINDOW_SERVICE));

try{

SERVICES[0]= wm.canStatusBarHide()//根据wm.canStatusBarHide()判断设备类型

?R.string.config_statusBarComponent

:R.string.config_systemBarComponent;

}catch (RemoteException e) {

Slog.w(TAG,"Failing checking whether status bar can hide", e);

}


finalint N = SERVICES.length;

mServices= new SystemUI[N];

for(int i=0; i<N; i++) {

Classcl = chooseClass(SERVICES[i]);

Slog.d(TAG,"loading: " + cl);

try{

mServices[i]= (SystemUI)cl.newInstance();

}catch (IllegalAccessException ex) {

thrownew RuntimeException(ex);

}catch (InstantiationException ex) {

thrownew RuntimeException(ex);

}

mServices[i].mContext= this;

Slog.d(TAG,"running: " + mServices[i]);

mServices[i].start();

}

}


在这段代码中,通过AIDL的方式获取了WindowManager的对象wm,并调用其方法canStatusBarHide()来判断当前设备的类型,也就是说如果我们使用的Phone那么后续就会加载StatusBarNivagationBar;而如果我们设备类型是Tablet(TV)之类的(可以在配置文档里面配置),就会加载CombiedBar

       这里的canStatusBarHide()方法的具体实现是在:frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java。为什么会是这里呢?我们在Eclipse中导入源码之后,找到SystemUIService.java中的wm.canStatusBarHide()方法,通过openImplementation直接跳转到WindowsManagerService中:

[java]viewplaincopyprint?

  1. public boolean canStatusBarHide() {  

  2.     return mPolicy.canStatusBarHide();  

  3. }  

publicboolean canStatusBarHide() {

returnmPolicy.canStatusBarHide();

}


但这里我们发现canStatusBarHide()实际上是WindowManagerPolicy的对象调用的方法,而WindowManagerPolicy只是一个接口类,根据以往分析的经验可以知道,这里的WindowManagerPolicy对象所调用的canStatusBartHide()方法一定是其实现类中的方法。因此,继续通过openImplementation跳转,来到了PhoneWindownManager中:

[java]viewplaincopyprint?

  1. public boolean canStatusBarHide() {  

  2.     return mStatusBarCanHide;  

  3. }  

publicboolean canStatusBarHide() {

returnmStatusBarCanHide;

}


继续查看mSatuBarCanHide的实现,如下所示:

[java]viewplaincopyprint?

  1. // Determine whether the status bar can hide based on the size  

  2. // of the screen.  We assume sizes > 600dp are tablets where we  

  3. // will use the system bar.  

  4. int shortSizeDp = shortSize  

  5.         * DisplayMetrics.DENSITY_DEFAULT  

  6.         / DisplayMetrics.DENSITY_DEVICE;  

  7. mStatusBarCanHide = shortSizeDp < 600;  

  8. mStatusBarHeight = mContext.getResources().getDimensionPixelSize(  

  9.         mStatusBarCanHide  

  10.         ? com.android.internal.R.dimen.status_bar_height  

  11.         : com.android.internal.R.dimen.system_bar_height);  

  12.   

  13. mHasNavigationBar = mContext.getResources().getBoolean(  

  14.         com.android.internal.R.bool.config_showNavigationBar);  

//Determine whether the status bar can hide based on the size

//of the screen. We assume sizes > 600dp are tablets where we

//will use the system bar.

intshortSizeDp = shortSize

*DisplayMetrics.DENSITY_DEFAULT

/DisplayMetrics.DENSITY_DEVICE;

mStatusBarCanHide= shortSizeDp < 600;

mStatusBarHeight= mContext.getResources().getDimensionPixelSize(

mStatusBarCanHide

?com.android.internal.R.dimen.status_bar_height

:com.android.internal.R.dimen.system_bar_height);


mHasNavigationBar= mContext.getResources().getBoolean(

com.android.internal.R.bool.config_showNavigationBar);


这里通过shortSizeDp来判断当前设备的类型,如果当前屏幕的shortSizeDp<600dp,则系统会认为该设备是Phone反之则认为是Tablet。根据mStatusBarCanHide的值,设定StatusBar或者SystemBar(CombinedBar)的高度,以及是否显示NavigationBar

       继续回到我们的SystemUIService.javaonCreate()方法中,根据前面对canStatusBarHide()的判断,SERVICE[0]中将存放R.string.config_statusBarComponent或者R.string.config_systemBarComponent。它们的值具体是:

[html]viewplaincopyprint?

  1. <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string>  

  2. <string name="config_systemBarComponent" translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string>  

<stringname="config_statusBarComponent"translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string>

<stringname="config_systemBarComponent"translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string>


因为我的测试设备是Phone,那么现在SERVICE[0]中存放的就是com.android.systemui.statusbart.phone.PhoneStatusBar。查看以下代码:

[java]viewplaincopyprint?

  1. final int N = SERVICES.length;  

  2. mServices = new SystemUI[N];  

  3. for (int i=0; i<N; i++) {  

  4.     Class cl = chooseClass(SERVICES[i]);  

  5.     Slog.d(TAG, "loading: " + cl);  

  6.     try {  

  7.         mServices[i] = (SystemUI)cl.newInstance();  

  8.     } catch (IllegalAccessException ex) {  

  9.         throw new RuntimeException(ex);  

  10.     } catch (InstantiationException ex) {  

  11.         throw new RuntimeException(ex);  

  12.     }  

  13.     mServices[i].mContext = this;  

  14.     Slog.d(TAG, "running: " + mServices[i]);  

  15.     mServices[i].start();  

  16. }  

finalint N = SERVICES.length;

mServices= new SystemUI[N];

for(int i=0; i<N; i++) {

Classcl = chooseClass(SERVICES[i]);

Slog.d(TAG,"loading: " + cl);

try{

mServices[i]= (SystemUI)cl.newInstance();

}catch (IllegalAccessException ex) {

thrownew RuntimeException(ex);

}catch (InstantiationException ex) {

thrownew RuntimeException(ex);

}

mServices[i].mContext= this;

Slog.d(TAG,"running: " + mServices[i]);

mServices[i].start();

}


这些方法会分别启动两个方法,这两个方法可以从log中知道,分别是PhoneStatusBar.start()PowerUI.start()。而我们的目的是要弄清SystemUI的启动,因此现关注PhoneStatusBar.start()方法。

log信息:

06-0413:23:15.379: DEBUG/SystemUIService(396): loading: classcom.android.systemui.statusbar.phone.PhoneStatusBar

06-0413:23:16.739: DEBUG/SystemUIService(396): loading: classcom.android.systemui.power.PowerUI

      来到PhoneStatusBar.start()方法中,位于:SourceCode/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java,代码如下:

[java]viewplaincopyprint?

  1. @Override  

  2. public void start() {  

  3.     mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))  

  4.             .getDefaultDisplay();  

  5.   

  6.     mWindowManager = IWindowManager.Stub.asInterface(  

  7.             ServiceManager.getService(Context.WINDOW_SERVICE));  

  8.   

  9.     super.start(); // calls makeStatusBarView()  

  10.   

  11.     addNavigationBar();  

  12.   

  13.     //addIntruderView();  

  14.   

  15.     // Lastly, call to the icon policy to install/update all the icons.  

  16.     mIconPolicy = new PhoneStatusBarPolicy(mContext);  

  17. }  

@Override

publicvoid 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);

}


这里的重心主要是在super.start()addNavigationBar()上。目前市面上很多手机已经刷入了ICS,但是大多数是没有NavigationBar的,也就是说自己修改了源码,屏蔽了NavigationBar。继续跟踪super.start()方法,来到/SourceCode/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.javastart()方法中,代码如下:

[java]viewplaincopyprint?

  1. public void start() {  

  2.     // First set up our views and stuff.  

  3.     View sb = makeStatusBarView();  

  4.   

  5.     // Connect in to the status bar manager service  

  6.     StatusBarIconList iconList = new StatusBarIconList();  

  7.     ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>();  

  8.     ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>();  

  9.     mCommandQueue = new CommandQueue(this, iconList);  

  10.     mBarService = IStatusBarService.Stub.asInterface(  

  11.             ServiceManager.getService(Context.STATUS_BAR_SERVICE));  

  12.     int[] switches = new int[7];  

  13.     ArrayList<IBinder> binders = new ArrayList<IBinder>();  

  14.     try {  

  15.         mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,  

  16.                 switches, binders);  

  17.     } catch (RemoteException ex) {  

  18.         // If the system process isn't there we're doomed anyway.  

  19.     }  

  20.   

  21.     disable(switches[0]);  

  22.     setSystemUiVisibility(switches[1]);  

  23.     topAppWindowChanged(switches[2] != 0);  

  24.     // StatusBarManagerService has a back up of IME token and it's restored here.  

  25.     setImeWindowStatus(binders.get(0), switches[3], switches[4]);  

  26.     setHardKeyboardStatus(switches[5] != 0, switches[6] != 0);  

  27.   

  28.     // Set up the initial icon state  

  29.     int N = iconList.size();  

  30.     int viewIndex = 0;  

  31.     for (int i=0; i<N; i++) {  

  32.         StatusBarIcon icon = iconList.getIcon(i);  

  33.         if (icon != null) {  

  34.             addIcon(iconList.getSlot(i), i, viewIndex, icon);  

  35.             viewIndex++;  

  36.         }  

  37.     }  

  38.   

  39.     // Set up the initial notification state  

  40.     N = notificationKeys.size();  

  41.     if (N == notifications.size()) {  

  42.         for (int i=0; i<N; i++) {  

  43.             addNotification(notificationKeys.get(i), notifications.get(i));  

  44.         }  

  45.     } else {  

  46.         Log.wtf(TAG, "Notification list length mismatch: keys=" + N  

  47.                 + " notifications=" + notifications.size());  

  48.     }  

  49.   

  50.     // Put up the view  

  51.     final int height = getStatusBarHeight();  

  52.   

  53.     final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(  

  54.             ViewGroup.LayoutParams.MATCH_PARENT,  

  55.             height,  

  56.             WindowManager.LayoutParams.TYPE_STATUS_BAR,  

  57.             WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE  

  58.                 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING  

  59.                 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,  

  60.             // We use a pixel format of RGB565 for the status bar to save memory bandwidth and  

  61.             // to ensure that the layer can be handled by HWComposer.  On some devices the  

  62.             // HWComposer is unable to handle SW-rendered RGBX_8888 layers.  

  63.             PixelFormat.RGB_565);  

  64.       

  65.     // the status bar should be in an overlay if possible  

  66.     final Display defaultDisplay   

  67.         = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))  

  68.             .getDefaultDisplay();  

  69.   

  70.     // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags.  The status bar occupies  

  71.     // very little screen real-estate and is updated fairly frequently.  By using CPU rendering  

  72.     // for the status bar, we prevent the GPU from having to wake up just to do these small  

  73.     // updates, which should help keep power consumption down.  

  74.   

  75.     lp.gravity = getStatusBarGravity();  

  76.     lp.setTitle("StatusBar");  

  77.     lp.packageName = mContext.getPackageName();  

  78.     lp.windowAnimations = R.style.Animation_StatusBar;  

  79.     WindowManagerImpl.getDefault().addView(sb, lp);  

  80.   

  81.     if (SPEW) {  

  82.         Slog.d(TAG, "Added status bar view: gravity=0x" + Integer.toHexString(lp.gravity)   

  83.                + " icons=" + iconList.size()  

  84.                + " disabled=0x" + Integer.toHexString(switches[0])  

  85.                + " lights=" + switches[1]  

  86.                + " menu=" + switches[2]  

  87.                + " imeButton=" + switches[3]  

  88.                );  

  89.     }  

  90.   

  91.     mDoNotDisturb = new DoNotDisturb(mContext);  

  92. }  

publicvoid start() {

//First set up our views and stuff.

Viewsb = makeStatusBarView();


//Connect in to the status bar manager service

StatusBarIconListiconList = new StatusBarIconList();

ArrayList<IBinder>notificationKeys = new ArrayList<IBinder>();

ArrayList<StatusBarNotification>notifications = new ArrayList<StatusBarNotification>();

mCommandQueue= new CommandQueue(this, iconList);

mBarService= IStatusBarService.Stub.asInterface(

ServiceManager.getService(Context.STATUS_BAR_SERVICE));

int[]switches = new int[7];

ArrayList<IBinder>binders = new ArrayList<IBinder>();

try{

mBarService.registerStatusBar(mCommandQueue,iconList, notificationKeys, notifications,

switches,binders);

}catch (RemoteException ex) {

//If the system process isn't there we're doomed anyway.

}


disable(switches[0]);

setSystemUiVisibility(switches[1]);

topAppWindowChanged(switches[2]!= 0);

//StatusBarManagerService has a back up of IME token and it's restoredhere.

setImeWindowStatus(binders.get(0),switches[3], switches[4]);

setHardKeyboardStatus(switches[5]!= 0, switches[6] != 0);


//Set up the initial icon state

intN = iconList.size();

intviewIndex = 0;

for(int i=0; i<N; i++) {

StatusBarIconicon = iconList.getIcon(i);

if(icon != null) {

addIcon(iconList.getSlot(i),i, viewIndex, icon);

viewIndex++;

}

}


//Set up the initial notification state

N= notificationKeys.size();

if(N == notifications.size()) {

for(int i=0; i<N; i++) {

addNotification(notificationKeys.get(i),notifications.get(i));

}

}else {

Log.wtf(TAG,"Notification list length mismatch: keys=" + N

+" notifications=" + notifications.size());

}


//Put up the view

finalint height = getStatusBarHeight();


finalWindowManager.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,

//We use a pixel format of RGB565 for the status bar to save memorybandwidth and

//to ensure that the layer can be handled by HWComposer. On somedevices the

//HWComposer is unable to handle SW-rendered RGBX_8888 layers.

PixelFormat.RGB_565);

//the status bar should be in an overlay if possible

finalDisplay defaultDisplay

=((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))

.getDefaultDisplay();


//We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags. Thestatus bar occupies

//very little screen real-estate and is updated fairly frequently. Byusing CPU rendering

//for the status bar, we prevent the GPU from having to wake up just todo these small

//updates, which should help keep power consumption down.


lp.gravity= getStatusBarGravity();

lp.setTitle("StatusBar");

lp.packageName= mContext.getPackageName();

lp.windowAnimations= R.style.Animation_StatusBar;

WindowManagerImpl.getDefault().addView(sb,lp);


if(SPEW) {

Slog.d(TAG,"Added status bar view: gravity=0x" +Integer.toHexString(lp.gravity)

+" icons=" + iconList.size()

+" disabled=0x" + Integer.toHexString(switches[0])

+" lights=" + switches[1]

+" menu=" + switches[2]

+" imeButton=" + switches[3]

);

}


mDoNotDisturb= new DoNotDisturb(mContext);

}


在这里,完成了SystemUI的整个初始化以及设置过程,并最终呈现到界面上。在StatusBar中的start()方法主要完成了以下几个工作:首先获取需要在StatusBar上显示的各种icons。然后初始化一些属性。最后通过WindowManageraddView方法将StatusBar显示出来。分析到这里可能有人会问了,明明说分析的是SystemUI的嘛,怎么最后变成StatusBar了呢?如果你硬要说我跑题那我也没有办法,回过头去看看addNavigationBar(),你会发现和StatusBar的加载几乎一致,因此没必要再详述了。如果细心阅读了的朋友肯定会发现这句代码:

mBarService=IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE));

这不正是我们前面addStatusBarManagerSerivce吗?这里通过AIDL的方式来获取它的对象。

       整个代码执行的时序图如图2.2所示:

2.2

        3.总结

       Android4.4SystemUI加载启动的过程大致就是这样。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值