OpenHarmony 实战开发——应用启动流程分析

134 篇文章 0 订阅
3 篇文章 0 订阅

作者:汪语

一、引言

本文基于OpenAtom OpenHarmony(以下简称“OpenHarmony”) 4.0 Release版本的源码,对应用进程初始化后MainThread初始化及调用AttachApplication、LaunchApplication、LaunchAbility的过程做了分析和总结,该流程贯穿了应用程序的用户进程和系统服务进程。

二、启动框架与核心类简介

1. 启动框架须知

如下图所示,OpenHarmony应用冷启动过程大致分为四个阶段:应用进程创建&初始化、Application&Ability初始化、Ability/AbilityStage生命周期、加载绘制首页。

2. 应用启动流程的核心类须知

●AppMgrService是应用管理服务主线程类,实现了IPC调用IAppMgr的接口,并通过AMSEventHandler将进程内各类事件及任务发送到主线程。
●AppRunningManager记录了应用的信息、应用的运行状态、进程信息等,内部持有了模块运行信息列表,应用第一次启动时,会先创建。
●AppSpawn是app孵化器,通过监听本地socket,接收客户端的请求消息。创建Ability应用所在进程,为Ability应用设置相应的权限,并预加载一些通用的模块。
●AbilityLoader负责注册和加载开发者Ability模块。开发者开发的Ability先调用AbilityLoader的注册接口注册到框架中,接着Ability启动时会被实例化。
●AbilityManager负责AbilityKit和Ability管理服务进行IPC的通信。
●MainThread是应用进程的核心类。应用进程内各类事件及任务通过MainThread中mainHandler投递到主线程并调用MainThread中的方法执行。
●AbilityThread是应用线程的核心类,是操作各种Ability生命周期及方法的入口。

三、源码分析

1.主线程初始化,通过IPC机制,AMS调用AttachApplication,再回调AMS端

foundation\ability\ability_runtime\frameworks\native\appkit\app\main_thread.cpp


 void MainThread::Start() 
 {
     sptr<MainThread> thread = sptr<MainThread>(new (std::nothrow) MainThread());
     ......
     thread->Init(runner);
     thread->Attach();  }

void MainThread::Init()
{
    auto task = [weak]() {
        auto appThread = weak.promote();
        appThread->SetRunnerStarted(true);
    };
    if (!mainHandler_->PostTask(task)) {
        HILOG_ERROR("MainThread::Init PostTask task failed");
    }
    watchdog_->Init(mainHandler_);
    extensionConfigMgr_->Init();
}

void MainThread::Attach()
{
    if (!ConnectToAppMgr()) {
        return;
    }
    mainThreadState_ = MainThreadState::ATTACH;
}

bool MainThread::ConnectToAppMgr()
{
    auto object = OHOS::DelayedSingleton<SysMrgClient>::GetInstance()->GetSystemAbility(APP_MGR_SERVICE_ID);
    appMgr_ = iface_cast<IAppMgr>(object);
    appMgr_->AttachApplication(this);  
}

客户端发送 attach application 请求foundation\ability\ability_runtime\interfaces\inner_api\app_manager\src\appmgr\app_mgr_proxy.cpp


AppMgrProxy::AttachApplication(const sptr<IRemoteObject> &obj)
{
    sptr<IRemoteObject> remote = Remote();
    remote->SendRequest(static_cast<uint32_t>(IAppMgr::Message::APP_ATTACH_APPLICATION), ...);
}

服务端收到 attach application 请求foundation\ability\ability_runtime\interfaces\inner_api\app_manager\src\appmgr\app_mgr_stub.cpp

int32_t AppMgrStub::HandleAttachApplication(MessageParcel &data, MessageParcel &reply)
{
    sptr<IRemoteObject> client = data.ReadRemoteObject();
    AttachApplication(client);  
}

foundation\ability\ability_runtime\services\appmgr\src\app_mgr_service.cpp

void AppMgrService::AttachApplication(const sptr<IRemoteObject> &app)
{
   pid_t pid = IPCSkeleton::GetCallingPid();
    AddAppDeathRecipient(pid);
    std::function<void()> attachApplicationFunc =
        std::bind(&AppMgrServiceInner::AttachApplication, appMgrServiceInner_, pid, iface_cast<IAppScheduler>(app));
    taskHandler_->SubmitTask(attachApplicationFunc, TASK_ATTACH_APPLICATION);
}

