SystemUI源码分析

此篇文章针对android5.1 systemUI源码进行分析

下面我们进行分析,
1.1 frameworks/base/packages/SystemUI/AndroidManifest.xml
我们先来看下这个文件下的内容:
android:name=”.SystemUIApplication”
android:persistent=”true”
android:allowClearUserData=”false”
android:allowBackup=”false”
android:hardwareAccelerated=”true”
android:label=”@string/app_label”
android:icon=”@drawable/icon”
android:process=”com.android.systemui”
android:supportsRtl=”true”
android:theme=”@style/systemui_theme”>
………………………………………
android:exported=”true”
/>
android:process=”:screenshot”
android:exported=”false” />
android:exported=”true” />
android:permission=”android.permission.BIND_WALLPAPER”
android:exported=”true” />
………………………………………
………………………………………
………………………………………

 我们可以看到,AndroidManifest.xml注册了很多的service 和 广播,那么是怎么启动的服务呢?
    我们继续看下这个所注册的三个服务,
               SystemUIService /
               .screenshot.TakeScreenshotService /
              .LoadAverageService/.ImageWallpaper

这三个服务是怎么启动的呢,我们仔细来看下这句注释:
“Broadcast receiver that gets the broadcast at boot time and starts up everything else.”
看里这个注释,我们就应该知道,首先启动的应该是SystemUIService这个服务。
那么SystemUIService这个服务是怎么启动的呢,启动服务我们知道多数的通用方法是
startService(intent)和bindService(intent)
那么我们就在SystemUI下全局搜索“SystemUIService”,可以看下结果
frameworks/base/services/java/com/android/server/SystemServer.java: “com.android.systemui.SystemUIService”));
我们打开SystemServer.java这个文件来看下是怎么调用的,

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

原来是 intent.setComponent()启动了SystemUIService这个服务。

1.2 frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java

下面我们来分析一下SystemUIService.java:

@Override
    public void onCreate() {
        super.onCreate();
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
    }

在oSystemUIService中的onCreate只调用了
((SystemUIApplication) getApplication()).startServicesIfNeeded();
这么一个语句,下面我们来看看startServicesIfNeeded()这里面有啥东西

public void startServicesIfNeeded() {        
    if (mServicesStarted) {         
        return;
    }                               
    if (!mBootCompleted) {          
        // check to see if maybe it was already completed long before we began
        // see ActivityManagerService.finishBooting()
        if ("1".equals(SystemProperties.get("sys.boot_completed"))) { 
            mBootCompleted = true;  
            if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");        
        }
    }

    Log.v(TAG, "Starting SystemUI services.");
    final int N = SERVICES.length;  
    for (int i=0; i<N; i++) {       
        Class<?> cl = SERVICES[i];  
        if (DEBUG) 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 = mComponents;  
        if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
        mServices[i].start();

        if (mBootCompleted) {
            mServices[i].onBootCompleted();      
        }
    }
    mServicesStarted = true;
}

}

在这里我们看到mServices启动了不止一个服务,那么这些都是那些服务呢,
我们看这个语句
mServices[i] = (SystemUI)cl.newInstance();
这里的语句付给了mServices[i].start()一个对象,
我们往上去找,可以看到这Class cl = SERVICES[i];
cl是SERVICES[i]这个数组中的一个值,在java的定义中,我们可以看到这个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
};
SERVICES中添加要start的所有服务选项,这里,我们重点关注一下
com.android.systemui.statusbar.SystemBars.class,
这是我们进行下一步分析的重要线索。

1.3 frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java

我们看下SystemBars.java这个文件中的start()中到底写了些什么东西,

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
}   

这里,启动了另外一个服务mServiceMonitor,除了启动这个服务外什么都没有做,那我们继续往下面去看看
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
在这个文件里面,对star()方法的调用
public void start() {
…………………
mHandler.sendEmptyMessage(MSG_START_SERVICE);
}
在这个函数里,这个sendEmptyMessage语句是一个非常关键的调用,这个调用也是启动了一个服务,我们去看下这个mHandler都干了些啥事,

private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what) {
case MSG_START_SERVICE:
startService();
break;
case MSG_CONTINUE_START_SERVICE:
continueStartService();
break;
case MSG_STOP_SERVICE:
stopService();
break;
case MSG_PACKAGE_INTENT:
packageIntent((Intent)msg.obj);
break;
case MSG_CHECK_BOUND:
checkBound();
break;
case MSG_SERVICE_DISCONNECTED:
serviceDisconnected((ComponentName)msg.obj);
break;
}
}
};

