Android Framework实战视频--init进程的bootanimation启动源码分析(补充Android 10部分的BootAnimation的启动源码分析)

Android Framework层开发 SystemUI路径:framework/base/package/systemUI/安装mingw,配置环境变量,即可用 gcc(类似Java的JVM)命令编译c文件;写C的工具:CodeBlocks预处理指令:#include 预处理器会对其处理条件编译指令: #if #else #elif #endif宏定义:#define PI 3.14可视化输入: scanf(“%d”, &a)C是没有GC的!C的碎片管理是依托于OS的碎片整理机制。 阅读详情

课程答疑和新课信息:QQ交流群:422901085进行课程讨论
FrameWork入门课到精通手把手实战课程

专题博客系列:
Android 8.1 zygote 启动过程源码
Android Framework实战视频–Zygote的fork进程篇
Android Framework实战视频–SystemServer启动篇
Android Framework实战视频–SystemServer启动FallbackHome篇
Android Framework实战视频–FallbackHome进程启动及Activity启动篇
Android Framework实战视频–FallbackHome结束启动Launcher篇
Android Framework实战视频–BootAnimation的启动源码分析(Android8.1)

Android Framework实战视频–init进程的bootanimation启动源码分析(补充Android 10部分的BootAnimation的启动源码分析)

Android Framework实战视频–BootAnimation的启动源码分析(补充Android 10部分的差异)

提示:针对有的同学可能代码较新这里基于Android 10源码对init部分进行分析
针对Android init进程启动property service的启动部分流程如下:
init进程的入口main函数已经不在init.cpp而是在main.cpp
路径如下:
system/core/init/main.cpp

int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
    __asan_set_error_report_callback(AsanReportCallback);
#endif

    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }

    if (argc > 1) {
        if (!strcmp(argv[1], "subcontext")) {
            android::base::InitLogging(argv, &android::base::KernelLogger);
            const BuiltinFunctionMap function_map;

            return SubcontextMain(argc, argv, &function_map);
        }

        if (!strcmp(argv[1], "selinux_setup")) {
            return SetupSelinux(argv);
        }

        if (!strcmp(argv[1], "second_stage")) {
            return SecondStageMain(argc, argv);//这里是关键,二阶段启动
        }
    }

    return FirstStageMain(argc, argv);
}

这里主要看的是二阶段启动方法SecondStageMain,该方法又是回到init.cpp

int SecondStageMain(int argc, char** argv) {
    //省略
    StartPropertyService(&property_fd);
    if (auto result = epoll.RegisterHandler(property_fd, HandlePropertyFd); !result) { //监听fd的事件
        LOG(FATAL) << "Could not register epoll handler for property fd: " << result.error();
    }
//省略
    return 0;
}

这里又看一个熟悉的方法StartPropertyService,而且传递进去了一个property_fd地址,然后对property_fd进行监听,该方法如下:

void StartPropertyService(int* epoll_socket) {
    property_set("ro.property_service.version", "2");

    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 0) {//特别注意这里双工通信
        PLOG(FATAL) << "Failed to socketpair() between property_service and init";
    }
    //特别注意这里双工通信,可以实现0端写入1端读取,1端写入0端读取
    *epoll_socket = sockets[0];//把fd传递给了指针
    init_socket = sockets[1];

    property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,false, 0666, 0, 0, nullptr);//创建PROP_SERVICE_NAME 的socket进行通信
    if (property_set_fd == -1) {
        PLOG(FATAL) << "start_property_service socket creation failed";
    }

    listen(property_set_fd, 8);

    std::thread{PropertyServiceThread}.detach();//启动线程监听数据

    property_set = [](const std::string& key, const std::string& value) -> uint32_t {
        android::base::SetProperty(key, value);
        return 0;
    };
}

这里其实和8.1差不多,主要创建socket,监听socket绑定和接收数据(特别注意这里双工通信,可以实现0端写入1端读取,1端写入0端读取),而且接收数据和对数据处理是在PropertyServiceThread方法中实现:

