Android SystemUI梳理

这篇具有很好参考价值的文章主要介绍了Android SystemUI梳理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


  团队博客: 汽车电子社区


一、简介

  在Android系统中SystemUI是一个系统级的APP,它提供了系统的用户界面,由system_server进程启动。SystemUI本身不属于system_server进程,它是一个独立的进程。它的HMI包括了状态栏、导航栏、通知栏、锁屏、近期任务等等。

  SystemServer是一个由Zogyte进程启动的程序,它负责启动和管理Android系统中的各种核心服务。 例如:ActivityManagerService和PackageManagerService,这些服务也都运行在system_server进程中,为Android系统提供各种功能和接口,供应用程序和其他服务调用。我们常说的Android Framework其实就是由这些Service组成的。

二、功能介绍

  这部分将主要介绍那些对我们定制自己的SystemUI时有参考价值的模块。

  1. 状态栏
     StatusBar,负责显示时间,电量,信号,通知等状态信息。
Android SystemUI梳理,Android,android,ui,C++,物联网   2. 导航栏
    NavigationBar,显示返回,主页,最近任务等按钮。在车载Android中,我们多数时候会称为Dock栏(DockBar)。一般负责显示车控、主页、蓝牙电话等常用功能的快捷控制和入口。
Android SystemUI梳理,Android,android,ui,C++,物联网
  3. 通知栏
    NotificationPanel,显示、控制通知的界面。实际的车载项目中通知栏往往会和【消息中心】合并成一个独立的APP。
Android SystemUI梳理,Android,android,ui,C++,物联网   4. 快捷控制
    QuickSettings,这个面板可以让用户快速地调整一些常用的设置,例如亮度、飞行模式、蓝牙等。QS面板有多种状态,包括初级展开面板(Quick Quick Settings,QQS)和完整QS面板(Quick Settings,QS)。用户可以通过下拉通知栏来打开或关闭QS面板。
Android SystemUI梳理,Android,android,ui,C++,物联网   5. 其他功能
    一些系统级的对话框、弹窗、动画、屏保等,这些内容相对比较简单,不再介绍了。而锁屏、媒体控制等一些功能,车载SystemUI开发时涉及的不多,也同样不再介绍。

三、SystemUI 启动流程

  当Android系统启动完成后,system_server进程会通过ActivityManagerService启动一个名为com.android.systemui.SystemUIService的服务,这个服务是SystemUI的入口类,它继承了Service类。

SystemServer的源码位置:/frameworks/base/services/java/com/android/server/SystemServer.java

mActivityManagerService.systemReady(() -> {
        Slog.i(TAG, "Making services ready");
        //...
        t.traceBegin("StartSystemUI");
        try {
            startSystemUi(context, windowManagerF);
        } catch (Throwable e) {
            reportWtf("starting System UI", e);
        }
        t.traceEnd();
    }, t);

  从这里我们可以看出,SystemUI本质就是一个Service,通过Pm获取到的Component是com.android.systemui/.SystemUIService。startSystemUi代码细节如下:

private static void startSystemUi(Context context, WindowManagerService windowManager) {
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.android.systemui",
            "com.android.systemui.SystemUIService"));
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    //Slog.d(TAG, "Starting service: " + intent);
    context.startServiceAsUser(intent, UserHandle.SYSTEM);
    windowManager.onSystemUiStarted();
}

  以上就是SystemUI的启动流程,接下来我们继续看SystemUI是如何初始化的。

四、SystemUI 初始化流程

  SystemUI的初始化流程分为以下几步:

4.1、Application初始化

SystemUIApplication源码位置:/frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java

  在SystemUI启动后,首先会调用Application的onCreate方法,并在onCreate方法中对SystemUI进行初始化。这里我把它分为四个部分的内容。
  1、第一部分内容不多,主要是通过Dagger拿到SystemUI中的一些创建好的组件,同时设定一些调试工具。

public void onCreate() {
    super.onCreate();
    Log.v(TAG, "SystemUIApplication created.");
    // This line is used to setup Dagger's dependency injection and should be kept at the
    // top of this method.
    // TimingsTraceLog 是一个用于跟踪代码执行时间的工具类,它可以在traceview中看到。
    TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
            Trace.TRACE_TAG_APP);
    log.traceBegin("DependencyInjection");
    // 此行用于设置Dagger的依赖注入,并应保持在onrecate方法的顶部。
    mContextAvailableCallback.onContextAvailable(this);
    log.traceEnd();

    mLocalHandler = new LocalHandler();

    // 设置所有服务继承的应用程序主题。请注意,
    // 仅在清单中设置应用程序主题仅适用于活动。请将其与在那里设置的主题同步。
    setTheme(R.style.Theme_SystemUI);
}

  2、首先判断当前进程是否属于系统用户。然后根据SF GPU上下文优先级设置设定SystemUI的渲染器的上下文优先级,最后开启SystemServer的binder调用trace跟踪。

