鴻蒙開發實戰:【系統服務框架部件】

烧脑猴發表於2024-04-23

簡介

在系統服務管理子系統中safwk元件定義OpenHarmony中SystemAbility的實現方法,並提供啟動、註冊等介面實現。

系統架構

圖 1 系統服務框架圖

image

說明

介面說明

介面名 介面描述
sptr GetSystemAbility(int32_t systemAbilityId); 獲取指定系統服務的RPC物件。
bool Publish(sptr systemAbility); 釋出系統服務。
virtual void DoStartSAProcess(const std::string& profilePath) = 0; 根據SA profile配置啟動System Ability。

使用說明

SystemAbility實現一般採用XXX.cfg + profile.json + libXXX.z.so的方式由init程序執行對應的XXX.cfg檔案拉起相關SystemAbility程序。

C++實現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");
};
}
  • 2. 定義客戶端通訊程式碼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
  • 3. 定義服務端通訊程式碼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);
    }
}
}
  • 4. SystemAbility的實現類
namespace {
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()
{
}
  • 5. SystemAbility配置

以c++實現的SA必須配置相關System Ability的profile配置檔案才會完成SA的載入註冊邏輯,否則沒有編寫profile配置的System Ability不會完成註冊。配置方法如下:

在子系統的根目錄新建一個以sa_profile為名的資料夾,然後在此資料夾中新建兩個檔案:一個以serviceId為字首的json檔案,另外一個為BUILD.gn檔案。

serviceid.json:

{
    "process": "listen_test",
    "systemability": [
        {
            "name": serviceid,
            "libpath": "liblisten_test.z.so",
            "run-on-create": true,
            "distributed": true,
            "dump_level": 1
        }
    ]
}

BUILD.gn:

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

說明:

  1. 程序名字即該SystemAbility要執行的程序空間,此欄位是必填選項。
  2. 一個SystemAbility配置檔案只能配置一個SystemAbility節點,配置多個會導致編譯失敗。
  3. SystemAbility的name為對應的serviceId必須與程式碼中註冊的serviceId保持一致,必配項。
  4. libpath為SystemAbility的載入路徑,必配項。
  5. run-on-create:true表示程序啟動後即向samgr元件註冊該SystemAbility;false表示按需啟動,即在其他模組訪問到該SystemAbility時啟動,必配項。
  6. distributed:true表示該SystemAbility為分散式SystemAbility,支援跨裝置訪問;false表示只有本地跨IPC訪問。
  7. bootphase:可不設定;可以設定的值有三種:BootStartPhase、CoreStartPhase、OtherStartPhase(預設型別),三種優先順序依次降低,當同一個程序中,會優先拉起註冊配置BootStartPhase的SystemAbility,然後是配置了CoreStartPhase的SystemAbility,最後是OtherStartPhase;當高優先順序的SystemAbility全部啟動註冊完畢才會啟動下一級的SystemAbility的註冊啟動。
  8. dump-level:表示systemdumper支援的level等級,預設配置1。
  9. BUILD.gn中subsystem_name為相應部件名稱;sources表示當前子系統需要配置的SystemAbility列表,可支援配置多個SystemAbility。

以上步驟完成後,全量編譯程式碼後會在out路徑向生成一個以程序名為字首的json檔案listen_test.json;路徑為:out...\system\profile\listen_test.json。

更多鴻蒙開發知識已更新qr23.cn/AKFP8k可前往參考學習。

image

  • 6. cfg配置檔案

cfg配置檔案為linux提供的native程序拉起策略,開機啟動階段由init程序解析配置的cfg檔案進行拉起。

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

相關文章