函数处理逻辑回到服务层foundation\ability\ability_runtime\services\appmgr\src/app_mgr_service_inner.cpp


void AppMgrServiceInner::AttachApplication(const pid_t pid, const sptr<IAppScheduler> &appScheduler)
{
    ......
    appRecord->SetApplicationClient(appScheduler);
    appRecord->RegisterAppDeathRecipient();
    if (appRecord->GetState() == ApplicationState::APP_STATE_CREATE) {
        LaunchApplication(appRecord);
    }
    eventInfo.pid = appRecord->GetPriorityObject()->GetPid();
    eventInfo.processName = appRecord->GetProcessName();
    AAFwk::EventReport::SendAppEvent(AAFwk::EventName::APP_ATTACH, HiSysEventType::BEHAVIOR, eventInfo);
}

void AppMgrServiceInner::LaunchApplication(const std::shared_ptr<AppRunningRecord> &appRecord)
{
    appRecord->LaunchApplication(*configuration_);
    appRecord->SetState(ApplicationState::APP_STATE_READY);
    appRecord->SetRestartResidentProcCount(restartResidentProcCount);
    ......
    appRecord->LaunchPendingAbilities();
    AAFwk::EventReport::SendAppEvent(AAFwk::EventName::APP_LAUNCH, HiSysEventType::BEHAVIOR, eventInfo);
}

2.应用初始化,通过AppRunningRecord调用LaunchApplication

应用第一次启动时,会先创建AppRunningRecordfoundation\ability\ability_runtime\services\appmgr\src\app_running_record.cpp

void AppRunningRecord::LaunchApplication(const Configuration &config)
{
    appLifeCycleDeal_->GetApplicationClient()
    ......
    launchData.SetProcessInfo(processInfo);
    launchData.SetRecordId(appRecordId_);
    launchData.SetUId(mainUid_);
    launchData.SetUserTestInfo(userTestRecord_);
    launchData.SetAppIndex(appIndex_);
    appLifeCycleDeal_->LaunchApplication(launchData, config);
}

foundation\ability\ability_runtime\services\appmgr\src\app_lifecycle_deal.cpp

void AppLifeCycleDeal::LaunchAbility(const std::shared_ptr<AbilityRunningRecord> &ability)
{
    appThread_->ScheduleLaunchApplication(launchData, config);
}

处理启动应用(加载依赖库、初始化资源管理器等)等逻辑foundation\ability\ability_runtime\frameworks\native\appkit\app\main_thread.cpp


void MainThread::ScheduleLaunchApplication(const AppLaunchData &data, const Configuration &config)
{
    appThread->HandleLaunchApplication(data, config);
}

