openharmony的SA介绍与编写--开鸿智谷
1 SA简述 SA的全称是system ability,类似于安卓里的service,是一些运行在单独进程的里的服务,可以选择开机运行或者不运行。同一个进程可以运行多个SA,这里介绍的SA仅适用于富设备。 2 IPC模型 SA作为运行在单独进程里的服务,其接口只能基于跨进程通讯方法进行调用(IPC),可以通过提供proxy接口让别的进程快速调用SA的接口,IPC通讯过程中的数据通过序列化接口读写。
1 SA简述
SA的全称是system ability,类似于安卓里的service,是一些运行在单独进程的里的服务,可以选择开机运行或者不运行。同一个进程可以运行多个SA,这里介绍的SA仅适用于富设备。
2 IPC模型
SA作为运行在单独进程里的服务,其接口只能基于跨进程通讯方法进行调用(IPC),可以通过提供proxy接口让别的进程快速调用SA的接口,IPC通讯过程中的数据通过序列化接口读写。
2.1 编写interface.h(ifree_sa_test.h)
#include "iremote_broker.h"
class IFreeSaTest : public OHOS::IRemoteBroker {
public:
DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.FreeSaTest.FreeSaTestService");
virtual std::string GetName() = 0;
virtual int32_t SetBalance(int32_t balance) = 0;
virtual int32_t GetBalance() = 0;
enum SA_FUN_CODE {
GET_NAME,
SET_BALANCE,
GET_BALANCE
};
};
DECLARE_INTERFACE_DESCRIPTOR只是用于申明descripor的宏,拿来用就行用就行了
#define DECLARE_INTERFACE_DESCRIPTOR(DESCRIPTOR) \
static constexpr const char16_t *metaDescriptor_ = DESCRIPTOR; \
static inline const std::u16string GetDescriptor() \
{ \
return metaDescriptor_; \
}
2.2 编写stub
stub.h
#include "ifree_sa_test.h"
#include "iremote_stub.h"
class IFreeSaTestStub : public IRemoteStub<IFreeSaTest> {
public:
// 响应客户端请求的入口函数
int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply,
MessageOption &option) override;
};
stub.cpp
#include "free_sa_test_stub.h"
int32_t IFreeSaTestStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
auto retvalue = 0;
// 实现的接口多的话可以用map绑定funCode与对应的处理函数,而不用switch
switch(code)
{
case GET_NAME: {
std::string name = GetName();
// 通过序列化的方法把数据写到共享内存
reply.WriteString(name);
}
break;
。。。
retvalue = IPCObjectStub::OnRemoteRequest(code, data, reply, option);
break;
}
return retvalue ;
}
2.3 编写service
service.h
#include "ipc_skeleton.h"
#include "system_ability.h"
#include "free_sa_test_stub.h"
// service会继承stub,所以stub不是必须的。stub只是把响应(OnRemoteRequest)这个动作独立出来,增加了可读性,建议还是都这么做。
class FreeSaTestService : public SystemAbility, public IFreeSaTestStub {
// 提供查询类名的接口
DECLARE_SYSTEM_ABILITY(FreeSaTestService);
// 删除拷贝构造和移动构造
DISALLOW_COPY_AND_MOVE(FreeSaTestService);
explicit FreeSaTestService(int32_t systemAbilityId, bool runOnCreate = true);
~FreeSaTestService() override;
private:
std::string GetName() override;
int32_t SetBalance(int32_t balance) override;
int32_t GetBalance() override;
// service的基本实现
void OnStart() override;
void OnStop() override;
int32_t m_balance;
};
service.cpp
#include "free_sa_test_service.h"
#include "system_ability_definition.h"
// 这一步是sa注册的宏
// FREE_SA_TEST_SERVICE_1是said,需要将saId和sa_name定义在foundation/systemabilitymgr/samgr/interfaces/innerkits/samgr_proxy/include/system_ability_definition.h里
REGISTER_SYSTEM_ABILITY_BY_ID(FreeSaTestService, FREE_SA_TEST_SERVICE_1, true);
FreeSaTestService::FreeSaTestService(int32_t systemAbilityId, bool runOnCreate)
:SystemAbility(systemAbilityId, runOnCreate), m_balance(0)
{
HILOGI("Create FreeSaTestService SaId = %{public}d", systemAbilityId);
}
FreeSaTestService::~FreeSaTestService()
{
}
// 自己的功能
std::string FreeSaTestService::GetName()
{
return "FreeSaTestService1";
}
void FreeSaTestService::OnStart()
{
bool res = Publish(this);
if (!res) {
HILOGE("Publish said = %{public}d failed", FREE_SA_TEST_SERVICE_1);
}
return;
}
void FreeSaTestService::OnStop()
{
}
。。。。。
gn
external_deps = [
"c_utils:utils",
"ipc:ipc_core",
"samgr:samgr_proxy",
"safwk:system_ability_fwk"
]
2.4 SA配置文件json
进程名字即该SystemAbility要运行的进程空间,此字段是必填选项。
一个SystemAbility配置文件只能配置一个SystemAbility节点,配置多个会导致编译失败。
SystemAbility的name为对应的serviceId必须与代码中注册的serviceId保持一致,必配项。
libpath为SystemAbility的加载路径,必配项。
run-on-create:true表示进程启动后即向samgr组件注册该SystemAbility;false表示按需启动,即在其他模块访问到该SystemAbility时启动,必配项。
distributed:true表示该SystemAbility为分布式SystemAbility,支持跨设备访问;false表示只有本地跨IPC访问。
bootphase:可不设置;可以设置的值有三种:BootStartPhase、CoreStartPhase、OtherStartPhase(默认类型),三种优先级依次降低,当同一个进程中,会优先拉起注册配置BootStartPhase的SystemAbility,然后是配置了CoreStartPhase的SystemAbility,最后是OtherStartPhase;当高优先级的SystemAbility全部启动注册完毕才会启动下一级的SystemAbility的注册启动。
dump-level:表示systemdumper支持的level等级,默认配置1。
BUILD.gn中subsystem_name为相应部件名称;sources表示当前子系统需要配置的SystemAbility列表,可支持配置多个SystemAbility。
{
"process": "free_sa_test_service",
"systemability": [
{
"name": 9600,
"libpath": "libfree_sa_test_service.z.so",
"run-on-create": true,
"distributed": false,
"dump_level": 1,
}
]
}
json的编译gn
import("//build/ohos/sa_profile/sa_profile.gni")
ohos_sa_profile("xxx_sa_profile") {
sources = [
"serviceid.json"
]
subsystem_name = "systemabilitymgr"
}
2.5 进程配置文件cfg
当前服务的cfg例子:
1.name是进程名
2.path是json
3.uid和gid都是需要指定的。对应的配置文件是base/startup/init/service/etc/group和base/startup/init/service/etc/passwd
4.ondemand,表示是否开机拉起该进程
5.secon,是selinux标签,如果所用标签未定义或者权限不足,进程都无法拉起。如果关闭了selinux,则需要在cfg里删除该字段。
{
"services" : [{
"name" : "free_sa_test_service",
"path" : ["/system/bin/sa_main", "/data/dynamic_sa/9600/free_sa_test_service.json"],
"uid" : "OpenValleyDynamicSa",
"gid" : ["OpenValleyDynamicSa", "shell"],
"ondemand" : false,
"apl" : "system_basic",
"secon" : "u:r:openvalley_dynamic_sa:s0"
}
]
}
gn
import("//build/ohos.gni")
ohos_prebuilt_etc("名称_init") {
source = "xx.cfg"
relative_install_dir = "init"
part_name = 模块名
subsystem_name = 子系统名
}
2.6 proxy
直至2.5,service已经可以起来了 。proxy是提供一些接口给使用者,让使用者可以方便地调用该服务的接口
proxy.h
#include "iremote_proxy.h"
#include "ifree_sa_test.h"
class FreeSaTestProxy : public IRemoteProxy<IFreeSaTest> {
public:
explicit FreeSaTestProxy (const sptr<IRemoteObject>& impl)
: IRemoteProxy<IFreeSaTest>(impl) {}
virtual std::string GetName();
virtual int32_t SetBalance(int32_t balance);
virtual int32_t GetBalance();
// 如果想使用iface_cast转化得到该proxy,则必须初始化这个代理变量,将这个proxy类型注册到BrokerRegistration
static inline BrokerDelegator<FreeSaTestProxy > delegator_;
}
proxy.cpp
#include "free_sa_test_proxy.h"
std::string FreeSaTestProxy::GetName()
{
sptr<IRemoteObject> remote = Remote();
MessageParcel data;
MessageParcel reply;
MessageOption option;
int32_t err= remote->SendRequest(GET_NAME, data, reply, option);
if (err != ERR_NONE) {
HILOGE("InstallDynamicSystemAbility SendRequest error: %{public}d!", err);
return err;
}
auto str = reply.ReadString();
return str;
}
。。。。
gn
external_deps = [
"c_utils:utils",
"ipc:ipc_core",
"samgr:samgr_proxy",
]
2.7 使用
然后在任意地方使用即可
auto systemManager =
SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
auto object = systemManager->GetSystemAbility(FREE_SA_TEST_SERVICE_1);
if (object == nullptr) {
HILOGE("Get service %{public}d failed", FREE_SA_TEST_SERVICE_1);
return nullptr;
}
Proxy_ = iface_cast<ISystemAbilityLoader>(object);
if (Proxy_ == nullptr) {
HILOGE("iface_cast to proxy failed");
return nullptr;
}
更多推荐
所有评论(0)