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