SystemUI 启动

2.1 SystemUI 启动

SystemUI是一个app,它所在的系统源码路径为:
androidSource/frameworks/base/packages/SystemUI
它的目录结构如下:
在这里插入图片描述
我们可以根据Android.mk配置信息可以看出这个模块最终编译成SystemUI.apk,生成的产物是在out/target/product/(productname)/system/priv-app/SystemUI.apk
在这里插入图片描述
由于安装包最后是放在了system/priv-app目录下,所以SystemUI.apk会开机便会被安装,安装好了,是不是就意味着开机就能看到状态栏与导航栏了呢,当然不是,这就需要被其他的服务拉起来,那下面就开始分析状态栏的启动过程。整个流程为:init->zygote->ZygoteInit->SystemServer->startSystemUi->SystemUIService->SystemBars->PhoneStatusBar
我们直接到SystemServer这步,上文有说明,前面几步可以参考上篇文章,这里不再赘述。
下面是函数跳转:

        ActivityManagerService.self().systemReady(new Runnable() {
            public void run() {
				.......//此处省略n行
                if (!headless) {
                    startSystemUi(contextF);
                }
				.......//此处省略n行
            }
        });

然后到startSystemUi函数:

    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.java,代码位置:
./frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
可以看到这里启动了各个服务,如Recents,SystemBars,PowerUI等服务,这里我们只分析SystemBars的启动。

    public void onCreate() {
        //add begin
        boolean isLowRam = SystemProperties.getBoolean("ro.config.low_ram", false);
        if(isLowRam) {
            SERVICES = new Class[] {
                //com.android.systemui.recent.Recents.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,
                //com.android.systemui.settings.SettingsUI.class,
            };
        }
        mServices = new SystemUI[SERVICES.length];
        //add end
        HashMap<Class<?>, Object> components = new HashMap<Class<?>, Object>();
        final int N = SERVICES.length;
        for (int i=0; i<N; i++) {
            Class<?> cl = SERVICES[i];
            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 = components;
            Log.d(TAG, "running: " + mServices[i]);
            mServices[i].start();
        }
    }

我们可以看到服务最终是通过start方法启动的,那我们就走到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
    }
    public void start() {
        // listen for setting changes
        ContentResolver cr = mContext.getContentResolver();
        cr.registerContentObserver(Settings.Secure.getUriFor(mSettingKey),
                false /*notifyForDescendents*/, mSettingObserver, UserHandle.USER_ALL);

        // listen for package/component changes
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        filter.addDataScheme("package");
        mContext.registerReceiver(mBroadcastReceiver, filter);

        mHandler.sendEmptyMessage(MSG_START_SERVICE);
    }
    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;
            }
        }
    };

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

start函数最后调用到了onNoService函数

    public void onNoService() {
        if (DEBUG) Log.d(TAG, "onNoService");
        createStatusBarFromConfig();  // fallback to using an in-process implementation
    }

那我们走入里面实现中的createStatusBarFromConfig函数的实现:

    private void createStatusBarFromConfig() {
        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
        final String clsName = mContext.getString(R.string.config_statusBarComponent);  //1
        if (clsName == null || clsName.length() == 0) {
            throw andLog("No status bar component configured", null);
        }
        Class<?> cls = null;
        try {
            cls = mContext.getClassLoader().loadClass(clsName);
        } catch (Throwable t) {
            throw andLog("Error loading status bar component: " + clsName, t);
        }
        try {
            mStatusBar = (BaseStatusBar) cls.newInstance();
        } catch (Throwable t) {
            throw andLog("Error creating status bar component: " + clsName, t);
        }
        mStatusBar.mContext = mContext;
        mStatusBar.mComponents = mComponents;
        mStatusBar.start();
        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
    }

注释1作用是通过配置文件,获取string字段,
在这里插入图片描述
由此可知最后是走到了PhoneStatusBar类的start函数,好的,已经快分析完了,再接着往下看其start的实现:

    public void start() {
        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        updateDisplaySize();

        super.start(); // 2

        addNavigationBar(); //3

        // Lastly, call to the icon policy to install/update all the icons.
        mIconPolicy = new PhoneStatusBarPolicy(mContext);

        mHeadsUpObserver.onChange(true); // set up
        if (ENABLE_HEADS_UP) {
            mContext.getContentResolver().registerContentObserver(
                    Settings.Global.getUriFor(SETTING_HEADS_UP), true,
                    mHeadsUpObserver);
        }
    }

注释2代码的作用就是开启状态栏,注释3代码开启导航栏。super.start();这段代码最后会调用到createAndAddWindow()函数,然后调用addStatusBarWindow函数:

    private void addStatusBarWindow() {
        // Put up the view
        final int height = getStatusBarHeight();

        // Now that the status bar window encompasses the sliding panel and its
        // translucent backdrop, the entire thing is made TRANSLUCENT and is
        // hardware-accelerated.
        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                height,
                WindowManager.LayoutParams.TYPE_STATUS_BAR,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);

        lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;

        lp.gravity = getStatusBarGravity();
        lp.setTitle("StatusBar");
        lp.packageName = mContext.getPackageName();

        makeStatusBarView();
        mWindowManager.addView(mStatusBarWindow, lp);
    }

上面的代码我们需要注意的makeStatusBarView这一段代码。makeStatusBarView里的代码比较多,其主要工作是实例化状态栏,通知栏等控件,并为之添加事件,如果不需要展示状态栏与导航栏,可以隐藏显示,这里通过两个方法实现了隐藏功能。首先是在makeStatusBarView函数中:
mStatusBarWindow.setBackground(null);
将状态栏里的背景设置为空,那么状态栏将会变成一个小黑条,这不大好看,那么就还需要一个操作,改配置文件的属性,代码路径为:
./frameworks/base/core/res/res/values/dimes.xml
修改的代码如下:
在这里插入图片描述
很简单,就是将状态栏和导航栏的高度变成0了,那当然也就看不到他们了,哈哈。到此,分析结束。

整个流程如下:
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值