车载系统-开机动画

文章详细阐述了Android车载系统的启动流程,从上电自检到显示界面,重点介绍了init进程的作用,包括启动系统服务、加载配置文件、执行初始化命令以及启动应用程序。此外,还提到了init进程如何守护关键服务,确保系统稳定性和可靠性,并解析了启动动画的显示时机和相关代码模块。
摘要由CSDN通过智能技术生成

启动流程

在我们看动画加载时机之前我们先来回顾一下车载启动的系统流程,安卓车载系统的启动流程与普通的安卓系统启动流程相似,其主要流程如下:

  • 上电自检:当车辆点火启动时,车载系统会执行硬件自检程序,检测各个硬件设备是否正常,例如电源、内存、存储设备等。

  • 启动 Bootloader:启动 Bootloader,Bootloader 会进行一些初始化工作,然后加载内核镜像并将控制权转移到内核。

  • 启动内核:安卓车载系统启动的内核通常是一个定制化内核,该内核会根据启动参数进行一些初始化工作,如加载驱动程序、初始化硬件等。

  • 启动 init 进程:当内核启动完成后,它会启动 init 进程,该进程是 Android 系统的第一个进程,它会读取 init.rc 配置文件并根据配置文件启动系统服务和应用程序。在车载系统中,通常需要启动一些定制的系统服务,如音频服务、视频服务、导航服务等。

  • 启动系统服务:一旦 init 进程启动完成,它会启动各种系统服务,例如 SurfaceFlinger、Zygote、MediaServer 等,这些服务是 Android 系统的核心服务,负责显示、应用程序运行等功能。

  • 启动应用程序:系统服务启动后,系统会启动一些预装的应用程序,如导航应用、音乐应用、收音机应用等,同时也会启动用户安装的应用程序。

  • 显示界面:一旦应用程序启动完成,系统会显示出 Android 车载系统的主界面,用户可以进行各种操作。

init进程的作用

概述

在 Android 系统中,init 进程是系统启动过程中的第一个用户空间进程,它的作用非常重要。init 进程主要有以下几个作用:

  • 启动系统服务:init 进程负责启动 Android 系统中的所有系统服务,例如 SurfaceFlinger、Zygote、adb 等。这些系统服务是 Android 系统中的核心组件,它们提供了各种系统功能和服务,例如图形显示、应用程序运行环境、调试工具等。

  • 加载配置文件:init 进程会加载 Android 系统中的各种配置文件,例如 /init.rc、/system/etc/init、/system/etc/init.d 等。这些配置文件包含了系统启动过程中的各种配置和命令,例如启动服务、挂载文件系统、设置系统属性等。

  • 执行初始化命令:init 进程会执行一系列初始化命令,例如创建目录、设置文件权限、加载内核模块等。这些初始化命令可以确保系统启动过程中的各种资源都能够正确地被初始化和配置。

  • 启动应用程序:在 Android 系统中,应用程序的启动是由 Zygote 进程来完成的,而 Zygote 进程是由 init 进程启动的。因此,init 进程也负责启动 Zygote 进程,从而启动应用程序。

init 进程在 Android 系统中扮演着非常重要的角色,它负责启动系统中的所有核心组件和服务,并确保系统启动过程中的各种资源都能够正确地被初始化和配置。如果 init 进程出现问题,整个系统的启动过程可能会受到影响,甚至无法启动。

开启关键服务守护关键服务

init 进程作为系统启动的第一个进程,负责初始化系统资源、启动系统服务和守护关键服务等工作。具体来说,init 进程会按照 init.rc 文件中定义的服务列表依次启动系统服务,例如 SurfaceFlinger、Zygote、SystemServer 等,并确保它们在系统运行期间一直处于活动状态。还有init 进程还可以守护(daemonize)其它进程或服务,以确保它们在系统运行期间一直处于活动状态。例如,如果某个服务异常退出,init 进程会自动重启该服务,以保证系统的稳定性和可靠性。因此,init 进程开启关键服务和守护关键服务都是其重要的作用之一。

