OpenHarmony系统服务框架部件介绍

鸿蒙小绿娃 2023-03-13 16:04:00

前言

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

系统服务框架图如下:

img

文件结构

/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的实现代码如下:

  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;
}

参考文档

系统服务框架部件

...全文
1755 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

419

社区成员

发帖
与我相关
我的任务
社区描述
OpenHarmony开发者社区
其他 企业社区
社区管理员
  • csdnsqst0025
  • shewaliujingli
  • BaoWei
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