在这里我们看到
case MSG_START_SERVICE:
startService();
break;
这里才是真正的启动了一个服务,mCallbacks.onNoService();
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);
}
}
我们来看下if (mServiceName == null) 这个判断的结果是怎么来的,
private ComponentName getComponentNameFromSetting() {
String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(),
mSettingKey, UserHandle.USER_CURRENT);
return cn == null ? null : ComponentName.unflattenFromString(cn);
}
由以上的代码我们可知,cn返回的是null值,在startService()中就调用了 mCallbacks.onNoService();

我们来看下frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
onNoService()的调用,

public void onNoService() {
if (DEBUG) Log.d(TAG, “onNoService”);
createStatusBarFromConfig();
}

private void createStatusBarFromConfig() {
…………………………………..
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mComponents;
mStatusBar.start();
…………………………………..
}
在createStatusBarFromConfig()中终于有了实际的行动来进行关于status的一下相关操作了,一直到这里,其实前面所做的都是一些服务的调用,并没有对screen进行任何的view类级别的操作,其实上面的流程,只是在系统框架先进行的一些服务注册,及逻辑方面的一些准备。

1.4 frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
下面我们来着重分析下BaseStatusBar.start().

public void start() {
…………………….
createAndAddWindows();
…………………….
}
在BaseStatusBar.start()中,这个语句是重点中的重点,是对整个status的布局,我们进到这个函数中去看个究竟
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
public void createAndAddWindows() {
addStatusBarWindow();
}
在createAndAddWindows中也只是调用了这么一个函数,没有其他的东西了,我们接着看
addStatusBarWindow();
其实在addStatusBarWindow所做的东西也不多,就是两步
makeStatusBarView()和mStatusBarWindowManager.add();
但是这两步确实非常重要的两部。
private void addStatusBarWindow() {
makeStatusBarView();
mStatusBarWindowManager = new StatusBarWindowManager(mContext);
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}

我们先来看看akeStatusBarView()这个里面是什么情况
protected PhoneStatusBarView makeStatusBarView() {
…………………………
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,R.layout.super_status_bar, null);
…………………………..

}

我们在super_status_bar.xml中这个文件可以看到
<-com.android.systemui.statusbar.phone.StatusBarWindowView
//xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:fitsSystemWindows=”true”>
…………………………..
<-com.android.systemui.statusbar.ScrimView android:id=”@+id/scrim_behind”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:importantForAccessibility=”no” />

<include layout="@layout/status_bar"
    android:layout_width="match_parent"
    android:layout_height="@dimen/status_bar_height" />

……………………………………
<-com.android.systemui.statusbar.phone.PanelHolder
android:id=”@+id/panel_holder”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:background=”@color/transparent” >
<-include layout=”@layout/status_bar_expanded”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:visibility=”gone” />
<-/com.android.systemui.statusbar.phone.PanelHolder>
在这里,我们主要注意上面所示status_bar / panel_holder才是我们要关注的重中之重,是我们整个view的最直观的显示,也是客户化定制比较多的地方,下面我们来进行进一步的细分。

1.5 frameworks/base/packages/SystemUI/res/layout/status_bar.xml

<-com.android.systemui.statusbar.phone.PhoneStatusBarView
23 xmlns:android=”http://schemas.android.com/apk/res/android”
24 xmlns:systemui=”http://schemas.android.com/apk/res/com.android.systemui”
25 android:id=”@+id/status_bar”
26 android:background=”@drawable/system_bar_background”
27 android:orientation=”vertical”
28 android:focusable=”true”
29 android:descendantFocusability=”afterDescendants”
30 >
………………………………
71 <-com.android.systemui.statusbar.phone.IconMerger android:id=”@+id/notificationIcons”
72 android:layout_width=”match_parent”
73 android:layout_height=”match_parent”
74 android:layout_alignParentStart=”true”
75 android:gravity=”center_vertical”
76 android:orientation=”horizontal”/>
77 <-/com.android.keyguard.AlphaOptimizedLinearLayout>
78 <-/com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
79
80 <-com.android.keyguard.AlphaOptimizedLinearLayout android:id=”@+id/system_icon_area”
81 android:layout_width=”wrap_content”
82 android:layout_height=”match_parent”
83 android:orientation=”horizontal”
84 >
85
86 <-include layout=”@layout/system_icons” />
87
88 <-com.android.systemui.statusbar.policy.Clock
89 android:id=”@+id/clock”
90 android:textAppearance=”@style/TextAppearance.StatusBar.Clock”
91 android:layout_width=”wrap_content”
92 android:layout_height=”match_parent”
93 android:singleLine=”true”
94 android:paddingStart=”7dp”
95 android:gravity=”center_vertical|start”
96 />
97 <-/com.android.keyguard.AlphaOptimizedLinearLayout>
98 <-/LinearLayout>