检测关键服务退出

init 进程使用 Linux 的 waitpid() 系统调用监视关键进程的状态。waitpid() 可以阻塞等待一个特定的子进程退出,并返回该进程的退出状态信息。init 进程可以利用这个特性监视指定的关键进程,并在进程异常退出时采取相应的措施,例如重启该进程等。

具体来说,init 进程会在启动关键进程时使用 fork() 系统调用创建一个子进程,并使用 execve() 系统调用加载指定的可执行文件。在子进程运行期间,init 进程会定期使用 waitpid() 系统调用监视该进程的状态,如果该进程异常退出,则 waitpid() 系统调用会返回该进程的状态信息,包括退出状态码、退出原因等。

在获取到该进程异常退出的状态信息后,init 进程可以根据预先定义的策略采取相应的措施。例如,如果该进程是一个关键服务,则 init 进程可以尝试重启该服务,以确保系统的稳定性和可靠性。如果该进程不是关键服务,则 init 进程可以选择忽略该异常退出事件,或者记录日志等。

守护子进程方式

init 进程可以通过以下两种方式守护(daemonize)子进程:

  1. 使用 “service” 关键字定义服务,并设置相应的属性
    在 init.rc 文件中,可以使用 “service” 关键字定义需要守护的子进程,并设置相应的属性,例如 “disabled”、“oneshot” 等。在子进程被启动后,init 进程会监视该进程的运行状态,如果该进程异常退出,则 init 进程会自动重启该进程。示例代码如下:
service my_service /system/bin/my_service
    class main
    user root
    group root
    disabled
    oneshot

在上述代码中,“service” 关键字定义了一个名为 “my_service” 的服务,指定该服务的可执行文件路径为 /system/bin/my_service。“disabled” 属性指定该服务默认情况下不会被启动,“oneshot” 属性指定该服务只执行一次。

  1. init.cpp 中使用 android::init::StartProcess() 函数
    在 init.cpp 文件中,可以使用 android::init::StartProcess() 函数启动需要守护的子进程,并通过参数指定该进程是否需要守护。示例代码如下:
void foo() {
    const std::vector<std::string> args = {"-a", "-b", "-c"};
    android::init::StartProcess("/system/bin/my_process", args, false /* daemonize */);
}

在上述代码中,android::init::StartProcess() 函数会启动名为 “my_process” 的可执行文件,并传递 “-a”、“-b”、“-c” 三个参数。第三个参数指定该进程不需要守护,如果将该参数设置为 true,则该进程会被守护。

显示时机

在安卓车载系统启动过程中,启动动画通常会在 init 进程启动之后、系统服务和应用程序启动之前显示。
具体地说,当内核启动完成并启动 init 进程后,init 进程会加载开机动画资源,并通过 SurfaceFlinger 服务将开机动画显示在屏幕上。此时,系统服务和应用程序还没有启动完成,因此在启动动画播放期间,用户无法进行其他操作。

此时不用安卓标准的绘制方式,是由于安卓相关的服务还没有启动。

代码模块

代码路径:frameworks>base > cmds>bootanimation
在 车机系统中,启动动画的实现主要是通过以下几个模块来完成的:

  • Bootanimation:负责管理启动动画资源,例如动画帧数、分辨率、文件格式等。Bootanimation 会将启动动画资源打包成一个 zip 文件,并存储在系统目录下的 /system/media/ 目录中。

  • BootanimationThread:负责播放启动动画,通过定时器逐帧显示启动动画。启动动画显示的时间和播放速度可以通过配置文件进行调整。BootanimationThread 还可以处理用户取消启动动画的事件,例如按下电源键或按下 HOME 键。

  • SurfaceFlinger:负责将启动动画显示在屏幕上,SurfaceFlinger 是 Android 系统中的一个核心服务,负责管理系统中的所有图形显示。在启动动画播放期间,BootanimationThread 会将每一帧的图像数据传递给 SurfaceFlinger,然后 SurfaceFlinger 将这些图像数据显示在屏幕上。

bootanimation_main.cpp的源码

int main()
{
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);

    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.nobootanimation", value, "0");
    int noBootAnimation = atoi(value);
    if (!noBootAnimation) {
        property_get("ro.boot.quiescent", value, "0");
        noBootAnimation = atoi(value);
    }
    ALOGI_IF(noBootAnimation,  "boot animation disabled");
    if (!noBootAnimation) {

				//开启进程
        sp<ProcessState> proc(ProcessState::self());
        //开启线程
        ProcessState::self()->startThreadPool();

        // TODO: replace this with better waiting logic in future, b/35253872
        int64_t waitStartTime = elapsedRealtime();
        sp<IServiceManager> sm = defaultServiceManager();
        const String16 name("SurfaceFlinger");
        const int SERVICE_WAIT_SLEEP_MS = 100;
        const int LOG_PER_RETRIES = 10;
        int retry = 0;
        while (sm->checkService(name) == nullptr) {
            retry++;
            if ((retry % LOG_PER_RETRIES) == 0) {
                ALOGW("Waiting for SurfaceFlinger, waited for %" PRId64 " ms",
                      elapsedRealtime() - waitStartTime);
            }
            usleep(SERVICE_WAIT_SLEEP_MS * 1000);
        };
        int64_t totalWaited = elapsedRealtime() - waitStartTime;
        if (totalWaited > SERVICE_WAIT_SLEEP_MS) {
            ALOGI("Waiting for SurfaceFlinger took %" PRId64 " ms", totalWaited);
        }

        // create the boot animation object 开启动画
        sp<BootAnimation> boot = new BootAnimation();

        IPCThreadState::self()->joinThreadPool();
    }
    return 0;
}

BootAnimation启动

目前zygote进程还没有启动,所以没有虚拟机,此时只能是c代码运行。

BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
        mTimeFormat12Hour(false), mTimeCheckThread(NULL) {
        //创建客户端
    mSession = new SurfaceComposerClient();

    // If the system has already booted, the animation is not being used for a boot. 开机
    mSystemBoot = !android::base::GetBoolProperty(BOOT_COMPLETED_PROP_NAME, false);
    std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
    if (powerCtl.empty()) {
        mShuttingDown = false;
    } else {
        mShuttingDown = true;
    }
}

动画资源路径:
有优先级,修改这些文件可以修改开机动画以及关机动画。

static const char OEM_BOOTANIMATION_FILE[] = “/oem/media/bootanimation.zip”;
static const char SYSTEM_BOOTANIMATION_FILE[] = “/system/media/bootanimation.zip”;
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = “/system/media/bootanimation-encrypted.zip”;
static const char OEM_SHUTDOWNANIMATION_FILE[] = “/oem/media/shutdownanimation.zip”;
static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = “/system/media/shutdownanimation.zip”;

按照路径找到相应的资源,我们看一下其里面的内容:
首先其实一个压缩包 里面存放的是三个文件夹及一个txt文件:part1,part2,part3文件夹以及desc.txt。
其文件夹中存放的是一张张的图片,帧动画那种(不想截图,图片在csdn中总是压缩)。

desc.txt是对文件的配置其内容如下:
280 280 30
c 1 0 part1
c 0 0 part2
c 1 0 part3

分别进行解释:
第一行:280宽度 280 高度 30帧率
接下来几行格式一样:c固定格式,1循环一次/0无限循环,0循环间隔,单位为第一行计算的时间间隔 ,part1文件夹名称

当然如果循环读取这样多的图片是相当耗性能的,可以直接修改源代码 用opengl进行渲染。

进入bootanim.rc

service bootanim /system/bin/bootanimation
    class core animation
    user graphics
    group graphics audio
    disabled
    oneshot
    writepid /dev/stune/top-app/tasks
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈德山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值