鸿蒙OS 开机动画流程

开机动画的启动与结束

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,playsound
    runner_ = 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");
    }
#else
    LOGI("player_framework part is not enabled.");
#endif
    runner_->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 为true
    system::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;
    }
    //初始化renderSurface
    InitRsSurface();
    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_CONTEXT
    if (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);
#else
    framePtr_ = 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.json
    char *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"
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值