麻花痒 发表于 2025-4-8 23:03:09

鸿蒙OS 开机动画流程

开机动画的启动与竣事

foundation\graphic\graphic_2d\graphic.cfg
"services" : [{
      "name" : "render_service",
      "path" : ["/system/bin/render_service"],
      "critical" : ,
      "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_;
    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 = {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"
}

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 鸿蒙OS 开机动画流程