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的一些簡單分析,在這裏對啓動的流程,各個文件的佈局進行了一些簡單的分析,這裏面有許多細節的東西沒有去進行更進一步的剖析,後面有時間會講這些細節的東西補上。

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