我们来看下对比图是怎样的:

———–android:id= “@+id/notificationIcons”
该部分内容显示USB/T卡/wifi链接等一些通知选项图标。
———–android:id=”@+id/system_icon_area”
该部分内容主要显示的是SIM卡/电池/时间等…………………

1.6 frameworks/base/packages/SystemUI/res/layout/status_bar_expanded.xml
我们先来看看这个文件中所码的内容:

<-com.android.systemui.statusbar.phone.NotificationPanelView
22 xmlns:android=”http://schemas.android.com/apk/res/android”
23 xmlns:systemui=”http://schemas.android.com/apk/res/com.android.systemui”
24 android:id=”@+id/notification_panel”
25 android:layout_width=”match_parent”
26 android:layout_height=”match_parent”
27 android:background=”@android:color/transparent”
28 >
29
30 <-include
31 layout=”@layout/carrier_label_group”
32 android:layout_height=”wrap_content”
33 android:layout_width=”match_parent”
34 android:layout_marginBottom=”@dimen/close_handle_height”
35 android:layout_gravity=”bottom”
36 />
37
38 <-include
39 layout=”@layout/keyguard_status_view”
40 android:layout_height=”wrap_content”
41 android:visibility=”gone” />
42
43 <-TextView
44 android:id=”@+id/emergency_calls_only”
45 android:textAppearance=”@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly”
46 android:layout_height=”wrap_content”
47 android:layout_width=”match_parent”
48 android:padding=”4dp”
49 android:gravity=”center”
50 android:visibility=”gone”
51 />
52
53 <-com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
54 android:layout_width=”match_parent”
55 android:layout_height=”match_parent”
56 android:layout_gravity=”@integer/notification_panel_layout_gravity”
57 android:id=”@+id/notification_container_parent”
58 android:clipToPadding=”false”
59 android:clipChildren=”false”>
60
<-com.android.systemui.statusbar.phone.ObservableScrollView
62 android:id=”@+id/scroll_view”
63 android:layout_width=”@dimen/notification_panel_width”
64 android:layout_height=”match_parent”
65 android:layout_gravity=”@integer/notification_panel_layout_gravity”
66 android:scrollbars=”none”
67 android:overScrollMode=”never”
68 android:fillViewport=”true”>
69 <-LinearLayout
70 android:layout_width=”match_parent”
71 android:layout_height=”wrap_content”
72 android:orientation=”vertical”>
73 <-include
74 layout=”@layout/qs_panel”
75 android:layout_marginTop=”@dimen/status_bar_header_height_expanded”
76 android:layout_width=”match_parent”
77 android:layout_height=”wrap_content”
78 android:layout_marginLeft=”@dimen/notification_side_padding”
79 android:layout_marginRight=”@dimen/notification_side_padding”/>
80
81
82
83 <-View
84 android:id=”@+id/reserve_notification_space”
85 android:layout_height=”@dimen/min_stack_height”
86 android:layout_width=”match_parent”
87 android:layout_marginTop=”@dimen/notifications_top_padding” />
88
89 <-View
90 android:layout_height=”@dimen/notification_side_padding”
91 android:layout_width=”match_parent” />
92 <-/LinearLayout>
93 <-/com.android.systemui.statusbar.phone.ObservableScrollView>
94
95 <-com.android.systemui.statusbar.stack.NotificationStackScrollLayout
96 android:id=”@+id/notification_stack_scroller”
97 android:layout_width=”@dimen/notification_panel_width”
98 android:layout_height=”match_parent”
99 android:layout_gravity=”@integer/notification_panel_layout_gravity”
100 android:layout_marginTop=”-10dp”
101 android:layout_marginBottom=”@dimen/close_handle_underlap”
102 android:importantForAccessibility=”no” />
103
104 <-ViewStub
105 android:id=”@+id/keyguard_user_switcher”
106 android:layout=”@layout/keyguard_user_switcher”
android:layout_height=”match_parent”
108 android:layout_width=”match_parent” />
109
110 <-include
111 layout=”@layout/keyguard_status_bar”
112 android:visibility=”invisible” />
113
114 <-/com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
115
116 <-include
117 layout=”@layout/keyguard_bottom_area”
118 android:visibility=”gone” />
119
120 <-include layout=”@layout/status_bar_expanded_header” />
121
122 <-com.android.systemui.statusbar.AlphaOptimizedView
123 android:id=”@+id/qs_navbar_scrim”
124 android:layout_height=”96dp”
125 android:layout_width=”match_parent”
126 android:layout_gravity=”bottom”
127 android:visibility=”invisible”
128 android:background=”@drawable/qs_navbar_scrim” />
129
130 <-/com.android.systemui.statusbar.phone.NotificationPanelView>

