作者:汪语
一、引言
本文基于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
- 基本概念
- 构建第一个ArkTS应用
- ……
开发基础知识:https://qr21.cn/FV7h05
- 应用基础知识
- 配置文件
- 应用数据管理
- 应用安全管理
- 应用隐私保护
- 三方应用调用管控机制
- 资源分类与访问
- 学习ArkTS语言
- ……
基于ArkTS 开发:https://qr21.cn/FV7h05
- Ability开发
- UI开发
- 公共事件与通知
- 窗口管理
- 媒体
- 安全
- 网络与链接
- 电话服务
- 数据管理
- 后台任务(Background Task)管理
- 设备管理
- 设备使用信息统计
- DFX
- 国际化开发
- 折叠屏系列
- ……
鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH
鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH
1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向