void MainThread::HandleLaunchApplication(const AppLaunchData &data, const Configuration &config)
{
    if (!InitCreate(contextDeal, appInfo, processInfo)) {
        return;
    }
    if (IsNeedLoadLibrary(bundleName)) {
        ChangeToLocalPath(bundleName, appInfo.moduleSourceDirs, localPaths);
        LoadAbilityLibrary(localPaths);
        LoadNativeLiabrary(bundleInfo, appInfo.nativeLibraryPath);
    }
    if (appInfo.needAppDetail) {
        LoadAppDetailAbilityLibrary(appInfo.appDetailAbilityLibraryPath);
    }
    LoadAppLibrary();
    if (isStageBased) {
        AppRecovery::GetInstance().InitApplicationInfo(GetMainHandler(), GetApplicationInfo());
    }
    // create contextImpl
    ......
    if (isStageBased) {
        // Create runtime
        ......
        application_->SetRuntime(std::move(runtime));
        AbilityLoader::GetInstance().RegisterAbility("Ability", [application = application_]() {
            return Ability::Create(application->GetRuntime());
        });
    LoadAllExtensions(jsEngine);
    contextDeal->initResourceManager(resourceManager);
    contextDeal->SetApplicationContext(application_);
    application_->AttachBaseContext(contextDeal);
    application_->SetAbilityRecordMgr(abilityRecordMgr_);
    application_->SetConfiguration(config);
    contextImpl->SetConfiguration(application_->GetConfiguration());

    applicationImpl_->SetRecordId(appLaunchData.GetRecordId());
    applicationImpl_->SetApplication(application_);
    mainThreadState_ = MainThreadState::READY;
    ......
    applicationImpl_->PerformAppReady()
    nwebMgr->PreStartNWebSpawnProcess();
    ......
    // init resourceManager.
    ......
}

3. 通过RunningRecord调用LaunchPendingAbilities,最终创建Ability

foundation\ability\ability_runtime\services\appmgr\src/module_running_record.cpp

void ModuleRunningRecord::LaunchPendingAbilities()
{
    for (const auto &item : abilities_) {
        const auto &ability = item.second;
        if (ability->GetState() == AbilityState::ABILITY_STATE_CREATE && ability->GetToken() &&
            appLifeCycleDeal_->GetApplicationClient()) {
            appLifeCycleDeal_->LaunchAbility(ability);
            ability->SetState(AbilityState::ABILITY_STATE_READY);
        }
    }
}
void ModuleRunningRecord::LaunchAbility(const std::shared_ptr<AbilityRunningRecord> &ability)
{
    appLifeCycleDeal_->LaunchAbility(ability);
    ability->SetState(AbilityState::ABILITY_STATE_READY);
}

通过IPC调用ScheduleLaunchAbility函数
foundation\ability\ability_runtime\services\appmgr\src/app_lifecycle_deal.cpp

AppLifeCycleDeal::LaunchAbility(const std::shared_ptr<AbilityRunningRecord> &ability)
{
    if (appThread_ && ability) {
        appThread_->ScheduleLaunchAbility(*(ability->GetAbilityInfo()), ability->GetToken(),
            ability->GetWant());
    }
}

foundation\ability\ability_runtime\frameworks\native\appkit\app\main_thread.cpp

MainThread::ScheduleLaunchAbility(const AbilityInfo &info, const sptr<IRemoteObject> &token, const std::shared_ptr<AAFwk::Want> &want)
{
    auto task = [weak, abilityRecord]() {
        ...
        auto appThread = weak.promote();
        appThread->HandleLaunchAbility(abilityRecord);
    };
    mainHandler_->PostTask(task);
}
 MainThread::HandleLaunchAbility(const std::shared_ptr<AbilityLocalRecord> &abilityRecord)
 {
    abilityRecordMgr_->SetToken(abilityToken);
    abilityRecordMgr_->AddAbilityRecord(abilityToken, abilityRecord);
    //创建AbilityStage
    std::shared_ptr<AbilityRuntime::Context> stageContext = application_->AddAbilityStage(abilityRecord);
    //启动Ability线程
    AbilityThread::AbilityThreadMain(application_, abilityRecord, stageContext);  
 }

foundation\ability\ability_runtime\frameworks\native\appkit\app\ohos_application.cpp

bool OHOSApplication::AddAbilityStage(const AppExecFwk::HapModuleInfo &hapModuleInfo)
{
     ......
    auto stageContext = std::make_shared<AbilityRuntime::ContextImpl>();
    stageContext->SetParentContext(abilityRuntimeContext_);
    stageContext->InitHapModuleInfo(hapModuleInfo);
    stageContext->SetConfiguration(GetConfiguration());
    auto abilityStage = AbilityRuntime::AbilityStage::Create(runtime_, *moduleInfo);
    abilityStage->Init(stageContext);
    Want want;
    abilityStage->OnCreate(want);
    abilityStages_[hapModuleInfo.moduleName] = abilityStage;
    return true;
}

foundation\ability\ability_runtime\frameworks\native\appkit\ability_runtime\app\ability_stage.cpp

std::shared_ptr<AbilityStage> AbilityStage::Create(
    const std::unique_ptr<Runtime>& runtime, const AppExecFwk::HapModuleInfo& hapModuleInfo)
{
    ......
    switch (runtime->GetLanguage()) {
        case Runtime::Language::JS:
            return JsAbilityStage::Create(runtime, hapModuleInfo);
        default:
            return std::make_shared<AbilityStage>();
    }
}

void AbilityStage::AddAbility(const sptr<IRemoteObject> &token,
    const std::shared_ptr<AppExecFwk::AbilityLocalRecord> &abilityRecord)
{
    ......
    abilityRecords_[token] = abilityRecord;
}

foundation\ability\ability_runtime\frameworks\native\appkit\ability_runtime\app\js_ability_stage.cpp

std::shared_ptr<AbilityStage> JsAbilityStage::Create(){
    auto& jsRuntime = static_cast<JsRuntime&>(*runtime);
    std::string srcPath(hapModuleInfo.name);
    std::string moduleName(hapModuleInfo.moduleName);
    moduleName.append("::").append("AbilityStage");
    ......
    //srcPath.append("/assets/js/");
    //srcPath.append("AbilityStage.abc");
    srcPath.append(hapModuleInfo.srcPath);
    srcPath.append("/AbilityStage.abc");
    auto moduleObj = jsRuntime.LoadModule(moduleName, srcPath, hapModuleInfo.hapPath,
        hapModuleInfo.compileMode == AppExecFwk::CompileMode::ES_MODULE, commonChunkFlag);
    return std::make_shared<JsAbilityStage>(jsRuntime, std::move(moduleObj));
}

void JsAbilityStage::Init(const std::shared_ptr<Context> &context)
{
    AbilityStage::Init(context);
}

void JsAbilityStage::OnCreate(const AAFwk::Want &want) const
{
    AbilityStage::OnCreate(want);
    ......
    auto& nativeEngine = jsRuntime_.GetNativeEngine();
    NativeValue* value = jsAbilityStageObj_->Get();
    nativeEngine.CallFunction(value, methodOnCreate, nullptr, 0);
}
//AbilityStage
void AbilityStage::Init(const std::shared_ptr<Context>& context){
    context_ = context;
}
void AbilityStage::OnCreate(const AAFwk::Want &want) cons{
    HILOG_DEBUG("AbilityStage OnCreate come.");
}

foundation\ability\ability_runtime\frameworks\native\ability\native\ability_thread.cpp


void AbilityThread::AbilityThreadMain(
    std::shared_ptr<OHOSApplication> &application, const std::shared_ptr<AbilityLocalRecord> &abilityRecord,
    const std::shared_ptr<AbilityRuntime::Context> &stageContext){
    //Attach The ability thread to the main process
    thread->Attach(application, abilityRecord, stageContext);
}

void AbilityThread::Attach(
    std::shared_ptr<OHOSApplication> &application, const std::shared_ptr<AbilityLocalRecord> &abilityRecord,
    const std::shared_ptr<AbilityRuntime::Context> &stageContext){
   // 1.new AbilityHandler 根据不同AbilityType获得abilityName
    std::string abilityName = CreateAbilityName(abilityRecord, application);
    runner_ = EventRunner::Create(abilityName);
    abilityHandler_ = std::make_shared<AbilityHandler>(runner_);
    // 2.new ability
    auto ability = AbilityLoader::GetInstance().GetAbilityByName(abilityName);
    currentAbility_.reset(ability);
    token_ = abilityRecord->GetToken();
    abilityRecord->SetEventHandler(abilityHandler_);
    abilityRecord->SetEventRunner(runner_);
    abilityRecord->SetAbilityThread(this);
    ability->AttachBaseContext(contextDeal);
    // new hap requires
    ability->AttachAbilityContext(BuildAbilityContext(abilityRecord->GetAbilityInfo(), application, token_,
        stageContext));
    // 3.new abilityImpl 
    abilityImpl_ = DelayedSingleton<AbilityImplFactory>::GetInstance()->MakeAbilityImplObject(abilityRecord->GetAbilityInfo());
    //Ability初始化操作
    abilityImpl_->Init(application, abilityRecord, currentAbility_, abilityHandler_, token_, contextDeal);
    // 4. ability attach : ipc
    ErrCode err = AbilityManagerClient::GetInstance()->AttachAbilityThread(this, token_);
}

至此,关于应用启动过程中application和ability初始化梳理清楚,OpenHarmony的源码关键Api和源码路径也都列举了出来,有疑问可自行阅读源码加深理解。

四、总结-时序图

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

  • 25
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值