Android12 源码分析 SystemUI 学习(2)

SystemUI 学习(2) --- StatusBar

StatusBar的创建过程

SystemUI 学习(1)中已经了解了SystemUI启动的过程,而在SystemUI启动过程中,系统会启动相关的服务组件,其中当然就包括了StatusBar

StatusBar的创建过程.png

注:StatusBars的启动在Android11版本进行了改动,Android10存在一个SystemBars.java类,在这个类里进行获取StatusBars的资源并启动它。

而在Android11往后,这个类被移除了。而StatusBar则由SystemUI程序直接启动。

在第一篇SystemUi学习文档中提到过,在系统第一次启动SystemUI时,SystemUI会启动很多服务组件。其中就包含了StatusBar,而Android11以前是SystemBars代替的StatusBars

状态栏视图窗口的创建分析(Start方法)

  • StatusBarstart()方法

    frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

    public class StatusBar extends SystemUI implements ActivityStarter, LifecycleOwner {
      @Override
      public void start() {
      	//...代码省略...
      	createAndAddWindows(result);
      	//...代码省略...
      }
    }
    

    start方法会调用一个叫createAndAddWindows的关键方法,系统状态栏视图的创建和添加工作就是在该方法中完成的。StatusBar start之后开始新建添加和填充视图。

  • createAndAddWindows相关的代码

    public class StatusBar extends SystemUI implements /*代码省略*/ {
        
        //...代码省略...
        private final StatusBarWindowController mStatusBarWindowController;
        private final StatusBarComponent.Factory mStatusBarComponentFactory;
        private StatusBarComponent mStatusBarComponent;
        //...代码省略...
        
        public StatusBar(
    		//...代码省略...
            StatusBarWindowController statusBarWindowController,
            StatusBarComponent.Factory statusBarComponentFactory,
    		//...代码省略...
    	){
    		//...代码省略...
            mStatusBarWindowController = statusBarWindowController;//状态栏控制器
            mStatusBarComponentFactory = statusBarComponentFactory;
            //...代码省略...
        }   
    
        @Override
        public void start() {
        	//...代码省略...	
        	createAndAddWindows(result);
        	//...代码省略...
        }
    
        public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
            makeStatusBarView(result);
            //...代码省略...
            mStatusBarWindowController.attach();
        }
    
       protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
    		//...代码省略...
            inflateStatusBarWindow();
            //...代码省略...
            mStatusBarWindowController.getFragmentHostManager()
                    .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {/*代码省略*/})
                	.getFragmentManager()
                    .beginTransaction()
                    .replace(R.id.status_bar_container,
                            mStatusBarComponent.createCollapsedStatusBarFragment(),
                            CollapsedStatusBarFragment.TAG)
                    .commit();
            //...代码省略...
       	}
           
        private void inflateStatusBarWindow() {
            mStatusBarComponent = mStatusBarComponentFactory.create();
            //...代码省略...
         }
    }
    
    

    createAndAddWindows首先调用了makeStatusBarView方法来构建视图,makeStatusBarView方法又会调用inflateStatusBarWindow方法,inflateStatusBarWindow方法内部又调用mStatusBarComponentFactory的create方法为状态栏组件mStatusBarComponent赋值。

    在inflateStatusBarWindow方法执行完毕后,makeStatusBarView方法会调用mStatusBarWindowController的getFragmentHostManager来获取FragmentHostManager对象实例。

  • 上面提到一个方法-----StatusBarWindowController的getFragmentHostManager方法,相关代码。

    frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java

    @SysUISingleton
    public class StatusBarWindowController {
        @Inject
        public StatusBarWindowController(
                Context context,
                @StatusBarWindowModule.InternalWindowView StatusBarWindowView statusBarWindowView,
                WindowManager windowManager,
                IWindowManager iWindowManager,
                StatusBarContentInsetsProvider contentInsetsProvider,
                @Main Resources resources) {
       		//...代码省略...
            mStatusBarWindowView = statusBarWindowView;
       		//...代码省略...
        }
        
        public FragmentHostManager getFragmentHostManager() {
            return FragmentHostManager.get(mStatusBarWindowView);
        }
    }
    

    getFragmentHostManager内部会将mStatusBarWindowView作为唯一参数,继续调用FragmentHostManager的get方法。

  • 继续查看FragmentHostManager的get方法代码

    frameworks/base/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java

    public class FragmentHostManager {
        public static FragmentHostManager get(View view) {
            try {
                return Dependency.get(FragmentService.class).getFragmentHostManager(view);
            } catch (ClassCastException e) {
                // TODO: Some auto handling here?
                throw e;
            }
        }
    }
    
  • get方法调用了FragmentService的getFragmentHostManager方法

    frameworks/base/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java

    public class FragmentService implements Dumpable {
    
        public FragmentHostManager getFragmentHostManager(View view) {
            View root = view.getRootView();
            FragmentHostState state = mHosts.get(root);
            if (state == null) {
            	//创建FragmentHostState对象实例
                state = new FragmentHostState(root);
                mHosts.put(root, state);
            }
            //调用FragmentHostState的getFragmentHostManager方法
            return state.getFragmentHostManager();
        } 
        private class FragmentHostState {
            private final View mView;
            private FragmentHostManager mFragmentHostManager;
            public FragmentHostState(View view) {
                mView = view;
                //创建FragmentHostManager对象实例
                mFragmentHostManager = new FragmentHostManager(FragmentService.this, mView);
            }
            public FragmentHostManager getFragmentHostManager() {
                return mFragmentHostManager;
            }
        }  
    }
    
    

    返回查看FragmentHostManager相关代码

    public class FragmentHostManager {
    
        private final View mRootView;
        
        FragmentHostManager(FragmentService manager, View rootView) {
            //...代码省略...
            //将StatusBarWindowView赋值给mRootView 
            mRootView = rootView;
            //...代码省略...
        }
    

    FragmentService的getFragmentHostManager会创建FragmentHostState对象实例,然后调用该对象的getFragmentHostManager方法,该方法会返回mFragmentHostManager,而mFragmentHostManager最早是在FragmentHostState自己的构造方法中创建的,原来绕了一圈,最后得到的结果其实就是,StatusBarWindowController的getFragmentHostManager方法会将StatusBarWindowView作为构造方法参数创建FragmentHostManager实例对象。

  • 关注到mStatusBarWindowView对象作为参数在各种方法中传递,探究一下具体来源。获取StatusBarWindowView对象实例的关键代码位于StatusBarWindowModule.kt的providesStatusBarWindowView方法中

    frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt

    @Module
    abstract class StatusBarWindowModule {
        @Module
        companion object {
        	//提供一个单例的StatusBarWindowView对象实例
            @JvmStatic
            @Provides
            @SysUISingleton
            @InternalWindowView
            fun providesStatusBarWindowView(layoutInflater: LayoutInflater): StatusBarWindowView {
                return layoutInflater.inflate(
                    R.layout.super_status_bar,
                    /* root= */null
                ) as StatusBarWindowView?
                    ?: throw IllegalStateException(
                        "R.layout.super_status_bar could not be properly inflated"
                    )
            }
        }
    
    }
    
  • 在providesStatusBarWindowView方法中,StatusBarWindowView是直接使用R.layout.super_status_bar布局文件转化成View对象的。

    frameworks/base/packages/SystemUI/res/layout/super_status_bar.xml

    <com.android.systemui.statusbar.window.StatusBarWindowView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:sysui="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">
    
        <FrameLayout
            android:id="@+id/status_bar_launch_animation_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
        <FrameLayout
            android:id="@+id/status_bar_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/system_bar_background" />
    </com.android.systemui.statusbar.window.StatusBarWindowView>
    

将状态栏窗口添加到Window中

  • StatusBarcreateAndAddWindows方法在调用makeStatusBarView方法构建好状态栏视图之后,便会调用StatusBarWindowControllerattach方法。

  • StatusBarWindowController的attach方法。

    @SysUISingleton
    public class StatusBarWindowController {
    
        private final WindowManager mWindowManager;
        private WindowManager.LayoutParams mLp;
        @Inject
        public StatusBarWindowController(
                Context context,
                @StatusBarWindowModule.InternalWindowView StatusBarWindowView statusBarWindowView,
                WindowManager windowManager,
                IWindowManager iWindowManager,
                StatusBarContentInsetsProvider contentInsetsProvider,
                @Main Resources resources) {
    		//...代码省略...
            mWindowManager = windowManager;
            mStatusBarWindowView = statusBarWindowView;
            if (mBarHeight < 0) {
                mBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
            }
        }
        
        public void attach() {
        	//获取状态栏类型窗口所需要的布局参数
            mLp = getBarLayoutParams(mContext.getDisplay().getRotation());
            //调用WindowManager的addView方法将状态栏窗口添加到Window中。
            mWindowManager.addView(mStatusBarWindowView, mLp);
    		//...代码省略...
        }
    }
    
  • attach首先调用getBarLayoutParams方法获取状态栏类型窗口所需要的布局参数,在获取到状态栏视图所需的参数后便会调用WindowManager的addView方法将状态栏视图窗口添加到Window中。

    注:StatusBar源码在Android11、Android12.0、Android12.1和Android13都存在一定的差异,本文以Android12.1代码作分析,其它版本源码可能存在差异,但是分析方法相同。感兴趣的可以自己去源码网站看看

    当然在StatusBar中还有和通知栏、底部导航栏的相关代码,这个我们后面再做分析

总结

SystemUI启动后,会通过资源文件启动相关的组件服务,其中就包含了StatusBar。StatusBar启动后,在start()方法中创建和添加窗口,然后构建StatusBar视图、填充StatusBar视图。而后实例化StatusBarWindowController,再通过StatusBarWindowController添加视图给WindowManager。

参考文章:系统状态栏StatusBar的创建流程 源码网站:Android Code Search 版本android-12.1.0_r8

全部评论

相关推荐

不愿透露姓名的神秘牛友
11-26 15:46
已编辑
字节国际 电商后端 24k-35k
点赞 评论 收藏
分享
球球别再泡了:坏,我单9要了14
点赞 评论 收藏
分享
海康威视 软开岗 15k15
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务