前言

safwk组件隶属于系统服务管理子系统,该子系统提供系统服务的启动、注册、查询等功能,提供查询跨设备的分布式系统服务。在系统服务管理子系统中,safwk组件定义了OpenHarmony中SystemAbility的实现方法,并提供启动、注册等接口实现。

系统服务框架图如下:

 

文件结构

/foundation/systemabilitymgr │── safwk               # 组件目录   ├── bundle.json      # 组件描述及编译脚本   ├── etc              # 配置文件   ├── interfaces       # 对外接口目录   ├── services         # 组件服务实现   ├── test             # 测试用例

接口说明

接口名 接口描述
sptr<IRemoteObject> GetSystemAbility(int32_t systemAbilityId); 获取指定系统服务的RPC对象。
bool Publish(sptr<IRemoteObject> systemAbility); 发布系统服务。
virtual void DoStartSAProcess(const std::string& profilePath) = 0; 根据SA profile配置启动System Ability。

使用说明

SystemAbility是OpenHarmony的标准服务程序,简称为sa,其实现一般采用XXX.cfg + profile.xml + libXXX.z.so的方式由init进程执行对应的XXX.cfg文件拉起相关SystemAbility进程,启动后注册到samgr。一般来说,一个sa对应一个so,但有个别so同时提供多个sa,比如窗口子系统组件同时提供了dms和wms等2个sa。

SystemAbility的实现代码如下:

  1. 定义IPC对外接口IXXX

定义该服务对外提供的能力集合函数,统一继承IPC接口类IRemoteBroker;同时实现该IPC对外接口唯一标识符 DECLARE_INTERFACE_DESCRIPTOR(XXX);该 标识符用于IPC通信的校验等目的。

namespace OHOS {     class IListenAbility : public IRemoteBroker {     public:         virtual int AddVolume(int volume) = 0;     public:         enum {             ADD_VOLUME = 1,        };     public:         DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.test.IListenAbility");    }; }
  1. 定义客户端通信代码XXXProxy

namespace OHOS {     class ListenAbilityProxy : public IRemoteProxy < IListenAbility > {     public:         int AddVolume(int volume);          explicit ListenAbilityProxy(const sptr < IRemoteObject >& impl)        : IRemoteProxy < IListenAbility >(impl)        {        }      private:         static inline BrokerDelegator < ListenAbilityProxy > delegator_;    }; } // namespace OHOS
  1. 定义服务端通信代码XXXStub

namespace OHOS { int32_t ListenAbilityStub::OnRemoteRequest(uint32_t code,MessageParcel& data, MessageParcel &reply, MessageOption &option) {     switch (code) {         case ADD_VOLUME: {             return reply.WriteInt32(AddVolume(data.ReadInt32()));        }          default:             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);    } } }
  1. SystemAbility的实现类

nnamespace {     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001800, "sa_TST"}; }  REGISTER_SYSTEM_ABILITY_BY_ID(ListenAbility, DISTRIBUTED_SCHED_TEST_LISTEN_ID, true);  ListenAbility::ListenAbility(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate) {     HiLog::Info(LABEL, ":%s called", __func__);     HiLog::Info(LABEL, "ListenAbility()"); }  ListenAbility::~ListenAbility() {     HiLog::Info(LABEL, "~ListenAbility()"); }  int ListenAbility::AddVolume(int volume) {     pid_t current = getpid();     HiLog::Info(LABEL, "ListenAbility::AddVolume volume = %d, pid = %d.", volume, current);     return (volume + 1); }  void ListenAbility::OnDump() { }  void ListenAbility::OnStart() {     HiLog::Info(LABEL, "ListenAbility::OnStart()");     HiLog::Info(LABEL, "ListenAbility:%s called:-----Publish------", __func__);     bool res = Publish(this);     if (res) {         HiLog::Error(LABEL, "ListenAbility: res == false");    }     HiLog::Info(LABEL, "ListenAbility:%s called:AddAbilityListener_OS_TST----beg-----", __func__);     AddSystemAbilityListener(DISTRIBUTED_SCHED_TEST_OS_ID);     HiLog::Info(LABEL, "ListenAbility:%s called:AddAbilityListener_OS_TST----end-----", __func__);      HiLog::Info(LABEL, "ListenAbility:%s called:StopAbility_OS_TST----beg-----", __func__);     StopAbility(DISTRIBUTED_SCHED_TEST_OS_ID);     HiLog::Info(LABEL, "ListenAbility:%s called:StopAbility_OS_TST----end-----", __func__);     return; }  void ListenAbility::OnStop() { }amespace { constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001800, "sa_TST"}; }  REGISTER_SYSTEM_ABILITY_BY_ID(ListenAbility, DISTRIBUTED_SCHED_TEST_LISTEN_ID, true);  ListenAbility::ListenAbility(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate) {     HiLog::Info(LABEL, ":%s called", __func__);     HiLog::Info(LABEL, "ListenAbility()"); }  ListenAbility::~ListenAbility() {     HiLog::Info(LABEL, "~ListenAbility()"); }  int ListenAbility::AddVolume(int volume) {     pid_t current = getpid();     HiLog::Info(LABEL, "ListenAbility::AddVolume volume = %d, pid = %d.", volume, current);     return (volume + 1); }  void ListenAbility::OnDump() { }  void ListenAbility::OnStart() {     HiLog::Info(LABEL, "ListenAbility::OnStart()");     HiLog::Info(LABEL, "ListenAbility:%s called:-----Publish------", __func__);     bool res = Publish(this);     if (res) {         HiLog::Error(LABEL, "ListenAbility: res == false");    }     HiLog::Info(LABEL, "ListenAbility:%s called:AddAbilityListener_OS_TST----beg-----", __func__);     AddSystemAbilityListener(DISTRIBUTED_SCHED_TEST_OS_ID);     HiLog::Info(LABEL, "ListenAbility:%s called:AddAbilityListener_OS_TST----end-----", __func__);      HiLog::Info(LABEL, "ListenAbility:%s called:StopAbility_OS_TST----beg-----", __func__);     StopAbility(DISTRIBUTED_SCHED_TEST_OS_ID);     HiLog::Info(LABEL, "ListenAbility:%s called:StopAbility_OS_TST----end-----", __func__);     return; }  void ListenAbility::OnStop() { }
  1. SytemAbility配置

以c++实现的sa必须配置相关System Ability的profile配置文件,才会完成sa的加载注册逻辑,否则没有编写profile配置的System Ability不会完成注册。配置方法如下:在子系统的根目录新建一个以sa_profile为名的文件夹,然后在此文件夹中新建两个文件:一个以serviceId为前缀的xml文件,另外一个为BUILD.gn文件。

serviceid.xml:

<?xml version="1.0" encoding="UTF-8"?> <info>     <process>listen_test</process>     <systemability>     <name>serviceid</name>     <libpath>/system/lib64/liblistentest.z.so</libpath>     <run-on-create>true</run-on-create>     <distributed>false</distributed>     <dump-level>1</dump-level> </systemability> </info>
  • process:容器程序名。

  • name: sa编号,每个sa都有一个唯一的数字编号。

  • libpath: sa所对应的库。

  • run-on-create: 是否容器运行起来时即刻创建sa。为true表示sa随容器启动,为false表示按需拉起。

  • distributed: 是否分布式。true表示该SystemAbility为分布式SystemAbility,支持跨设备访问;false表示只有本地跨IPC访问。

  • dump-level: 拉起优先级。依次为:引导拉起、核心拉起和其他。

BUILD.gn:

import("//build/ohos/sa_profile/sa_profile.gni") ohos_sa_profile("xxx_sa_profile") {     sources = [         "serviceid.xml"    ]     subsystem_name = "systemabilitymgr" }

5.1. cfg配置文件

cfg配置文件为linux提供的native进程拉起策略,开机启动阶段由init进程解析配置的cfg文件进行拉起。该配置文件表示init在normal阶段会拉起listen_test服务。服务程序为sa_main,配置文件名为listen_test.xml。

{     "jobs" : [{             "name" : "post-fs-data",             "cmds" : [                 "start listen_test"            ]        }    ],  "services" : [{             "name" : "listen_test",             "path" : ["/system/bin/sa_main", "/system/profile/listen_test.xml"],             "uid" : "system",             "gid" : ["system", "shell"]        }    ] }

5.2. sa的按需启动和创建启动

sa有三种启动模式。

  • 创建启动