static void PropertyServiceThread() {
    Epoll epoll;
    if (auto result = epoll.Open(); !result) {
        LOG(FATAL) << result.error();
    }

    if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd); !result) {
        LOG(FATAL) << result.error();
    }

    if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result) {
        LOG(FATAL) << result.error();
    }

    while (true) {
        if (auto result = epoll.Wait(std::nullopt); !result) {
            LOG(ERROR) << result.error();
        }
    }
}

这里主要使用了epoll来监听各个fd的变化,这里我们主要关心是epoll.RegisterHandler(property_set_fd, handle_property_set_fd); !result),这个property_set_fd才是我们关心的fd,有数据变化这里会触发handle_property_set_fd方法:

static void handle_property_set_fd() {
  //省略
    switch (cmd) {
    case PROP_MSG_SETPROP: {
        //省略
        uint32_t result =HandlePropertySet(prop_name, prop_value, source_context, cr, nullptr, &error);     
        //省略
        break;
      }

    case PROP_MSG_SETPROP2: {
      //省略
        uint32_t result = HandlePropertySet(name, value, source_context, cr, &socket, &error);
        //省略
    default:
      //省略
        break;
    }
}

这里最后其实最后调用到了HandlePropertySet:

// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
                           const std::string& source_context, const ucred& cr,
                           SocketConnection* socket, std::string* error) {
  //省略
    if (StartsWith(name, "ctl.")) {//开机动画就是符合这个
        return SendControlMessage(name.c_str() + 4, value, cr.pid, socket, error);
    }
//省略

    return PropertySet(name, value, error);
}

代码可以看出开机动画就是符合这个“ctrl.”情况接下来执行SendControlMessage:

static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid,SocketConnection* socket, std::string* error) {
   //省略
    if (auto result = SendMessage(init_socket, property_msg); !result) {
        // We've already released the fd above, so if we fail to send the message to init, we need
        // to manually free it here.
        if (fd != -1) {
            close(fd);
        }
        *error = "Failed to send control message: " + result.error_string();
        return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
    }

    return PROP_SUCCESS;
}

这里其实就是调用SendMessage来发一个消息,但是这里大家注意发给了init_socket这个fd(就是前面说过的0端写入1端读取),那接下来在就会在init.cpp的HandlePropertyFd收到消息,故来分析方法:

static void HandlePropertyFd() {
    auto message = ReadMessage(property_fd);
   //省略
    switch (property_message.msg_case()) {
        case PropertyMessage::kControlMessage: {
            auto& control_message = property_message.control_message();
            //这里是关键,又会调用HandleControlMessage启动及判断是否成功
            bool success = HandleControlMessage(control_message.msg(), control_message.name(),
                                                control_message.pid());

            uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
            if (control_message.has_fd()) {
                int fd = control_message.fd();
                TEMP_FAILURE_RETRY(send(fd, &response, sizeof(response), 0));
                close(fd);
            }
            break;
        }
        case PropertyMessage::kChangedMessage: {
            auto& changed_message = property_message.changed_message();
            property_changed(changed_message.name(), changed_message.value());
            break;
        }
        default:
            LOG(ERROR) << "Unknown message type from property service: "
                       << property_message.msg_case();
    }
}

这里最后又调用到HandleControlMessage:

bool HandleControlMessage(const std::string& msg, const std::string& name, pid_t pid) {
//获取一个control msg的map
    const auto& map = get_control_message_map();
    const auto it = map.find(msg);
   //省略
    const ControlMessageFunction& function = it->second;//得到对应function

    Service* svc = nullptr;

    switch (function.target) {
        case ControlTarget::SERVICE:
            svc = ServiceList::GetInstance().FindService(name);//寻找出对于service
            break;
        case ControlTarget::INTERFACE:
            svc = ServiceList::GetInstance().FindInterface(name);
            break;
        default:
            LOG(ERROR) << "Invalid function target from static map key '" << msg << "': "
                       << static_cast<std::underlying_type<ControlTarget>::type>(function.target);
            return false;
    }

    if (svc == nullptr) {
        LOG(ERROR) << "Could not find '" << name << "' for ctl." << msg;
        return false;
    }

    if (auto result = function.action(svc); !result) {//获取service后,会调用function进行执行
        LOG(ERROR) << "Could not ctl." << msg << " for '" << name << "': " << result.error();
        return false;
    }
    return true;
}

