鸿蒙OS 开机动画流程

news/2024/10/15 18:04:16/

开机动画的启动与结束

foundation\graphic\graphic_2d\graphic.cfg

"services" : [{"name" : "render_service","path" : ["/system/bin/render_service"],"critical" : [0, 5, 60],"importance" : -20,"uid" : "graphics","gid" : ["system", "tp_host"],"caps" : ["SYS_NICE"],"permission" : ["ohos.permission.REPORT_RESOURCE_SCHEDULE_EVENT"],"secon" : "u:r:render_service:s0","jobs" : {"on-restart" : "services:restartrender_service"},"once" : 0}, {"name" : "bootanimation","path" : ["/system/bin/bootanimation"],"bootevents": ["bootevent.bootanimation.started","bootevent.bootanimation.finished"],"importance" : -20,"once" : 1,"uid" : "graphics","gid" : ["graphics"],"secon" : "u:r:bootanimation:s0"}
]

foundation\graphic\graphic_2d\frameworks\bootanimation\src\main.cpp

int main(int argc, const char *argv[])
{LOGI("main enter");//等待renderService的初始化WaitRenderServiceInit();Rosen::RSInterfaces& interface = Rosen::RSInterfaces::GetInstance();Rosen::ScreenId defaultId = interface.GetDefaultScreenId();if (defaultId == Rosen::INVALID_SCREEN_ID) {LOGE("invalid default screen id, return");return 0;}//获取屏的宽高Rosen::RSScreenModeInfo modeinfo = interface.GetScreenActiveMode(defaultId);int screenWidth = modeinfo.GetScreenWidth();int screenHeight = modeinfo.GetScreenHeight();//运行动画BootAnimation bootAnimation;bootAnimation.Run(defaultId, screenWidth, screenHeight);LOGI("main exit");return 0;
}

foundation\graphic\graphic_2d\frameworks\bootanimation\src\boot_animation.cpp