系统启动时init拉起容器程序,在容器程序启动时,即load该sa的lib库,创建sa对象,并调用其start。

  • 按需启动

系统启动时init拉起容器程序,容器程序启动时,并不启动该sa。而是等待需要sa时才创建。

  • 动态启动

系统启动时容器程序不拉起,而是后期在运行过程中动态拉起(给init发指令)。

sakfw组件的实现

main

main.cpp文件路径为:foundation\systemabilitymgr\safwk\services\safwk\src\main.cpp。

最多可以传入两个参数:profile xml和sa_id。这两个值默认为:/system/usr/default.xml和-1。这样main的启动方式有3种,目前有两种被使用。一种用于默认拉起,一种用户按需拉起。

namespace { const string TAG = "saMain"; using ProcessNameSetFunc = std::function<void(const string&)>; constexpr auto DEFAULT_XML = "/system/usr/default.xml"; // The pid name can be up to 16 bytes long, including the terminating null byte. // So need to set the max length of pid name to 15 bytes. constexpr size_t MAX_LEN_PID_NAME = 15; constexpr int PROFILE_INDEX = 1; constexpr int saID_INDEX = 2; constexpr int DEFAULT_saID = -1; constexpr int DEFAULT_LOAD = 1; constexpr int ONDEMAND_LOAD = 2; }

LocalAbilityManagerStub类

Stub类,用于和samgr通信,samgr会通过向本类发送拉起ondemand sa指令实现按需拉起。

local_ability_manager_stub.cpp文件路径为:foundation\systemabilitymgr\safwk\services\safwk\src\local_ability_manager_stub.cpp。

SystemAbility类

sa对象的基类,定义了一些通用接口。

system_ability.cpp的文件路径为:\foundation\systemabilitymgr\safwk\services\safwk\src\system_ability.cpp。