其实就是根据control msg获取对应的function,然后执行方法,那具体执行什么方法呢?
这里的get_control_message_map如下:

static const std::map<std::string, ControlMessageFunction>& get_control_message_map() {
    // clang-format off
    static const std::map<std::string, ControlMessageFunction> control_message_functions = {
        {"sigstop_on",        {ControlTarget::SERVICE,
                               [](auto* service) { service->set_sigstop(true); return Success(); }}},
        {"sigstop_off",       {ControlTarget::SERVICE,
                               [](auto* service) { service->set_sigstop(false); return Success(); }}},
        {"start",             {ControlTarget::SERVICE,   DoControlStart}},
        {"stop",              {ControlTarget::SERVICE,   DoControlStop}},
        {"restart",           {ControlTarget::SERVICE,   DoControlRestart}},
        {"interface_start",   {ControlTarget::INTERFACE, DoControlStart}},
        {"interface_stop",    {ControlTarget::INTERFACE, DoControlStop}},
        {"interface_restart", {ControlTarget::INTERFACE, DoControlRestart}},
    };
    // clang-format on

    return control_message_functions;
}

所以这里我们bootanimation(“ctrl.start”)明显属于start,所以匹配的方法为DoControlStart:

static Result<Success> DoControlStart(Service* service) {
    return service->Start();
}

看到service->Start();后就知道和以前8.1一模一样了,都是service启动,不再进行分析,看对于视频或者blog既可以

安卓12开机动画Bootanimation源码分析-启动流程 安卓开机动画Bootanimation源码分析-启动流程1.配置文件路径介绍2.Bootanimation服务启动分析 1.配置文件路径介绍 目录: bootanimation: frameworks/base/cmds/bootanimation/ surfaceflinger : frameworks/native/services/surfaceflinger/ init : system/core/init/ 文件: main_surfaceflinger.cpp : frame 阅读详情

相关推荐

从源码角度看Android系统init进程启动过程

init进程是Linux系统中用户空间的第一个进程,进程号为1。Kernel启动后,在用户空间启动init进程,并调用/system/core/init.cpp中的main方法执行一些重要的工作。 备注:本文将结合Android8.0的源码看init进程的启动过程以及init进程做了哪些重要工作。 1. init进程启动前系统的启动流程 在引入init进程前,我们需要大致了解系统是如何走到init...

张许平的博客 1043

android7.1-修改开机动画

android系统修改开机动画

Paper_Love的博客 2893

Android系统启动(一)— init 进程启动过程

Android和Android系统服务。严格来说,Android系统实际是运行在Linux内核之上的一系列“服务进程”,而这些服务进程的“老祖宗”就是init进程。initAndroidPID1Androidinit.rcAndroidinit.rcinitmkdirmountinit.rcZygoteinitLinuxinit.rcinitAndroid 10对init进程的入口函数进行了调整,不再是之前的的main函数,**而是换成了的main。

xingyu19911016的博客 4721

Android SystemProperties系统属性分析

原文地址:https://skytoby.github.io/2019/Android%20SystemProperties%E7%B3%BB%E7%BB%9F%E5%B1%9E%E6%80%A7%E5%88%86%E6%9E%90/ SystemProperties.set方法可以设置系统属性,通过设置系统属性可以启动一些服务和操作,如关机,重启、uncrypt服务等。下面将分析为什么设置系统属...

skytoby 3032

[Android 13]探索ctl.属性控制服务的实现

从上面可知到当socket对端,也就是属性写入端发来数据时唤醒property-service线程,然后将消息入队,唤醒init主线程处理,第二个问题找到答案了,最后一个问题,属性控制事件怎么来的,谁发送的?搜索,实际是在bionic/libc/bionic/system_property_set.cpp中,属性写入是被libc实现为标准API了,所以每个地方写入属性都会调用到这里。这个队列中的,查找这个队列的流程,得到第二个问题的流程。根据属性的前缀,走不同的分支,我们例子看的是。开头的, 其他的同理。

qq_40731414的博客 2106

LTspice导入德州仪器SPICE模型的实用指南与常见问题解析