我们先来看看真机上的效果图:
这里写图片描述
这就是我们真机上的效果图,这是我们status展开后的效果图,没有展开的我们上面已经分析过了,这里就不再重复。

下面我们来看下这个效果图主要是由那些部分组合而成的,
这里写图片描述
这个部分我们看到,并没有在这status_bar_expanded.xml中直接进行定义,但是我们可以通过
android:id=”@+id/header”
这个ID反方向去寻找在status_bar_expanded.xml中是怎么调用的,我们通过搜索知道
android:id=”@+id/header”
这个其实是在
status_bar_expanded_header.xml
这里进行定义的,找到这里,我们就能清楚的看到,其实在status_bar_expanded.xml中有对status_bar_expanded_header.xml的调用,
<-include layout=”@layout/status_bar_expanded_header” />
到了这里,我们就不继续对status_bar_expanded_header.xml这个文件进行分析了,进入到该文件中,我们能清楚明白的看到各个id的应用。

下面我们继续看最地下的通知信息栏是在哪里加载的,如下如所示:
这里写图片描述
在这里,该部分内容是在
<-com.android.systemui.statusbar.stack.NotificationStackScrollLayout
96 android:id=”@+id/notification_stack_scroller”
97 android:layout_width=”@dimen/notification_panel_width”
98 android:layout_height=”match_parent”
99 android:layout_gravity=”@integer/notification_panel_layout_gravity”
100 android:layout_marginTop=”-10dp”
101 android:layout_marginBottom=”@dimen/close_handle_underlap”
102 android:importantForAccessibility=”no” />
这里进行添加的,我们可以看到otification_stack_scroller其实在这个效果图里面是没有展开的,而是重叠在一起的,但是我们在这里不进行进一步的分析。

现在,我们来看最后一部分内容,就是快捷键的使用,我们先看下效果图,如下:
这里写图片描述
通过android:id的定位,我们知道,该部分内容是在这里
<-com.android.systemui.statusbar.phone.ObservableScrollView
62 android:id=”@+id/scroll_view”
63 android:layout_width=”@dimen/notification_panel_width”
64 android:layout_height=”match_parent”
65 android:layout_gravity=”@integer/notification_panel_layout_gravity”
66 android:scrollbars=”none”
67 android:overScrollMode=”never”
68 android:fillViewport=”true”>
69 <-LinearLayout
70 android:layout_width=”match_parent”
71 android:layout_height=”wrap_content”
72 android:orientation=”vertical”>
73 <-include
74 layout=”@layout/qs_panel”
75 android:layout_marginTop=”@dimen/status_bar_header_height_expanded”
76 android:layout_width=”match_parent”
77 android:layout_height=”wrap_content”
78 android:layout_marginLeft=”@dimen/notification_side_padding”
79 android:layout_marginRight=”@dimen/notification_side_padding”/>
80
81
82 <-!– Layout height: notification_min_height + bottom_stack_peek_amount –>
83 <-View
84 android:id=”@+id/reserve_notification_space”
85 android:layout_height=”@dimen/min_stack_height”
86 android:layout_width=”match_parent”
87 android:layout_marginTop=”@dimen/notifications_top_padding” />
88
89 <-View
90 android:layout_height=”@dimen/notification_side_padding”
91 android:layout_width=”match_parent” />
92 <-/LinearLayout>
93 <-/com.android.systemui.statusbar.phone.ObservableScrollView>
进行加载.

2.0 下面我们来对相关的各个模块一一进行剖析
2.0.1 下面我们先来分析 android:id=”@+id/brightness_slider”
先上图:
这里写图片描述
我们全局搜索“brightness_slider”看看有什么收获
1 33 frameworks/base/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml <<>>
android:id=”@+id/brightness_slider”
2 109 frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java <<>>
(ToggleSlider) findViewById(R.id.brightness_slider));
3 126 frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java <<>>
ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider);
4 127 frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java <<>>
ToggleSlider mirror = (ToggleSlider) c.getMirror().findViewById(R.id.brightness_slider);
5 51 frameworks/base/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java <<>>
final ToggleSlider slider = (ToggleSlider) findViewById(R.id.brightness_slider);