public void onCreate() {
    // 判断当前进程是否是系统进程。如果是系统进程,那么就注册 BOOT_COMPLETED 广播接收器。
    if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
        // 创建 BOOT_COMPLETED 广播接收器的意图过滤器。
        IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
        bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);   
    }
}

  ThreadedRenderer可以简单理解为一个渲染器,它可以在后台线程中渲染视图层次结构。优先级越高,渲染速度越快。
  Process.myUserHandle()可以获取当前进程的用户类型。如果是从事移动端APP开发,很少会涉及Android系统的多用户机制。但是由于汽车是一种具有共享属性的工具,会存在多个家庭成员使用一辆车的情况,所以Android多用户在车载Android开发中较为常见。
  当我们在系统设置中的「系统」「多用户」添加一个新用户并切换到这个新用户时,实际上会再启动一个SystemUI进程,新的SystemUI进程的用户ID会从U1X开始,原始的SystemUI的用户ID则始终是U0。
  3、第三部分注册监听开机广播,并在SystemUIService启动后,再通知SystemUI中的其它组件「系统启动完成」。

public void onCreate() {
registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (mBootCompleted) return;

            if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
            unregisterReceiver(this);
            mBootCompleted = true;
            if (mServicesStarted) {
                final int N = mServices.length;
                for (int i = 0; i < N; i++) {
                    mServices[i].onBootCompleted();
                }
            }

        }
    }, bootCompletedFilter);
    
        IntentFilter localeChangedFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
        registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
                    if (!mBootCompleted) return;
                    // Update names of SystemUi notification channels
                    NotificationChannels.createAll(context);
                }
            }
        }, localeChangedFilter);
    } else {
        /* 第四部分 */
    }
}

  4、第四部分如果当前用户非系统用户那么调用startSecondaryUserServicesIfNeeded方法。