  • MakeAndRegisterAbility

将sa加入到本地map。

bool SystemAbility::MakeAndRegisterAbility(SystemAbility* systemAbility) { HILOGD(TAG, "registering system ability..."); return LocalAbilityManager::GetInstance().AddAbility(systemAbility); }

REGISTER_SYSTEM_ABILITY_BY_ID是对MakeAndRegisterAbility的封装。其在so中定义了一个静态变量。当该so被load时REGISTER_SYSTEM_ABILITY_BY_ID会生效,其会调用MakeAndRegisterAbility,传入参数包括:new出来的sa对象(构造参数包括(said和runoncreate),接着会调用AddAbility()。

namespace OHOS { #define REGISTER_SYSTEM_ABILITY_BY_ID(abilityClassName, systemAbilityId, runOnCreate) \ const bool abilityClassName##_##RegisterResult = \ SystemAbility::MakeAndRegisterAbility(new abilityClassName(systemAbilityId, runOnCreate)); ..... }
  • Publish

将sa发布到samgr

bool SystemAbility::Publish(sptr<IRemoteObject> systemAbility) { if (systemAbility == nullptr) { HILOGE(TAG, "systemAbility is nullptr"); return false; } HILOGD(TAG, "[PerformanceTest] saFWK Publish systemAbilityId:%{public}d", saId_); int64_t begin = GetTickCount(); sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (samgrProxy == nullptr) { HILOGE(TAG, "failed to get samgrProxy"); return false; } publishObj_ = systemAbility; ISystemAbilityManager::saExtraProp saExtra(GetDistributed(), GetDumpLevel(), capability_, permission_); int32_t result = samgrProxy->AddSystemAbility(saId_, publishObj_, saExtra); HILOGI(TAG, "[PerformanceTest] saFWK Publish sa:%{public}d result : %{public}d, spend:%{public}" PRId64 " ms", saId_, result, (GetTickCount() - begin)); return result == ERR_OK; }
  • Start

启动sa,会回调OnStart。

void SystemAbility::Start() { HILOGD(TAG, "starting system ability..."); if (isRunning_) { return; } HILOGD(TAG, "[PerformanceTest] saFWK OnStart systemAbilityId:%{public}d", saId_); int64_t begin = GetTickCount(); HITRACE_METER_NAME(HITRACE_TAG_saMGR, ToString(saId_) + "_OnStart"); OnStart(); isRunning_ = true; HILOGI(TAG, "[PerformanceTest] saFWK OnStart systemAbilityId:%{public}d finished, spend:%{public}" PRId64 " ms", saId_, (GetTickCount() - begin)); }
  • stop

停止sa,会回调OnStop。

void SystemAbility::Stop() { HILOGD(TAG, "stopping system ability..."); if (!isRunning_) { return; } OnStop(); isRunning_ = false; sptr < ISystemAbilityManager > samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (samgrProxy == nullptr) { HILOGE(TAG, "failed to get samgrProxy"); return; } int32_t ret = samgrProxy->RemoveSystemAbility(saId_); HILOGI(TAG, "%{public}s to remove ability", (ret == ERR_OK) ? "success" : "failed"); } 

LocalAbilityManager类

本地Ability管理类,继承了LocalAbilityManagerStub。容器程序的大部分逻辑都在本类实现。

local_ability_manager.cpp的文件路径为:\foundation\systemabilitymgr\safwk\services\safwk\src\local_ability_manager.cpp。

DoStartSAProcess

  • CheckAndGetProfilePath

检查profile xml路径合法性。(必须在/system/profile/或/system/usr/)

  • InitSystemAbilityProfiles

解析profile,得到进程名和诸多sainfo, 如解析失败则返回false并退出。检查是否是可信sa,检查方法:查看/system/profile/下是否有xxx_trust.xml文件(xxx为sa进程名), 如果存在则进行可信检查,移走不可信的sainfo。加载sa对应的库:如果sa id指定,则load单个sa的库,否则load所有runOnCreate的库。

bool LocalAbilityManager::InitSystemAbilityProfiles(const std::string& profilePath, int32_t saId) { HILOGD(TAG, "[PerformanceTest] saFWK parse system ability profiles!"); int64_t begin = GetTickCount(); bool ret = profileParser_->ParsesaProfiles(profilePath); if (!ret) { HILOGW(TAG, "ParsesaProfiles failed!"); return false; } procName_ = profileParser_->GetProcessName(); auto saInfos = profileParser_->GetAllsaProfiles(); std::string process = Str16ToStr8(procName_); HILOGI(TAG, "[PerformanceTest] saFWK parse process:%{public}s system ability profiles finished, spend:%{public}" PRId64 " ms", process.c_str(), (GetTickCount() - begin)); std::string path = PREFIX + process + SUFFIX; bool isExist = profileParser_->CheckPathExist(path); if (isExist) { CheckTrustsa(path, process, saInfos); } begin = GetTickCount(); if (saId != DEFAULT_saID) { HILOGD(TAG, "[PerformanceTest] saFWK LoadsaLib systemAbilityId:%{public}d", saId); bool result = profileParser_->LoadsaLib(saId); HILOGI(TAG, "[PerformanceTest] saFWK LoadsaLib systemAbilityId:%{public}d finished, spend:%{public}" PRId64 " ms", saId, (GetTickCount() - begin)); return result; } else { HILOGD(TAG, "[PerformanceTest] saFWK load all libraries"); profileParser_->OpenSo(); HILOGI(TAG, "[PerformanceTest] saFWK load all libraries finished, spend:%{public}" PRId64 " ms", (GetTickCount() - begin)); return true; } } 
  • CheckSystemAbilityManagerReady

等待samgr服务启动。

bool LocalAbilityManager::CheckSystemAbilityManagerReady() { int32_t timeout = RETRY_TIMES_FOR_saMGR; constexpr int32_t duration = std::chrono::microseconds(MILLISECONDS_WAITING_saMGR_ONE_TIME).count(); sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); while (samgrProxy == nullptr) { HILOGI(TAG, "waiting for samgr..."); if (timeout > 0) { usleep(duration); samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); } else { HILOGE(TAG, "wait for samgr time out (10s)"); return false; } timeout--; } return true; }
  • InitializesaProfiles

初始化sa。如果sa为-1,则对所有sa操作InitializesaProfilesInnerLocked;否则对指定sa操作InitializesaProfilesInnerLocked。

InitializesaProfilesInnerLocked会把sa分到三个不同等级的map中分别启动。

bool LocalAbilityManager::InitializesaProfiles(int32_t saId) { return (saId == DEFAULT_saID) ? InitializeRunOnCreatesaProfiles() : InitializeOnDemandsaProfile(saId); } 

Run