从这里我们看到,brightness_slider是在quick_settings_brightness_dialog.xml里添加的id,那么我们就在看看是哪里调用的quick_settings_brightness_dialog.xml文件,
1 99 frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java <>
R.layout.quick_settings_brightness_dialog, this, false);
2 48 frameworks/base/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java <>
setContentView(R.layout.quick_settings_brightness_dialog);
原来是在QSPanel.java中调用的xml,
mBrightnessView = LayoutInflater.from(context).inflate(R.layout.quick_settings_brightness_dialog, this, false);
为了更直观的看到这个调用顺序,我们在
public QSPanel(Context context, AttributeSet attrs)
中把调用堆栈给打印出来看看:
0java.lang.Throwable
at com.android.systemui.qs.QSPanel.(QSPanel.java:89)
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at android.view.LayoutInflater.createView(LayoutInflater.java:607)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:916)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:802)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:916)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:802)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
at android.view.View.inflate(View.java:18547)
at com.android.systemui.statusbar.phone.PhoneStatusBar.makeStatusBarView(PhoneStatusBar.java:648)
at com.android.systemui.statusbar.phone.PhoneStatusBar.addStatusBarWindow(PhoneStatusBar.java:3087)
at com.android.systemui.statusbar.phone.PhoneStatusBar.createAndAddWindows(PhoneStatusBar.java:3083)
at com.android.systemui.statusbar.BaseStatusBar.start(BaseStatusBar.java:564)
at com.android.systemui.statusbar.phone.PhoneStatusBar.start(PhoneStatusBar.java:598)
at com.android.systemui.statusbar.SystemBars.createStatusBarFromConfig(SystemBars.java:107)
at com.android.systemui.statusbar.SystemBars.onNoService(SystemBars.java:59)
at com.android.systemui.statusbar.ServiceMonitor.startService(ServiceMonitor.java:228)
at com.android.systemui.statusbar.ServiceMonitor.access000(ServiceMonitor.java:49)atcom.android.systemui.statusbar.ServiceMonitor 1.handleMessage(ServiceMonitor.java:73)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5345)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:947)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:742)

从上面的调用中我们可以看到,
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
的protected PhoneStatusBarView makeStatusBarView(){};
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,R.layout.super_status_bar, null);
这个语句中动态加载的。

2.1 设置header视图中的位置信息: updateHeaderShade()

at com.android.systemui.statusbar.phone.NotificationPanelView.**updateHeaderShade**(NotificationPanelView.java:1510)
    at com.android.systemui.statusbar.phone.NotificationPanelView.updateHeader(NotificationPanelView.java:1502)
    at com.android.systemui.statusbar.phone.NotificationPanelView.onHeightUpdated(NotificationPanelView.java:1379)
    at com.android.systemui.statusbar.phone.PanelView.setExpandedHeightInternal(PanelView.java:660)
    at com.android.systemui.statusbar.phone.PanelView.onTouchEvent(PanelView.java:315)
    at com.android.systemui.statusbar.phone.NotificationPanelView.onTouchEvent(NotificationPanelView.java:707)
    at com.android.systemui.statusbar.phone.PanelBar.onTouchEvent(PanelBar.java:131)
    at com.android.systemui.statusbar.phone.PhoneStatusBarView.onTouchEvent(PhoneStatusBarView.java:158)
    at android.view.View.**dispatchTouchEvent**(View.java:8481)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2432)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2103)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132)
    at com.android.systemui.statusbar.phone.StatusBarWindowView.dispatchTouchEvent(StatusBarWindowView.java:165)
    at android.view.View.dispatchPointerEvent(View.java:8681)
    at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4123)
    at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3989)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3597)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3563)
    at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3680)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3571)
    at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3737)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3597)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3563)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3571)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544)
    at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5817)
    at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5791)
    at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5762)
    at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5907)
    at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
    at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
    at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176)
    at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:5878)
    at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:5930)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
    at android.view.Choreographer.doCallbacks(Choreographer.java:580)
    at android.view.Choreographer.doFrame(Choreographer.java:548)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5345)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:947)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:742)

我们看到,每当有点击事件的时候,都会去更新header的y轴的数据信息,从负值一直到零,注意这里最大的值是零。

总结,以上是对SystemUi的一些简单分析,在这里对启动的流程,各个文件的布局进行了一些简单的分析,这里面有许多细节的东西没有去进行更进一步的剖析,后面有时间会讲这些细节的东西补上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章