本文详细介绍了如何在LTspice中导入德州仪器的SPICE模型,包括模型文件获取、路径管理、导入步骤及常见问题解析。通过实用指南帮助工程师精确仿真电路性能,提升设计效率,重点涵盖了第三方模型的导入教程和最佳实践。

kk1234的博客 309

Android Framework实战视频--BootAnimation的启动源码分析(Android8.1)

课程答疑和新课信息:QQ交流群:422901085进行课程讨论 FrameWork入门课视频链接:https://edu.youkuaiyun.com/course/detail/30298 FrameWork实战课1视频链接:https://edu.youkuaiyun.com/course/detail/30275 专题博客系列: Android 8.1 zygote 启动过程源码 Android Framework实战视频–Zygote的fork进程篇 Android Framework实战视频–SystemServer启动

learnframework的博客 1396

Ubuntu 24.04 下 NoMachine 极速安装与远程桌面配置全攻略

本文详细介绍了在Ubuntu 24.04系统下安装和配置NoMachine远程桌面的完整指南。从系统准备、分步安装到性能调优和常见问题解决,帮助用户快速实现低延迟的远程桌面访问。特别适合开发者和IT管理员在Linux环境下高效部署远程工作环境。

moon9的博客 945

Android Framework学习教程-BootAnimation开机动画启动流程源码分析

课程答疑和新课信息:QQ交流群:422901085进行课程讨论 FrameWork入门课视频链接:https://edu.youkuaiyun.com/course/detail/30298 FrameWork实战课1视频链接:https://edu.youkuaiyun.com/course/detail/30275 专题博客系列: Android 8.1 zygote 启动过程源码 Android Framework实战视频–Zygote的fork进程篇 Android Framework实战视频–SystemServer启动

learnframework的博客 1707

SPI为什么不需要加上拉电阻

大家好,我是记得诚。I2C因为其开漏的结构,无法输出高电平,所以外部加上拉电阻。我们在使用SPI的时候,发现是不需要加上拉电阻的。主要因为SPI多为推挽的结构,推挽电路,高低电平都可以输出,所以外部不需要加上拉电阻。推挽电路可以用2个三极管或者2个MOS管搭建而成。

记得诚 2628

10万+字超硬核 机器学习 笔记(面试八股)

10w字总结面试中可能用到的机器学习八股和常用算法,包括感知机(Perceptron)、多层感知机(MLP, Multi-Layer Perceptron)、支持向量机(SVM, Support Vector Machine)、K 最近邻(KNN, K-Nearest Neighbors)、朴素贝叶斯(Naive Bayes)、决策树(Decision Tree)、随机森林(Random Forest)、Bagging、Boosting、GBDT、XGBoos、LightGBM等。

haopinglianlian的博客 4658

Android Framework学习视频(1)-BootAnimation开机动画启动流程源码分析

课程答疑和新课信息:QQ交流群:422901085进行课程讨论 FrameWork入门课视频链接:https://edu.youkuaiyun.com/course/detail/30298 FrameWork实战课1视频链接:https://edu.youkuaiyun.com/course/detail/30275 专题博客系列: Android 8.1 zygote 启动过程源码 Android Framework实战视频–Zygote的fork进程篇 Android Framework实战视频–SystemServer启动

liaosongmao1的专栏 715

把机器学习“搬进”数据库:SAP HANA PAL 快速上手与 ABAP AMDP 实战

摘要:本文探讨了SAP HANA PAL(Predictive Analysis Library)在企业数据分析中的实践应用。PAL通过将机器学习算法下推到数据库内部执行,有效解决了大数据量场景下的数据搬运瓶颈和治理成本问题。文章详细介绍了PAL的核心功能(包括聚类、分类、回归等10类算法)、使用前提(版本、组件和权限要求)以及通过AMDP实现ABAP与PAL集成的技术方案。重点阐述了参数表设计理念和两个典型应用场景:利用PageRank算法分析企业权限网络关系,以及通过PAL_SCALE进行特征预处理。文

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 5738

Jack server failed,Try jack-diagnose,SSL error when connecting to the Jack server,8.1,7.1系统源码编译不过

