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