// 我们不需要为正在执行某些任务的子进程初始化组件。例如:截图进程等
String processName = ActivityThread.currentProcessName();
ApplicationInfo info = getApplicationInfo();
if (processName != null && processName.startsWith(info.processName + ":")) {
    return;
}
// 对于第二个用户,boot-completed永远不会被调用,因为它已经在启动时为主SystemUI进程广播了
// 对于需要每个用户初始化SystemUI组件的组件,我们现在为当前非系统用户启动这些组件。
startSecondaryUserServicesIfNeeded();

  在这里插入代码片`startSecondaryUserServicesIfNeeded方法也是通过startServicesIfNeeded方法来初始化SystemUI中的功能组件。具体是如何初始化,我们之后再来分析。

void startSecondaryUserServicesIfNeeded() {
    String[] names =
              getResources().getStringArray(R.array.config_systemUIServiceComponentsPerUser);
    startServicesIfNeeded(names);
}

  到这里,我们简单总结一下SystemUIApplication中其实最主要的工作,其实只有两个:
    1.、在系统用户空间中监听开机广播,并通知SystemUI的功能组件。
    2、在非系统用户空间中,直接初始化SystemUI的功能组件。

4.2、启动 SystemUIService

  当Application完成初始化之后,紧接着,SystemUIService就会被启动。

SystemUIService源码位置:/frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
  SystemUIService在onCreate()方法中会调用((SystemUIApplication) getApplication()).startServicesIfNeeded()方法。

@Override
public void onCreate() {
    super.onCreate();
    // Start all of SystemUI
    ((SystemUIApplication) getApplication()).startServicesIfNeeded();
    ...
}

  这里可能有个疑问:为什么不把startServicesIfNeeded的相关逻辑写在Service中,非要写到Application中?
  是因为,当前用户不是系统用户时,startSecondaryUserServicesIfNeeded也需要去调用startServicesIfNeeded方法进行组件初始化,所以干脆把所有的初始化逻辑都写到Application中了。文章来源地址https://www.toymoban.com/news/detail-806623.html

private void startServicesIfNeeded(String[] services) {
    if (mServicesStarted) {
        return;
    }
    mServices = new SystemUI[services.length];

    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 for user " +
            Process.myUserHandle().getIdentifier() + ".");

    Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
    Message msg = mLocalHandler.obtainMessage();
    msg.obj = services;
    msg.arg1 = services.length;
    msg.arg2 = 0;
    msg.what = EVENT_START_SERVICE;
    msg.sendToTarget();
}

到了这里,关于Android SystemUI梳理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 9.0 原生SystemUI下拉通知栏UI背景设置为圆角背景的定制(一)

     在9.0的系统rom产品定制化开发中,在原生系统SystemUI下拉状态栏的通知栏的通知背景默认是白色四角的背景, 由于在产品设计中,需要把四角背景默认改成圆角背景,所以就需要分析系统原生下拉通知栏的每条通知的默认背景, 然后通知显示流程,设置默认下拉状态栏UI中

    2024年02月01日
    浏览(46)
  • Android 12.0 原生SystemUI下拉通知栏UI背景设置为圆角背景的定制(二)

     在12.0的系统rom定制化开发中,在原生系统SystemUI下拉状态栏的下拉通知栏的背景默认是白色四角的背景, 由于在产品设计中,在对下拉通知栏通知的背景需要把四角背景默认改成圆角背景,所以就需要分析系统原生下拉通知栏的每条通知的默认背景, 然后通过systemui的通知

    2024年02月08日
    浏览(48)
  • 一线互联网架构师360°全方面性能调优,android适配器ui

    为什么要使用多进程 对于进程的概念,来到这里的都是编程修仙之人,就不再啰嗦了,相信大家倒着、跳着、躺着、各种姿势都能背出来。 相信很多同学在实际开发中,基本都不会去给app划分进程,而且,在Android中使用多进程,还可能需要编写额外的进程通讯代码,还可能

    2024年04月13日
    浏览(42)
  • [Android14] SystemUI的启动

            SystemUI是Android系统级应用,负责反馈系统及应用状态并与用户保持大量的交互。业务主要涉及的组成部分包括状态栏(Status Bar),通知栏(Notification Panel),锁屏(Keyguard),控制中心(Quick Setting),音量调节(VolumeUI), 近期任务(Recents)等等。 图例如下所示: package name:    

    2024年04月27日
    浏览(43)
  • Android 11 SystemUI 启动流程

    从表面上看, 我们看到的 状态栏、通知栏、下拉菜单、导航栏、锁屏、最近任务、低电提示 等系统页面都是 SystemUI 的。SystemUI,在源码目录中位于: framework/base/packages 目录下, 可见 SystemUI 和 framework 是关联的, SystemUI 依赖了很多内部 API , 系统资源, SystemUI 编译是要依赖

    2024年02月13日
    浏览(39)
  • Android 9-SystemUI:(1)启动流程

    具体分析(以下代码示例,讲解,都是通过,Android9代码来举例) SystemUI,其实是可以看作是一个系统级的服务,也就是SystemUIService, SystemUI的服务启动,要从SystemServer.run()方法入手 main 方法里启动了 run() 方法,而在 run 方法中调用了startOtherServices() 方法,在启动startOtherServices(

    2024年02月11日
    浏览(44)
  • Android 10.0 SystemUI启动流程

    1、手机开机后,Android系统首先会创建一个Zygote(核心进程)。 2、由Zygote启动SystemServer。 3、SystemServer会启动系统运行所需的众多核心服务和普通服务、以及一些应用及数据。例如:SystemUI 启动就是从 SystemServer 里启动的。 4、进入锁屏界面,开机完成。 SystemServer 中有一个

    2024年02月05日
    浏览(47)
  • Android10 SystemUI系列(一)概述

    由于笔者之前负责过SystemUI,之前没有抽空把很多东西整理出来,趁着最近不太忙,就慢慢动手梳理一下,顺便把自己遇到的问题也整理一下,当然自己之前主要看的是android11 之后的源码。这次主要是Android10 的源码,当然原理大差不差,也算是自己沉淀一下了 SystemUI 是 And

    2024年02月10日
    浏览(33)
  • Android 车载应用开发指南(3) - SystemUI 详解

    Android 车载应用开发指南系列文章 Android 车载应用开发指南(1)- 车载操作系统全解析 Android 车载应用开发指南(2)- 应用开发入门 Android 车载应用开发指南(3)- SystemUI 详解 SystemUI 全称 System User Interface ,直译过来就是 系统级用户交互界面 ,在 Android 系统中由 SystemUI 负责

    2024年02月19日
    浏览(41)
  • 关于Android SystemUI Flag详解及使用情景

    触摸屏幕任何位置 顶部下拉状态栏 底部上拉导航栏 Window的变化(如:跳转到其他界面、弹出键盘等) View.SYSTEM_UI_FLAG_HIDE_NAVIGATION:(=api16) 作用是隐藏系统NavigationBar。 但是用户的任何交互,都会导致此Flag被系统清除,进而导航栏自动重新显示,同时View.SYSTEM_UI_FLAG_FULLSCREEN也会

    2024年02月08日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包