419
社区成员




safwk组件隶属于系统服务管理子系统,该子系统提供系统服务的启动、注册、查询等功能,提供查询跨设备的分布式系统服务。在系统服务管理子系统中,safwk组件定义了OpenHarmony中SystemAbility的实现方法,并提供启动、注册等接口实现。
系统服务框架图如下:
/foundation/systemabilitymgr
│── safwk # 组件目录
│ ├── bundle.json # 组件描述及编译脚本
│ ├── etc # 配置文件
│ ├── interfaces # 对外接口目录
│ ├── services # 组件服务实现
│ ├── test # 测试用例
接口名 | 接口描述 |
---|---|
sptr GetSystemAbility(int32_t systemAbilityId); | 获取指定系统服务的RPC对象。 |
bool Publish(sptr 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的实现代码如下:
定义该服务对外提供的能力集合函数,统一继承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");
};
}
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
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);
}
}
}
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()
{
}
以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>
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发指令)。
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;
}
Stub类,用于和samgr通信,samgr会通过向本类发送拉起ondemand sa指令实现按需拉起。
local_ability_manager_stub.cpp文件路径为:foundation\systemabilitymgr\safwk\services\safwk\src\local_ability_manager_stub.cpp。
sa对象的基类,定义了一些通用接口。
system_ability.cpp的文件路径为:\foundation\systemabilitymgr\safwk\services\safwk\src\system_ability.cpp。
将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));
.....
}
将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;
}
启动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));
}
停止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");
}
本地Ability管理类,继承了LocalAbilityManagerStub。容器程序的大部分逻辑都在本类实现。
local_ability_manager.cpp的文件路径为:\foundation\systemabilitymgr\safwk\services\safwk\src\local_ability_manager.cpp。
检查profile xml路径合法性。(必须在/system/profile/或/system/usr/)
解析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;
}
}
等待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;
}
初始化sa。如果sa为-1,则对所有sa操作InitializesaProfilesInnerLocked;否则对指定sa操作InitializesaProfilesInnerLocked。
InitializesaProfilesInnerLocked会把sa分到三个不同等级的map中分别启动。
bool LocalAbilityManager::InitializesaProfiles(int32_t saId)
{
return (saId == DEFAULT_saID) ? InitializeRunOnCreatesaProfiles() : InitializeOnDemandsaProfile(saId);
}
按照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);
}
}
}
如果是在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);
}
}
}
}
建立对应的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();
}
查找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;
}