  • 启动线程池

  • FindAndStartPhaseTasks

按照3个优先级启动3个等级的sa。

void LocalAbilityManager::FindAndStartPhaseTasks() { std::shared_lock<std::shared_mutex> readLock(abilityMapLock_); for (uint32_t startType = BOOT_START; startType <= OTHER_START; ++startType) { auto iter = abilityPhaseMap_.find(startType); if (iter != abilityPhaseMap_.end()) { StartPhaseTasks(iter->second); } } } 
  • RegisterOnDemandSystemAbility

如果是在default load模式,那些非创建时运行的sa会注册到samgr。如果在demand load模式,非当前sa都会被注册到samgr。调用samgr的 AddOnDemandSystemAbilityInfo 。

void LocalAbilityManager::RegisterOnDemandSystemAbility(int32_t saId) { auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (samgrProxy == nullptr) { HILOGI(TAG, "failed to get samgrProxy"); return; } auto& saProfileList = profileParser_->GetAllsaProfiles(); for (const auto& saProfile : saProfileList) { if (NeedRegisterOnDemand(saProfile, saId)) { HILOGD(TAG, "register ondemand ability:%{public}d to samgr", saProfile.saId); int32_t ret = samgrProxy->AddOnDemandSystemAbilityInfo(saProfile.saId, procName_); if (ret != ERR_OK) { HILOGI(TAG, "failed to add ability info for on-demand sa:%{public}d", saProfile.saId); } } } } 
  • 等待子线程结束

  • 清理资源

StartSystemAbilityTask

建立对应的sa。如果对应的sa没有依赖,直接调用其Start函数。如果依赖其他sa,则调用samgrProxy->CheckSystemAbility,以保证对应的sa启动。

void LocalAbilityManager::StartSystemAbilityTask(SystemAbility* ability) { if (ability != nullptr) { HILOGD(TAG, "StartSystemAbility is called for %{public}d", ability->GetSystemAbilitId()); if (ability->GetDependsa().empty()) { ability->Start(); } else { int64_t start = GetTickCount(); int64_t dependTimeout = ability->GetDependTimeout(); while (!CheckDependencyStatus(ability->GetDependsa()).empty()) { int64_t end = GetTickCount(); int64_t duration = ((end >= start) ? (end - start) : (INT64_MAX - end + start)); if (duration < dependTimeout) { usleep(CHECK_DEPENDENT_sa_PERIOD); } else { break; } } vector<u16string> unpreparedDeps = CheckDependencyStatus(ability->GetDependsa()); if (unpreparedDeps.empty()) { ability->Start(); } else { for (const auto& unpreparedDep : unpreparedDeps) { HILOGI(TAG, "%{public}d's dependency:%{public}s not started in %{public}d ms", ability->GetSystemAbilitId(), Str16ToStr8(unpreparedDep).c_str(), ability->GetDependTimeout()); } } } } std::lock_guard<std::mutex> lock(startPhaseLock_); if (startTaskNum_ > 0) { --startTaskNum_; } startPhaseCV_.notify_one(); } 
  • AddAbility

查找profile。将profile中的参数赋值给sa对象。

bool LocalAbilityManager::AddAbility(SystemAbility* ability) { if (ability == nullptr) { HILOGW(TAG, "try to add null ability!"); return false; } int32_t saId = ability->GetSystemAbilitId(); saProfile saProfile; bool ret = profileParser_->GetProfile(saId, saProfile); if (!ret) { return false; } std::unique_lock < std::shared_mutex > writeLock(abilityMapLock_); auto iter = abilityMap_.find(saId); if (iter != abilityMap_.end()) { HILOGW(TAG, "try to add existed ability:%{public}d!", saId); return false; } HILOGI(TAG, "set profile attributes for sa:%{public}d", saId); ability->SetLibPath(saProfile.libPath); ability->SetRunOnCreate(saProfile.runOnCreate); ability->SetDependsa(saProfile.dependsa); ability->SetDependTimeout(saProfile.dependTimeout); ability->SetDistributed(saProfile.distributed); ability->SetDumpLevel(saProfile.dumpLevel); ability->SetCapability(saProfile.capability); ability->SetPermission(saProfile.permission); abilityMap_.emplace(saId, ability); return true; }

参考文档

系统服务框架部件

 

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