课程答疑和新课信息:QQ交流群:422901085进行课程讨论 FrameWork入门课视频链接:https://edu.youkuaiyun.com/course/detail/30298 FrameWork实战课1视频链接:https://edu.youkuaiyun.com/course/detail/30275 专题博客系列: Android 8.1 zygote 启动过程源码 Android Framework实战视频–Zygote的fork进程篇 Android Framework实战视频–SystemServer启动

learnframework的博客 4648

【阿里AgentScope框架】多框架组合:AgentScope加LangChain,让你的开发效率直线上升

本文以一个例子来看下AgentScope框架和LangChain如何实现融合使用,真的超级简单,一看就懂。这是一种思路,为多种框架的融合使用提供借鉴。

同学小张的博客 3471

YOLOv11改进 | Conv篇 | 2024最新轻量化自适应提取模块LAE助力边缘设备部署计算(附代码 + 修改教程 + 运行教程)

本文给大家带来的一个改进机制是最新由LSM-YOLO提出的轻量化自适应特征提取(Lightweight Adaptive Extraction, LAE)模块,其是LSM-YOLO模型中的关键模块,旨在进行多尺度特征提取,同时降低计算成本。LAE通过以下方式实现更有效的特征提取:多尺度特征提取、自适应特征提取。LAE模块可以在不增加额外参数的情况下提高了模型对ROI区域的检测性能。​欢迎大家订阅我的专栏一起学习YOLO!YOLOv11改进系列专栏——本专栏持续复习各种顶会内容——科研必备目录一、本文介绍。

Snu77的博客 4056

Android 12 init(5) start&stop命令流程分析

通常,在开发过程中,需要push一些修改到系统分区,之后需要重启系统使修改生效。不过,执行stop、start命令需要root权限,这点需要注意。接下来分析这两个命令的执行流程。执行start/stop程序,它的本体实际上是toolbox。执行命令可以指定特定服务,表示要启动、停止对应服务start/stop通过设置控制属性 ctl.start、ctl.stop 来启动、停止服务init 处理 ctl.start、ctl.stop属性事件,执行启动、停止服务的操作。

pecuyu 2371

2024年CSP-X复赛真题题解(T1:购物)

2024年CSP-X复赛真题题解(T1:购物)

王老师青少年编程 1180

深入讲解Android Property机制

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33873846的博客 565

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

qt QErrorMessage详解

QErrorMessage是Qt框架中用于显示错误消息的一个对话框类。它提供了一个简单的模态对话框,用于向用户显示错误或警告消息。QErrorMessage通常用于应用程序中,当需要向用户报告错误但不希望中断当前操作时。它提供了一个标准的错误消息界面,使用户能够轻松识别并响应错误。QErrorMessage对话框通常包含一个标签,用于显示错误消息文本,以及一个“显示详细信息”按钮(可选),用于显示更详细的错误信息。此外,它还提供了关闭对话框的标准按钮,如“确定”或“关闭”。

ckg3824278的博客 640

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Android-深入理解init

文章目录initinit介绍学习路线init分析解析配置文件 init init介绍 init是一个进程,它是Linux系统中用户空间的第一个进程,因为Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程,它的进程号是1,本节关注几个重要的职责: 1.init进程负责创建系统中的几个关键进程,尤其是zygote(后面会讲) 2.Android系统有很多属性,于是init就提供了一个property service(属性服务)来管理他们,那么这个属性服务是怎么工作的呢

李木子的博客 5238

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

android8.1开机动画启动分析

init.cpp AOSP/system/core/init/init.cpp SurfaceFlinger是由init进程启动的 int main(int argc, char** argv) { ... if (bootmode == "charger") { am.QueueEventTrigger("charger"); } else { am.QueueEventTrigger("late-init"); } ...

we1less的博客 1060

Android系统启动-init进程详解(Android 14)

Android系统启动之init进程

lzz214的博客 3019

安卓init进程详解

安卓init进程详解

似霰的博客 2557
上一篇: Android Framework实战视频--BootAnimation的启动源码分析(Android8.1)
下一篇: Jack server failed,Try jack-diagnose,SSL error when connecting to the Jack server,8.1,7.1系统源码编译不过
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

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

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

打赏作者

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

抵扣说明:

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

余额充值