void BootAnimation::Run(Rosen::ScreenId id, int screenWidth, int screenHeight)
{LOGI("Run enter");//解析配置的json文件animationConfig_.ParserCustomCfgFile();Rosen::RSInterfaces& interface = Rosen::RSInterfaces::GetInstance();//根据配置的json文件中是否配置了其他的屏,获取对应宽高if (animationConfig_.GetRotateScreenId() >= 0) {id = interface.GetActiveScreenId();LOGI("GetActiveScreenId: " BPUBU64 "", id);Rosen::RSScreenModeInfo modeinfo = interface.GetScreenActiveMode(id);screenWidth = modeinfo.GetScreenWidth();screenHeight = modeinfo.GetScreenHeight();LOGI("screenWidth: %{public}d, screenHeight: %{public}d", screenWidth, screenHeight);if (id > 0) {LOGI("SetScreenPowerStatus POWER_STATUS_OFF_FAKE: 0");interface.SetScreenPowerStatus(0, Rosen::ScreenPowerStatus::POWER_STATUS_OFF_FAKE);LOGI("SetScreenPowerStatus POWER_STATUS_ON: " BPUBU64 "", id);interface.SetScreenPowerStatus(id, Rosen::ScreenPowerStatus::POWER_STATUS_ON);}} else if (interface.GetScreenPowerStatus(id) != Rosen::ScreenPowerStatus::POWER_STATUS_ON) {//设置屏幕状态为点亮状态interface.SetScreenPowerStatus(id, Rosen::ScreenPowerStatus::POWER_STATUS_ON);}//异步处理init,playvideo,playsoundrunner_ = AppExecFwk::EventRunner::Create(false);mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);mainHandler_->PostTask(std::bind(&BootAnimation::Init, this, id, screenWidth, screenHeight));LOGI("PostTask Init");
#ifdef PLAYER_FRAMEWORK_ENABLE//根据配置设置是否支持开机视频if (animationConfig_.IsBootVideoEnabled()) {mainHandler_->PostTask(std::bind(&BootAnimation::PlayVideo, this));LOGI("PostTask PlayVideo");} else {mainHandler_->PostTask(std::bind(&BootAnimation::PlaySound, this));LOGI("PostTask PlaySound");}
#elseLOGI("player_framework part is not enabled.");
#endifrunner_->Run();
}......void BootAnimation::Init(Rosen::ScreenId defaultId, int32_t width, int32_t height)
{defaultId_ = defaultId;windowWidth_ = width;windowHeight_ = height;LOGI("Init enter, width: %{public}d, height: %{public}d", width, height);//计算中心点坐标InitPicCoordinates();//配置RSDisplayNodeConfig的displayOffset,frame,bounds等参数InitRsDisplayNode();//配置RSSurfaceNodeConfig的PositionZ,FrameGravity,BackgroundColor,bounds等参数InitRsSurfaceNode();
#ifdef PLAYER_FRAMEWORK_ENABLE//根据配置设置是否支持开机视频if (animationConfig_.IsBootVideoEnabled()) {LOGI("Init end");return;}
#endif//使用序列帧动画播放LOGI("Playing boot animation using sequence frames.");//投票bootevent.bootanimation.started 为truesystem::SetParameter("bootevent.bootanimation.started", "true");auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance();while (receiver_ == nullptr) {//获取VSyncReceiver的代理端,用于显示receiver_ = rsClient.CreateVSyncReceiver("BootAnimation", mainHandler_);}VsyncError ret = receiver_->Init();if (ret) {LOGE("vsync receiver init failed: %{public}d", ret);PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));return;}//初始化renderSurfaceInitRsSurface();ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::preload");//通过读取配置的图片动画,获取对应的大小if (animationConfig_.ReadPicZipFile(imageVector_, freq_)) {imgVecSize_ = imageVector_.size();} else {LOGE("Read PicZipFile failed");PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));return;}ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);OHOS::Rosen::VSyncReceiver::FrameCallback fcb = {.userData_ = this,//显示回调.callback_ = std::bind(&BootAnimation::OnVsync, this),};//开机动画的送显帧率int32_t changefreq = static_cast<int32_t>((1000.0 / freq_) / 16);ret = receiver_->SetVSyncRate(fcb, changefreq);if (ret) {PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));LOGE("SetVSyncRate failed: %{public}d %{public}d %{public}d", ret, freq_, changefreq);return;} else {LOGI("SetVSyncRate success: %{public}d %{public}d", freq_, changefreq);}
}......void BootAnimation::OnVsync()
{//绘制PostTask(std::bind(&BootAnimation::Draw, this));
}......void BootAnimation::Draw()
{if (picCurNo_ < (imgVecSize_ - 1)) {picCurNo_ = picCurNo_ + 1;} else {//开机动画播放完成退出CheckExitAnimation();return;}ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw RequestFrame");auto frame = rsSurface_->RequestFrame(windowWidth_, windowHeight_);if (frame == nullptr) {LOGE("Draw frame is nullptr");return;}ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
#ifdef NEW_RENDER_CONTEXTif (rsSurface_ == nullptr) {LOGE("rsSurface is nullptr");return;}auto canvas = rsSurface_->GetCanvas();//开始绘制OnDraw(canvas, picCurNo_);ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw FlushFrame");rsSurface_->FlushFrame();ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
#elseframePtr_ = std::move(frame);auto canvas = framePtr_->GetCanvas();OnDraw(canvas, picCurNo_);ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::Draw FlushFrame");rsSurface_->FlushFrame(framePtr_);ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
#endif
}.....void BootAnimation::OnDraw(SkCanvas* canvas, int32_t curNo)
{if (canvas == nullptr) {LOGE("OnDraw canvas is nullptr");return;}if (curNo > (imgVecSize_ - 1) || curNo < 0) {return;}std::shared_ptr<ImageStruct> imgstruct = imageVector_[curNo];sk_sp<SkImage> image = imgstruct->imageData;ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawRect");SkPaint backPaint;backPaint.setColor(SK_ColorBLACK);canvas->drawRect(SkRect::MakeXYWH(0.0, 0.0, windowWidth_, windowHeight_), backPaint);ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, "BootAnimation::OnDraw in drawImageRect");SkPaint paint;SkRect rect;rect.setXYWH(pointX_, pointY_, realWidth_, realHeight_);canvas->drawImageRect(image.get(), rect, SkSamplingOptions(), &paint);ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
}......bool BootAnimation::CheckExitAnimation()
{if (!isAnimationEnd_) {LOGI("Boot animation is end");//投票system::SetParameter("bootevent.bootanimation.finished", "true");isAnimationEnd_ = true;}//检查所有的投票事件是否都已经完成std::string bootEventCompleted = system::GetParameter("bootevent.boot.completed", "false");if (bootEventCompleted == "true") {mainHandler_->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner_));LOGI("Read bootevent.boot.completed is true");return true;}return false;
}#ifdef PLAYER_FRAMEWORK_ENABLE
void BootAnimation::PlaySound()
{LOGI("PlaySound start");bool bootSoundEnabled = BootAnimationUtils::GetBootAnimationSoundEnabled();if (bootSoundEnabled == true) {LOGI("PlaySound read bootSoundEnabled is true");if (soundPlayer_ == nullptr) {soundPlayer_ = Media::PlayerFactory::CreatePlayer();}std::string uri = animationConfig_.GetSoundUrl();soundPlayer_->SetSource(uri);soundPlayer_->SetLooping(false);soundPlayer_->PrepareAsync();soundPlayer_->Play();}LOGI("PlaySound end");
}
#endif#ifdef PLAYER_FRAMEWORK_ENABLE
void BootAnimation::PlayVideo()
{LOGI("PlayVideo start w:%{public}d h:%{public}d", windowWidth_, windowHeight_);if (!animationConfig_.IsBootVideoEnabled()) {return;}fcb_ = {.userData_ = this,.callback_ = std::bind(&BootAnimation::CloseVideoPlayer, this),};LOGI("PlayVideo setVideo screenId:%{public}d", (int32_t)defaultId_);bootVideoPlayer_ = std::make_shared<BootVideoPlayer>();bootVideoPlayer_->SetVideoPath(defaultId_ == 0 ? animationConfig_.GetBootVideoPath() : animationConfig_.GetBootExtraVideoPath());bootVideoPlayer_->SetPlayerSurface(rsSurfaceNode_ ? rsSurfaceNode_->GetSurface() : nullptr);bootVideoPlayer_->SetCallback(&fcb_);if (!bootVideoPlayer_->PlayVideo()) {LOGE("Play video failed.");CloseVideoPlayer();}
}
#endif

foundation\graphic\graphic_2d\frameworks\bootanimation\src\boot_animationconfig.cpp

void BootAnimationConfig::ParserCustomCfgFile()
{//读取对应的开机播放的图片动画,视频,音频std::string file = GetCustomCfgFile();if (!file.empty()) {//解析出对应的文件地址ReadCustomBootConfig(file, custConfig_);//根据配置设置是否支持开机视频CheckBootVideoEnabled();}
}......std::string BootAnimationConfig::GetCustomCfgFile()
{std::string ret = "";char buf[MAX_PATH_LEN] = {0};//获取文件etc/bootanimation/bootanimation_custom_config.jsonchar *pfile = GetOneCfgFile(BOOT_CUSTOM_PATHSUFFIX.c_str(), buf, MAX_PATH_LEN);if (pfile != nullptr) {LOGI("get one filePath:%{public}s", pfile);return pfile;} else {LOGI("not find %{public}s", BOOT_CUSTOM_PATHSUFFIX.c_str());}return ret;
}

bootanimation_custom_config.json文件如下
配置了对应的开机播放的图片动画,视频,音频

{"cust.bootanimation.pics": "/sys_prod/etc/bootanimation/cust_bootpic.zip","cust.bootanimation.sounds": "/sys_prod/etc/bootanimation/cust_bootsound.wav","cust.bootanimation.video": "/sys_prod/etc/bootanimation/cust_bootvideo.mp4"
}

http://www.ppmy.cn/news/1539540.html

相关文章

现货黄金价格走势图策略分析 先看“势”

在现货黄金投资市场&#xff0c;对金价走势图的趋势进行分析&#xff0c;是投资者做出明智决策的关键步骤。通过有效的趋势分析&#xff0c;投资者可以更好地预测市场的走向&#xff0c;从而制定相应的交易策略。本文将详细介绍如何分析金价的趋势&#xff0c;并探讨这种分析方…

麒麟(Kylin)系统下安装MySQL 5.7.44(离线版)

目录 1、下载MySQL安装包2、卸载系统自带的mariadb和已安装过的MySQL包3、解压bundle.tar4、安装MySQL5、修改配置文件&#xff1a;vi /etc/my.cnf6、启动MySQL7、查看临时密码&#xff0c;并修改密码&#xff0c;授权远程访问。8、常见问题8.1 启动mysql内存溢出8.2 安装mysql…

服务器与内存市场|2025预测动态早知道

根据TrendForce的数据分析报告&#xff0c;三大DRAM供应商在2023年服务器总bit增长率经历了不同程度下滑后&#xff0c;2024年市场迎来了反弹&#xff0c;增长率分别达到了9.9%/12.3%/24.1%。这一转变表明服务器DRAM在三大供应商中的比例预计将会增加。与此同时&#xff0c;由于…

vite 配置开发环境和测试环境,接口 API 自动切换

在Vite项目中配置开发环境和测试环境&#xff0c;并实现接口API的自动切换&#xff0c;可以通过配置环境变量和相应的代理设置来完成。以下是一个详细的步骤指南&#xff1a; 一、创建环境文件 在项目根目录下创建.env、.env.development和.env.test文件&#xff0c;用于存储…

【Linux】命令行下的增删查改之“查看”

致谢:Linux常用命令大全(手册) – 真正好用的Linux命令在线查询网站 提供的命令查询 头部内容获取(head) head命令的功能是显示文件开头的内容&#xff0c;默认值为前10行。 指令参数&#xff1a; -n 定义显示行数 -c 指定显示头部内容的字符数 -v 总是显示文件名的头信…

洗衣店管理新思路:Spring Boot订单管理系统

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常适…

.net core 实现多线程方式有哪些

在 .NET Core 中&#xff0c;有多种方式可以实现多线程编程。这些方式包括使用 Thread 类、Task 和 Parallel 类库。每种方法都有其适用场景和优缺点。下面我将通过代码示例来展示这些不同的多线程实现方式。 1. 使用 Thread 类 Thread 类是 .NET 中最基本的多线程实现方式。…

less和sass基本使用

变量 变量在LESS和SASS中都以符号定义&#xff0c;可以在全局范围内使用&#xff0c;也可以在局部范围内定义和使用。 LESS示例&#xff1a; primary-color: #3498db; padding: 15px;.article {background-color: primary-color;padding: padding; }SASS示例&#xff1a; $…