Zygote -> SystemServer /SystemServer中会初始化一些Android的java层的服务,如ActivityManagerService、WindowManagerService..
SystemServer的run方法中startOtherServices来启动SystemUIService服务
frameworks\base\services\java\com\android\server\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);
}
SystemUIService 的onCreate中获取SystemUIApplication对象来初始化SystemUI相关的服务
SystemUIApplication.java{
public void onCreate() {
startServicesIfNeeded();
}
//初始化 SERVICES 数据中的 服务,for循环调用 onstart方法
startServicesIfNeeded(){
TunerService(定制状态栏服务)
KeyguardViewMediator(锁屏相关)
Recents(近期任务)
VolumeUI(音量条)
SystemBars(状态栏,导航栏)
StorageNotification(通知栏)
PowerUI(电源相关)
RingtonePlayer(铃声播放相关)类
它们都是继承与SystemUI抽象类
}
}
然后就走到了 SystemBar 这个类中
SystemBars.java{
public void start() {
...
createStatusBarFromConfig();
}
createStatusBarFromConfig(){
//通过config中配置的 类名实例化
...
...
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mComponents;
mStatusBar.start();//调用类的start方法
}
}
SystemBar 中去创建 statusbar.java 对象
StatusBar.java {
public void onStart(){
//位置控制
mLocationController
//电池
mBatteryController
//网络
mNetworkController
//热点
mHotspotController
//蓝牙
mBluetoothController
mSecurityController
//手电筒
mFlashlightController
//键盘
mKeyguardBottomArea
.....
createAndAddWindows()
//Set up the quick settings tile panel
mQSPanel
mQSBarControll
QSFragment.
}
createAndAddWindows --> addStatusBarWindow --> makeStatusBarView
// 这里就是处理 状态栏的一些加载和逻辑
makeStatusBarView{
//加载StartBarWindowView视图
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
R.layout.super_status_bar, null);
mStatusBarWindow.setService(this);
//监听下拉事件
mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
checkUserAutohide(v, event);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mExpandedVisible) {
animateCollapsePanels();
}
}
return mStatusBarWindow.onTouchEvent(event);
}
});
//通知栏
mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(R.id.notification_panel);
mNotificationPanel.setStatusBar(this);
//状态栏
mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
mStatusBarView.setBar(this);
//****** 是否显示导航栏 ******//
boolean showNav = mWindowManagerService.hasNavigationBar();
//**** 实际调用地方
frameworks\base\service\core\java\com\android\server\PhoneWindowManager.java
PhoneWindowManager{
@Override
public boolean hasNavigationBar() {
return mHasNavigationBar;
}
mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
// Allow a system property to override this. Used by the emulator.
// See also hasNavigationBar().
String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
if ("1".equals(navBarOverride)) {
mHasNavigationBar = false;
} else if ("0".equals(navBarOverride)) {
mHasNavigationBar = true;
}
} ***//
if(showNav){
//创建导航栏
createNavigationBar();
}
.....
//下拉通知栏
mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
mStackScroller.setPhoneStatusBar(this);
mStackScroller.setGroupManager(mGroupManager);
mStackScroller.setHeadsUpManager(mHeadsUpManager);
mGroupManager.setOnGroupChangeListener(mStackScroller);
....
.....
//下拉清除键,代码位置不同版本会变,搜索 mDismissView
mDismissView = (DismissView) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_notification_dismiss_all, mStackScroller, false);
//锁屏相关,,代码位置不同版本会变,搜索 mKeyguardStatusBar
mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
mKeyguardBottomArea =
(KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
mKeyguardBottomArea.setActivityStarter(this);
mKeyguardBottomArea.setAssistManager(mAssistManager);
mKeyguardIndicationController = new KeyguardIndicationController(mContext,
(KeyguardIndicationTextView) mStatusBarWindow.findViewById(
R.id.keyguard_indication_text),
mKeyguardBottomArea.getLockIcon());
mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIn
//主要是控制一些系统图标,第三方图标等的显示和更新
mIconController = new StatusBarIconController(
mContext, mStatusBarView, mKeyguardStatusBar, this);
// Background thread for any controllers that need it.
mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
}
createNavigationBar{
//创建 Nav
NavigationBarFragment.create()
}
}
NavigationBarFragment.java 这个类, 调用静态 oncreate() 去实例化
NavigationBarFragment.java{
public void onCreateView(){
//这里就是 navigation_bar.xml 的布局
//这个布局老版本是画好的
//8.0 是在 NavigationBarInflaterView 中按照config 配置加载的
return inflater.inflat(R.layout.navigation_bar, container, false);
}
public void onViewCreated(View view, Bundle ){
mNavigationBarView = (mNavigationBarView)view
mNavigationBarView.setOntouchListener();
}
private void prepareNavigationBarView() {
//决定导航栏的显示
mNavigationBarView.reorient();
//设置导航栏三个图标的点击事件
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
mNavigationBarView.getRecentsButton().setLongClickable(true);
mNavigationBarView.getRecentsButton().setOnLongClickListener(mLongPressBackRecentsListener);
mNavigationBarView.getBackButton().setLongClickable(true);
mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener);
mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);
mNavigationBarView.getHomeButton().setOnLongClickListener(mLongPressHomeListener);
.....
}
//创建 navigationbar
public static View create(){
//设置 Nav LayoutParams
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,//导航栏
0
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING//当手机处于睡眠状态时,如果屏幕被按下,那么该window将第一个收到到事件
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE//不获取焦点
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL//即使在该window在可获得焦点情况下,仍然把该window之外的任何event发送到该window之后的其他window
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH//不接受事件,转发到其他window
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,//当该window在可以接受触摸屏情况下,让因在该window之外,而发送到后面的window的触摸屏可以支持split touch.
lp.setTitle("NavigationBar");
}
}
NavigationBarFragment.java 加载的 navigation_bar.xml --- (关键词 keybuttonview 的使用地方)
8.0 是加载的 NavigationBarView , NavigationBarInflaterView.java
<com.android.systemui.statusbar.phone.NavigationBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="@drawable/system_bar_background">
<com.android.systemui.statusbar.phone.NavigationBarInflaterView
android:id="@+id/navigation_inflater"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.android.systemui.statusbar.phone.NavigationBarView>
NavigationBarView.java
在NavigationBarView导航栏这个布局加载的时候就会设置图片资源,和长度改变,屏幕旋转都有可能引起重新设置
NavigationBarView(){
NavigationBarInflateView
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
mDisplay = ((WindowManager) context.getSystemService(
Context.WINDOW_SERVICE)).getDefaultDisplay();
...
/******** 更新icon *****/
updateIcons(context, Configuration.EMPTY, mConfiguration);
/******** 更新icon *****/
mBarTransitions = new NavigationBarTransitions(this);
//mButtonDispatchers 是维护这些home back recent图标view的管理类,
//传递到他的child,NavigationBarInflaterView类中
mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
mButtonDispatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
mButtonDispatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
mButtonDispatchers.put(R.id.accessibility_button,
new ButtonDispatcher(R.id.accessibility_button));
}
private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
...
mHomeDefaultIcon = getDrawable(ctx,
R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
mHomeDefaultIcon = getDrawable(iconLight,iconDark);
...
}
public void reorient() {
//获取屏幕方向
final int rot = mDisplay.getRotation();
//隐藏导航栏布局
for (int i=0; i<4; i++) {
mRotatedViews[i].setVisibility(View.GONE);
}
//根据屏幕方向显示导航栏布局
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
setLayoutTransitionsEnabled(mLayoutTransitionsEnabled);
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
// force the low profile & disabled states into compliance
mBarTransitions.init();
setDisabledFlags(mDisabledFlags, true /* force */);
setMenuVisibility(mShowMenu, true /* force */);
updateTaskSwitchHelper();
setNavigationIconHints(mNavigationIconHints, true);
}
@Override
public void onFinishInflate() {
//屏幕方位0和180方向显示的导航栏为rot0
mRotatedViews[Surface.ROTATION_0] =
mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
//屏幕访问90和270显示的导航栏为rot90
mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
mRotatedViews[Surface.ROTATION_270] = mRotatedViews[Surface.ROTATION_90];
//mCurrentView = mRotatedViews[Surface.ROTATION_0];
mCurrentView = mRotatedViews[Surface.ROTATION_90];
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
updateRTLOrder();
}
}
NavigationBarInflaterView.java ,去创建每个具体的按钮 KeyButtonView
NavigationBarInflaterView.java{
private View createView(String buttonSpec, ViewGroup parent, LayoutInflater inflater) {
View v = null;
...
//每个按钮
if (HOME.equals(button)) {
v = inflater.inflate(R.layout.home, parent, false);
} else if (BACK.equals(button)) {
v = inflater.inflate(R.layout.back, parent, false);
} else if (RECENT.equals(button)) {
v = inflater.inflate(R.layout.recent_apps, parent, false);
} else if (MENU_IME.equals(button)) {
v = inflater.inflate(R.layout.menu_ime, parent, false);
} else if (NAVSPACE.equals(button)) {
v = inflater.inflate(R.layout.nav_key_space, parent, false);
} else if (CLIPBOARD.equals(button)) {
v = inflater.inflate(R.layout.clipboard, parent, false);
}
//如果添加自己的 hide 按钮
else if(){
}
...
return v;
}
//***** KeyButtonView *********
R.layout.home.xml,......
<com.android.systemui.statusbar.policy.KeyButtonView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/home"
android:layout_width="@dimen/navigation_key_width"//引用了dimens.xml里的navigation_key_width
android:layout_height="match_parent"
android:layout_weight="0"
systemui:keyCode="3"//systemui自定义的属性
android:scaleType="fitCenter"
android:contentDescription="@string/accessibility_home"
android:paddingTop="@dimen/home_padding"
android:paddingBottom="@dimen/home_padding"
android:paddingStart="@dimen/navigation_key_padding"
android:paddingEnd="@dimen/navigation_key_padding"
/>
KeyButtonView.java{
public KeyButtonView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
}
//监听导航栏每个keyButton按钮
public boolean onTouchEvent(MotionEvent ev) {
switch (action) {
case MotionEvent.ACTION_DOWN:
mDownTime = SystemClock.uptimeMillis();
mLongClicked = false;
setPressed(true);
if (mCode != 0) {
//发送事件
sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
} else {
// Provide the same haptic feedback that the system offers for virtual keys.
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
playSoundEffect(SoundEffectConstants.CLICK);
removeCallbacks(mCheckLongPress);
postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
break;
}
return true;
}
void sendEvent(int action, int flags, long when) {
final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
//根据mCode new了一个KeyEvent事件
final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
InputDevice.SOURCE_KEYBOARD);
//injectInputEvent使事件生效
InputManager.getInstance().injectInputEvent(ev,
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
}
***/
onFinishInflate(){
inflateLayout();
}
//加载 Nav 布局
inflateLayout(){
newLayout = getDefaultLayout();
//<string name="config_navBarLayout" translatable="false">left;back,home,recent;right</string>
String[] sets = newLayout.split(GRAVITY_SEPARATOR, 3);//根据“;”号分割成长度为3的数组
String[] start = sets[0].split(BUTTON_SEPARATOR);//根据“,”号分割,包含 left[.5W]和back[1WC]
String[] center = sets[1].split(BUTTON_SEPARATOR);//home
String[] end = sets[2].split(BUTTON_SEPARATOR);//含recent[1WC]和right[.5W]
inflateButtons();
...
}
//虚拟键的配置, 是存在在 conif
getDefaultLayouts(){
R.string.config_nav -- 需要在配置中添加
}
private void inflateButtons(String[] buttons, ViewGroup parent, boolean landscape,
boolean start) {
for (int i = 0; i < buttons.length; i++) {
inflateButton(buttons[i], parent, landscape, start);
}
}
@Nullable
protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape,
boolean start) {
LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
View v = createView(buttonSpec, parent, inflater);//创建view
if (v == null) return null;
v = applySize(v, buttonSpec, landscape, start);
parent.addView(v);//addView到父布局
addToDispatchers(v);
...
}
}