README.md
1# safwk<a name="EN-US_TOPIC_0000001115588558"></a>
2
3- [Introduction](#section11660541593)
4- [Directory Structure](#section161941989596)
5- [Usage](#section1312121216216)
6 - [Available APIs](#section1551164914237)
7 - [Usage Guidelines](#section129654513264)
8
9- [Repositories Involved](#section1371113476307)
10
11## Introduction<a name="section11660541593"></a>
12
13The **safwk** module of the Distributed Scheduler subsystem defines how to implement a **SystemAbility** in OpenHarmony and provides APIs for system ability startup and registration.
14
15## Directory Structure<a name="section161941989596"></a>
16
17```
18/foundation/distributedschedule
19│── safwk # Directory for the safwk module
20│ ├── ohos.build # Compilation script for safwk
21│ ├── interfaces # APIs exposed externally
22│ ├── services # Service implementation
23```
24
25## Usage<a name="section1312121216216"></a>
26
27### Available APIs<a name="section1551164914237"></a>
28
29<a name="table775715438253"></a>
30<table><thead align="left"><tr id="row12757154342519"><th class="cellrowborder" valign="top" width="43.19%" id="mcps1.1.3.1.1"><p id="p1075794372512"><a name="p1075794372512"></a><a name="p1075794372512"></a>API</p>
31</th>
32<th class="cellrowborder" valign="top" width="56.81%" id="mcps1.1.3.1.2"><p id="p375844342518"><a name="p375844342518"></a><a name="p375844342518"></a>Description</p>
33</th>
34</tr>
35</thead>
36<tbody><tr id="row1975804332517"><td class="cellrowborder" valign="top" width="43.19%" headers="mcps1.1.3.1.1 "><p id="p5758174313255"><a name="p5758174313255"></a><a name="p5758174313255"></a>sptr<IRemoteObject> GetSystemAbility(int32_t systemAbilityId);</p>
37</td>
38<td class="cellrowborder" valign="top" width="56.81%" headers="mcps1.1.3.1.2 "><p id="p14758743192519"><a name="p14758743192519"></a><a name="p14758743192519"></a>Obtains the remote procedure call (RPC) object of a specified system ability.</p>
39</td>
40</tr>
41<tr id="row2758943102514"><td class="cellrowborder" valign="top" width="43.19%" headers="mcps1.1.3.1.1 "><p id="p107581438250"><a name="p107581438250"></a><a name="p107581438250"></a>bool Publish(sptr<IRemoteObject> systemAbility);</p>
42</td>
43<td class="cellrowborder" valign="top" width="56.81%" headers="mcps1.1.3.1.2 "><p id="p8758743202512"><a name="p8758743202512"></a><a name="p8758743202512"></a>Publishes a specified system ability.</p>
44</td>
45</tr>
46<tr id="row09311240175710"><td class="cellrowborder" valign="top" width="43.19%" headers="mcps1.1.3.1.1 "><p id="p159328405571"><a name="p159328405571"></a><a name="p159328405571"></a>virtual void DoStartSAProcess(const std::string& profilePath) = 0;</p>
47</td>
48<td class="cellrowborder" valign="top" width="56.81%" headers="mcps1.1.3.1.2 "><p id="p493294018574"><a name="p493294018574"></a><a name="p493294018574"></a>Enables a system ability based on the SA profile information.</p>
49</td>
50</tr>
51<tr id="row159634125718"><td class="cellrowborder" valign="top" width="43.19%" headers="mcps1.1.3.1.1 "><p id="p10596134105710"><a name="p10596134105710"></a><a name="p10596134105710"></a>void OnConnectedSystemAbility(const sptr<IRemoteObject>& connectionCallback);</p>
52</td>
53<td class="cellrowborder" valign="top" width="56.81%" headers="mcps1.1.3.1.2 "><p id="p105961241125713"><a name="p105961241125713"></a><a name="p105961241125713"></a>Called when a system ability is connected.</p>
54</td>
55</tr>
56<tr id="row611715428577"><td class="cellrowborder" valign="top" width="43.19%" headers="mcps1.1.3.1.1 "><p id="p10118242155716"><a name="p10118242155716"></a><a name="p10118242155716"></a>void OnDisConnectedSystemAbility(int32_t systemAbilityId);</p>
57</td>
58<td class="cellrowborder" valign="top" width="56.81%" headers="mcps1.1.3.1.2 "><p id="p81189429578"><a name="p81189429578"></a><a name="p81189429578"></a>Called when a system ability is disconnected.</p>
59</td>
60</tr>
61</tbody>
62</table>
63
64### Usage Guidelines<a name="section129654513264"></a>
65
66System abilities can be implemented in both C++ and Java languages. In C++, you must define the _XXX_**.rc**, **profile.xml**, and **lib**_XXX_**.z.so** files to declare the system ability, and the init process executes the specified _XXX_**.rc** file to start the process of the particular system ability. Similar to the implementation in C++, the system ability process is started by [the foundationserver module](en-us_topic_0000001078878484.md) in Java.
67
68**Implementing a System Ability in C++**
69
70- **Define the _IXXX_ class for IPC.**
71
72This _IXXX_ class is used to define the functions for the system ability to provide specific capabilities. To define this class, implement the **IRemoteBroker** interface provided by OpenHarmony for inter-process communication \(IPC\). In addition, implement the **DECLARE\_INTERFACE\_DESCRIPTOR\(_XXX_\)** that uniquely identifies this class. The identifier is used for purposes such as IPC communication verification.
73
74The following example shows how to define the **IListenAbility** class for testing in the Distributed Scheduler subsystem:
75
76```
77namespace OHOS {
78class IListenAbility : public IRemoteBroker {
79public:
80 virtual int AddVolume(int volume) = 0;
81
82public:
83 enum {
84 ADD_VOLUME = 1,
85 };
86public:
87 DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.test.IListenAbility");
88};
89}
90```
91
92- **Define the _XXX_Proxy class for client communication.**
93
94```
95namespace OHOS {
96class ListenAbilityProxy : public IRemoteProxy<IListenAbility> {
97public:
98 int AddVolume(int volume);
99
100 explicit ListenAbilityProxy(const sptr<IRemoteObject>& impl)
101 : IRemoteProxy<IListenAbility>(impl)
102 {
103 }
104
105private:
106 static inline BrokerDelegator<ListenAbilityProxy> delegator_;
107};
108} // namespace OHOS
109```
110
111- **Define the _XXX_Stub class for server communication.**
112
113```
114namespace OHOS {
115int32_t ListenAbilityStub::OnRemoteRequest(uint32_t code,
116 MessageParcel& data, MessageParcel &reply, MessageOption &option)
117{
118 switch (code) {
119 case ADD_VOLUME: {
120 return reply.WriteInt32(AddVolume(data.ReadInt32()));
121 }
122
123 default:
124 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
125 }
126}
127}
128```
129
130- **Implement a system ability.**
131
132```
133namespace {
134constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001800, "SA_TST"};
135}
136
137REGISTER_SYSTEM_ABILITY_BY_ID(ListenAbility, DISTRIBUTED_SCHED_TEST_LISTEN_ID, true);
138
139ListenAbility::ListenAbility(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate)
140{
141 HiLog::Info(LABEL, ":%s called", __func__);
142 HiLog::Info(LABEL, "ListenAbility()");
143}
144
145ListenAbility::~ListenAbility()
146{
147 HiLog::Info(LABEL, "~ListenAbility()");
148}
149
150int ListenAbility::AddVolume(int volume)
151{
152 pid_t current = getpid();
153 HiLog::Info(LABEL, "ListenAbility::AddVolume volume = %d, pid = %d.", volume, current);
154 return (volume + 1);
155}
156
157void ListenAbility::OnDump()
158{
159}
160
161void ListenAbility::OnStart()
162{
163 HiLog::Info(LABEL, "ListenAbility::OnStart()");
164 HiLog::Info(LABEL, "ListenAbility:%s called:-----Publish------", __func__);
165 bool res = Publish(this);
166 if (res) {
167 HiLog::Error(LABEL, "ListenAbility: res == false");
168 }
169 HiLog::Info(LABEL, "ListenAbility:%s called:AddAbilityListener_OS_TST----beg-----", __func__);
170 AddSystemAbilityListener(DISTRIBUTED_SCHED_TEST_OS_ID);
171 HiLog::Info(LABEL, "ListenAbility:%s called:AddAbilityListener_OS_TST----end-----", __func__);
172
173 HiLog::Info(LABEL, "ListenAbility:%s called:StopAbility_OS_TST----beg-----", __func__);
174 StopAbility(DISTRIBUTED_SCHED_TEST_OS_ID);
175 HiLog::Info(LABEL, "ListenAbility:%s called:StopAbility_OS_TST----end-----", __func__);
176 return;
177}
178
179void ListenAbility::OnStop()
180{
181}
182```
183
184- **Configure the system ability.**
185
186If the system ability is implemented in C++, you must define a profile for it so that it can be loaded and registered. The configuration procedure is as follows:
187
188Create a folder named **sa\_profile** in the root directory of the subsystem. Then, create two files in this folder, including an XML file prefixed with the service ID of the system ability and a **BUILD.gn** file.
189
190Sample _serviceid_**.xml** file:
191
192```
193<?xml version="1.0" encoding="UTF-8"?>
194<info>
195 <process>listen_test</process>
196 <systemability>
197 <name>serviceid</name>
198 <libpath>/system/lib64/liblistentest.z.so</libpath>
199 <run-on-create>true</run-on-create>
200 <distributed>false</distributed>
201 <dump-level>1</dump-level>
202</systemability>
203</info>
204```
205
206Sample **BUILD.gn** file:
207
208```
209import("//build/ohos/sa_profile/sa_profile.gni")
210ohos_sa_profile("xxx_sa_profile") {
211 sources = [
212 "serviceid.xml"
213 ]
214 subsystem_name = "distributedschedule"
215}
216```
217
218>**NOTE:**
219>1. Set the **process** tag to the name of the process where the system ability will run. This tag is mandatory.
220>2. Add only one **systemability** node in the profile of a system ability. If multiple **systemability** nodes are added, the building fails.
221>3. Set the **name** tag to the service ID registered in the code for the system ability. This tag is mandatory.
222>4. Set the **libpath** tag to the path for loading the system ability. This tag is mandatory.
223>5. Set the **run-on-create** tag to **true** if you want to register this system ability with the **samgr** module immediately after the process is started. Set this tag to **false** if you want the system ability to start only when other modules access the system ability. This tag is mandatory.
224>6. Set the **distributed** tag to **true** if this system ability allows cross-device access; set it to **false** if it allows IPC only on the local device.
225>7. Set the **def-permission** tag to define the permissions, if any, required for the process on another device to access this system ability during cross-device RPC communication when **distributed** is set to **true**. This tag is optional.
226>8. Set the **bootphase** tag to define the startup priority of the system ability, which \(from high to low\) can be **BootStartPhase**, **CoreStartPhase**, or **OtherStartPhase** \(default value\). In the same process, the system ability of the **BootStartPhase** priority will be started first, then that of the **CoreStartPhase** priority, and finally the **OtherStartPhase** priority. System abilities of a lower priority can be started and registered only after those of a high priority have all been started and registered. This tag is optional.
227>9. Set **dump-level** to **1**, which indicates that the level is supported by the system dumper.
228>10. In the **BUILD.gn** file, set **subsystem\_name** to the name of the corresponding subsystem, and add the list of system abilities that need to be configured for the specified subsystem in **sources**. Multiple system abilities can be configured.
229
230After the preceding files are configured and full code building is complete, a **listen\_test.xml** prefixed with the process name will be generated in the **out** directory. The path is **out\\phone-release\\system\\profile\\listen\_test.xml** in this example.
231
232- **Configure the _XXX_.rc file.**
233
234The **_XXX_.rc** configuration file defines the native process startup policy provided by Linux. The **init** process parses the configured **_XXX_.rc** file during device startup.
235
236```
237service listen_test /system/bin/sa_main /system/profile/listen_test.xml
238 class z_core
239 user system
240 group system shell
241 seclabel u:r:xxxx:s0
242```
243
244>**NOTE:**
245>For details about the implementation of **listen\_ability**, see the code in **test/unittest/common/listen\_ability**.
246
247## Repositories Involved<a name="section1371113476307"></a>
248
249[Distributed Scheduler subsystem](en-us_topic_0000001115719369.md)
250
251[dmsadapter](en-us_topic_0000001124134145.md)
252
253[dmsfwk](en-us_topic_0000001078718754.md)
254
255[foundationserver](en-us_topic_0000001078878484.md)
256
257**[safwk](safwk.md)**
258
259[samgr](en-us_topic_0000001124076649.md)
260
261
README_zh.md
1# safwk组件<a name="ZH-CN_TOPIC_0000001115588558"></a>
2## 简介<a name="section11660541593"></a>
3
4在系统服务管理子系统中safwk组件定义OpenHarmony中SystemAbility的实现方法,并提供启动、注册等接口实现。
5
6## 目录<a name="section161941989596"></a>
7
8```
9/foundation/distributedschedule
10│── safwk # 组件目录
11│ ├── bundle.json # 组件描述及编译脚本
12│ ├── etc # 配置文件
13│ ├── interfaces # 对外接口目录
14│ ├── services # 组件服务实现
15│ ├── test # 测试用例
16```
17
18## 说明<a name="section1312121216216"></a>
19
20### 接口说明<a name="section1551164914237"></a>
21
22<a name="table775715438253"></a>
23<table><thead align="left"><tr id="row12757154342519"><th class="cellrowborder" valign="top" width="43.19%" id="mcps1.1.3.1.1"><p id="p1075794372512"><a name="p1075794372512"></a><a name="p1075794372512"></a>接口名</p>
24</th>
25<th class="cellrowborder" valign="top" width="56.81%" id="mcps1.1.3.1.2"><p id="p375844342518"><a name="p375844342518"></a><a name="p375844342518"></a>接口描述</p>
26</th>
27</tr>
28</thead>
29<tbody><tr id="row1975804332517"><td class="cellrowborder" valign="top" width="43.19%" headers="mcps1.1.3.1.1 "><p id="p5758174313255"><a name="p5758174313255"></a><a name="p5758174313255"></a>sptr<IRemoteObject> GetSystemAbility(int32_t systemAbilityId);</p>
30</td>
31<td class="cellrowborder" valign="top" width="56.81%" headers="mcps1.1.3.1.2 "><p id="p14758743192519"><a name="p14758743192519"></a><a name="p14758743192519"></a>获取指定系统服务的RPC对象。</p>
32</td>
33</tr>
34<tr id="row2758943102514"><td class="cellrowborder" valign="top" width="43.19%" headers="mcps1.1.3.1.1 "><p id="p107581438250"><a name="p107581438250"></a><a name="p107581438250"></a>bool Publish(sptr<IRemoteObject> systemAbility);</p>
35</td>
36<td class="cellrowborder" valign="top" width="56.81%" headers="mcps1.1.3.1.2 "><p id="p8758743202512"><a name="p8758743202512"></a><a name="p8758743202512"></a>发布系统服务。</p>
37</td>
38</tr>
39<tr id="row09311240175710"><td class="cellrowborder" valign="top" width="43.19%" headers="mcps1.1.3.1.1 "><p id="p159328405571"><a name="p159328405571"></a><a name="p159328405571"></a>virtual void DoStartSAProcess(const std::string& profilePath) = 0;</p>
40</td>
41<td class="cellrowborder" valign="top" width="56.81%" headers="mcps1.1.3.1.2 "><p id="p493294018574"><a name="p493294018574"></a><a name="p493294018574"></a>根据SA profile配置启动System Ability。</p>
42</td>
43</tr>
44</tbody>
45</table>
46
47### 使用说明<a name="section129654513264"></a>
48
49SystemAbility实现一般采用XXX.cfg + profile.xml + libXXX.z.so的方式由init进程执行对应的XXX.cfg文件拉起相关SystemAbility进程。
50
51**C++实现SystemAbility**
52
53示例代码如下:
54
55- **1. 定义IPC对外接口IXXX**
56
57定义该服务对外提供的能力集合函数,统一继承IPC接口类IRemoteBroker;同时实现该IPC对外接口唯一标识符DECLARE\_INTERFACE\_DESCRIPTOR\(XXX\);该标识符用于IPC通信的校验等目的。
58
59```
60namespace OHOS {
61class IListenAbility : public IRemoteBroker {
62public:
63 virtual int AddVolume(int volume) = 0;
64
65public:
66 enum {
67 ADD_VOLUME = 1,
68 };
69public:
70 DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.test.IListenAbility");
71};
72}
73```
74
75- **2. 定义客户端通信代码XXXProxy**
76
77```
78namespace OHOS {
79class ListenAbilityProxy : public IRemoteProxy<IListenAbility> {
80public:
81 int AddVolume(int volume);
82
83 explicit ListenAbilityProxy(const sptr<IRemoteObject>& impl)
84 : IRemoteProxy<IListenAbility>(impl)
85 {
86 }
87
88private:
89 static inline BrokerDelegator<ListenAbilityProxy> delegator_;
90};
91} // namespace OHOS
92```
93
94- **3. 定义服务端通信代码XXXStub**
95
96```
97namespace OHOS {
98int32_t ListenAbilityStub::OnRemoteRequest(uint32_t code,
99 MessageParcel& data, MessageParcel &reply, MessageOption &option)
100{
101 switch (code) {
102 case ADD_VOLUME: {
103 return reply.WriteInt32(AddVolume(data.ReadInt32()));
104 }
105
106 default:
107 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
108 }
109}
110}
111```
112
113- **4. SystemAbility的实现类**
114
115```
116namespace {
117constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001800, "SA_TST"};
118}
119
120REGISTER_SYSTEM_ABILITY_BY_ID(ListenAbility, DISTRIBUTED_SCHED_TEST_LISTEN_ID, true);
121
122ListenAbility::ListenAbility(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate)
123{
124 HiLog::Info(LABEL, ":%s called", __func__);
125 HiLog::Info(LABEL, "ListenAbility()");
126}
127
128ListenAbility::~ListenAbility()
129{
130 HiLog::Info(LABEL, "~ListenAbility()");
131}
132
133int ListenAbility::AddVolume(int volume)
134{
135 pid_t current = getpid();
136 HiLog::Info(LABEL, "ListenAbility::AddVolume volume = %d, pid = %d.", volume, current);
137 return (volume + 1);
138}
139
140void ListenAbility::OnDump()
141{
142}
143
144void ListenAbility::OnStart()
145{
146 HiLog::Info(LABEL, "ListenAbility::OnStart()");
147 HiLog::Info(LABEL, "ListenAbility:%s called:-----Publish------", __func__);
148 bool res = Publish(this);
149 if (res) {
150 HiLog::Error(LABEL, "ListenAbility: res == false");
151 }
152 HiLog::Info(LABEL, "ListenAbility:%s called:AddAbilityListener_OS_TST----beg-----", __func__);
153 AddSystemAbilityListener(DISTRIBUTED_SCHED_TEST_OS_ID);
154 HiLog::Info(LABEL, "ListenAbility:%s called:AddAbilityListener_OS_TST----end-----", __func__);
155
156 HiLog::Info(LABEL, "ListenAbility:%s called:StopAbility_OS_TST----beg-----", __func__);
157 StopAbility(DISTRIBUTED_SCHED_TEST_OS_ID);
158 HiLog::Info(LABEL, "ListenAbility:%s called:StopAbility_OS_TST----end-----", __func__);
159 return;
160}
161
162void ListenAbility::OnStop()
163{
164}
165```
166
167- **5. SystemAbility配置**
168
169以c++实现的SA必须配置相关System Ability的profile配置文件才会完成SA的加载注册逻辑,否则没有编写profile配置的System Ability不会完成注册。配置方法如下:
170
171在子系统的根目录新建一个以sa\_profile为名的文件夹,然后在此文件夹中新建两个文件:一个以serviceId为前缀的xml文件,另外一个为BUILD.gn文件。
172
173serviceid.xml:
174
175```
176<?xml version="1.0" encoding="UTF-8"?>
177<info>
178 <process>listen_test</process>
179 <systemability>
180 <name>serviceid</name>
181 <libpath>/system/lib64/liblistentest.z.so</libpath>
182 <run-on-create>true</run-on-create>
183 <distributed>false</distributed>
184 <dump-level>1</dump-level>
185</systemability>
186</info>
187```
188
189BUILD.gn:
190
191```
192import("//build/ohos/sa_profile/sa_profile.gni")
193ohos_sa_profile("xxx_sa_profile") {
194 sources = [
195 "serviceid.xml"
196 ]
197 subsystem_name = "distributedschedule"
198}
199```
200
201>**说明:**
202>1. 进程名字即该SystemAbility要运行的进程空间,此字段是必填选项。
203>2. 一个SystemAbility配置文件只能配置一个SystemAbility节点,配置多个会导致编译失败。
204>3. SystemAbility的name为对应的serviceId必须与代码中注册的serviceId保持一致,必配项。
205>4. libpath为SystemAbility的加载路径,必配项。
206>5. run-on-create:true表示进程启动后即向samgr组件注册该SystemAbility;false表示按需启动,即在其他模块访问到该SystemAbility时启动,必配项。
207>6. distributed:true表示该SystemAbility为分布式SystemAbility,支持跨设备访问;false表示只有本地跨IPC访问。
208>7. bootphase:可不设置;可以设置的值有三种:BootStartPhase、CoreStartPhase、OtherStartPhase(默认类型),三种优先级依次降低,当同一个进程中,会优先拉起注册配置BootStartPhase的SystemAbility,然后是配置了CoreStartPhase的SystemAbility,最后是OtherStartPhase;当高优先级的SystemAbility全部启动注册完毕才会启动下一级的SystemAbility的注册启动。
209>8. dump-level:表示systemdumper支持的level等级,默认配置1。
210>9. BUILD.gn中subsystem\_name为相应部件名称;sources表示当前子系统需要配置的SystemAbility列表,可支持配置多个SystemAbility。
211
212以上步骤完成后,全量编译代码后会在out路径向生成一个以进程名为前缀的xml文件listen\_test.xml;路径为:out\\...\\system\\profile\\listen\_test.xml。
213
214- **6. cfg配置文件**
215
216cfg配置文件为linux提供的native进程拉起策略,开机启动阶段由init进程解析配置的cfg文件进行拉起。
217
218```
219{
220 "jobs" : [{
221 "name" : "post-fs-data",
222 "cmds" : [
223 "start listen_test"
224 ]
225 }
226 ],
227 "services" : [{
228 "name" : "listen_test",
229 "path" : ["/system/bin/sa_main", "/system/profile/listen_test.xml"],
230 "uid" : "system",
231 "gid" : ["system", "shell"]
232 }
233 ]
234}
235```
236
237>**说明:**
238>listen\_ability的实现可以参考:test/services/safwk/unittest/common/listen\_ability。
239
240## 相关仓<a name="section1371113476307"></a>
241
242系统服务管理子系统
243
244[**distributedschedule\_safwk**](https://gitee.com/openharmony/distributedschedule_safwk)
245
246[distributedschedule\_samgr](https://gitee.com/openharmony/distributedschedule_samgr)
247
248[distributedschedule\_safwk\_lite](https://gitee.com/openharmony/distributedschedule_safwk_lite)
249
250[distributedschedule\_samgr\_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite)