1# IDL Specifications and User Guide (for System Applications Only) 2 3## IDL Overview 4To ensure successful communications between the client and server, interfaces recognized by both parties must be defined. The OpenHarmony Interface Definition Language (IDL) is a tool for defining such interfaces. IDL decomposes objects into primitives that can be understood by the operating system and encapsulates cross-boundary objects based on your requirements. 5 6**Figure 1** IDL interface description 7 8 9 10**IDL provides the following functions:** 11 12- Declares interfaces provided by system services for external systems, and based on the interface declaration, generates C, C++, JS, or TS code for inter-process communication (IPC) or remote procedure call (RPC) proxies and stubs during compilation. 13 14- Declares interfaces provided by abilities for external systems, and based on the interface declaration, generates C, C++, JS, or TS code for IPC or RPC proxies and stubs during compilation. 15 16**Figure 2** IPC/RPC communication model 17 18 19 20**IDL has the following advantages:** 21 22- Services are defined in the form of interfaces in IDL. Therefore, you do not need to focus on implementation details. 23 24- Interfaces defined by IDL can be used in IPC or RPC scenarios. The information or code generated based on the definitions in IDL simplifies IPC or RPC implementation. 25 26## IDL File Structure 27 28### Data Types 29 30#### Primitive Type 31| IDL Primitive Type| C++ Primitive Type| TS Primitive Type| 32| -------- | -------- | -------- | 33|void | void | void | 34|boolean | bool | boolean | 35|byte | int8_t | number | 36|short | int16_t | number | 37|int | int32_t | number | 38|long | int64_t | number | 39|float | float | number | 40|double | double | number | 41|String | std::string | string | 42 43The preceding table lists the primitive types supported by IDL and the mappings to the C++ and TS primitive types. 44 45#### sequenceable Type 46The sequenceable type is declared using the keyword **sequenceable**. This type can be passed during IPC or RPC through **Parcel** objects. The declaration mode of the sequenceable type in C++ is different from that in TS. 47 48In C++, the declaration is placed in the file header in the format of **sequenceable includedir..namespace.typename**. It can be in any of the following forms: 49 50```cpp 51sequenceable includedir..namespace.typename 52sequenceable includedir...typename 53sequenceable namespace.typename 54``` 55 56In the preceding information, **includedir** indicates the directory where the header file of the type is located, and the dot (.) is used as the separator. **namespace** indicates the namespace where the type is located, and the dot (.) is used as the separator. **typename** indicates the data type, which can contain only English characters. **includedir** and **namespace** are separated by two dots (..). If the declaration statement does not contain two dots, all characters except the last typename will be parsed as a namespace. Example: 57 58```cpp 59sequenceable a.b..C.D 60``` 61 62The preceding statement is parsed into the following code in the C++ header file: 63 64```cpp 65#include "a/b/d.h" 66using C::D; 67``` 68 69In TS, the declaration is placed in the file header in the format of **sequenceable namespace.typename;**. An example is provided below, where **idl** is the namespace and **MySequenceable** is the type name: 70 71```ts 72sequenceable idl.MySequenceable 73``` 74 75In the preceding information, **namespace** indicates the namespace to which the data type belongs, **typename** indicates the data type name, and **MySequenceable** indicates that data can be passed during IPC using **Parcel** objects. The sequenceable type is not defined in the IDL file, but in the .ts file. Therefore, IDL adds the following statement to the generated .ts file based on the declaration: 76 77```ts 78import MySequenceable from "./my_sequenceable" 79``` 80 81Note that IDL does not implement code for this type. It only imports the header file in the specified format or imports the specified module and uses the type. Therefore, you must ensure that the imported directory, namespace, and type are correct. 82 83#### Interface Type 84The interface type refers to interfaces defined in IDL files. The interfaces defined in an IDL file can be directly used as the parameter type or return value type of a method declared in the file. If an IDL file attempts to use interfaces defined in other IDL files, forward declaration must be contained in the header of that IDL file. 85 86The declaration form in C++ is similar to that of the sequenceable type. The declaration form is as follows: 87 88```cpp 89interface includedir..namespace.typename 90``` 91 92In TS, the declaration form is as follows: 93 94```ts 95interface namespace.interfacename 96``` 97 98In the preceding information, **namespace** indicates the namespace to which the interface belongs, and **interfacename** indicates the name of the interface. For example, **interface OHOS.IIdlTestObserver;** declares the **IIdlTestObserver** interface defined in another IDL file. This interface can be used as the parameter type or return value type of a method in the current file. IDL adds the following statement to the generated .ts file based on the statement: 99 100```ts 101import IIdlTestObserver from "./i_idl_test_observer" 102``` 103 104#### Array Type 105The array type is represented by T[], where **T** can be the primitive, sequenceable, interface, or array type. In C++, this type is generated as **std::vector<T>**. 106The table below lists the mappings between the IDL array type and TS and C++ data types. 107 108|IDL Data Type | C++ Data Type | TS Data Type | 109| ------- | -------- | -------- | 110|T[] | std::vector<T> | T[] | 111 112#### Container Type 113IDL supports two container types: List and Map. The List container is represented in the format of **List<T>**. The Map container is represented in the format of **Map<KT,VT>**, where **T**, **KT**, and **VT** can be of the primitive, sequenceable, interface, array, or container type. 114 115In C++, the List container type is generated as **std::list**, and the Map container type is generated as **std::map**. 116 117In TS, the List container type is not supported, and the Map container type is generated as **Map**. 118 119The table below lists the mappings between the IDL container type and TS and C++ data types. 120 121|IDL Data Type | C++ Data Type | TS Data Type | 122| -------- | -------- | ------- | 123|List<T> | std::list | Not supported | 124|Map<KT,VT> | std::map | Map | 125 126 127### Specifications for Compiling IDL Files 128Only one interface type can be defined in an IDL file, and the interface name must be the same as the file name. The interface definition of the IDL file is described in Backus-Naur form (BNF). The basic definition format is as follows: 129 130``` 131[<*interface_attr_declaration*>]interface<*interface_name_with_namespace*>{<*method_declaration*>} 132``` 133 134In the preceding information, <*interface_attr_declaration*> declares interface attributes. Currently, only the **oneway** attribute is supported, indicating that all methods in the interface are unidirectional. Such a method returns value without waiting for the execution to complete. This attribute is optional. If this attribute is not set, synchronous call is used. The interface name must contain the complete interface header file directory, namespace, and method declaration. Null interfaces are not allowed. 135The method declaration format in the interface is as follows: 136 137``` 138[<*method_attr_declaration*>]<*result_type*><*method_declaration*> 139``` 140 141In the preceding information, <*method_attr_declaration*> describes the interface attributes. Currently, only the **oneway** attribute is supported, indicating that the method is unidirectional. Such a method returns value without waiting for the execution to complete. This attribute is optional. If this attribute is not set, synchronous call is used. <*result_type*> indicates the type of the return value, and <*method_declaration*> indicates the method name and parameter declaration. 142The parameter declaration format is as follows: 143 144``` 145[<*formal_param_attr*>]<*type*><*identifier*> 146``` 147 148The value of <*formal_param_attr*> can be **in**, **out**, or **inout**, indicating that the parameter is an input parameter, an output parameter, or both an input and an output parameter, respectively. A **oneway** method does not allow **output** or **inout** parameters or return values. 149 150## How to Develop 151 152### Obtaining IDL 153#### Method 1 (Recommended) 1541. On Linux, download two OpenHarmony repositories: ability_idl_tool and third_party_bounds_checking_function. 1552. Go to the ability_idl_tool repository, and run the **make** command in the directory where **Makefile** is located. (Modify the relative position of **bounds_checking_function** in **MakefileLinux**.) 1563. Find the idl-gen executable file generated in the current directory to debug local IDL files. 157 158#### Method 2 159On DevEco Studio, choose **Tools > SDK Manager** to view the local installation path of the OpenHarmony SDK. The following figure uses DevEco Studio 3.0.0.993 as an example. 160 161 162 163 164 165Go to the local installation path, choose **toolchains > 3.x.x.x** (the folder named after the version number), and check whether the executable file of IDL exists. 166 167> **NOTE** 168> 169> Use the SDK of the latest version. The use of an earlier version may cause errors in some statements. 170 171If the executable file does not exist, download the SDK package from the mirror as instructed in the [Release Notes](../../release-notes). The following uses [3.2 Beta3](../../release-notes/OpenHarmony-v3.2-beta3.md) as an example. 172 173For details about how to replace the SDK package, see [Full SDK Compilation Guide](../faqs/full-sdk-compile-guide.md). 174 175After obtaining the executable file, perform subsequent development steps based on your scenario. 176 177### Development Using TS 178 179#### Creating an IDL File 180 181You can use TS to create IDL files. 182 183For example, create a file named **IIdlTestService.idl** with the following content: 184 185```cpp 186 interface OHOS.IIdlTestService { 187 int TestIntTransaction([in] int data); 188 void TestStringTransaction([in] String data); 189 void TestMapTransaction([in] Map<int, int> data); 190 int TestArrayTransaction([in] String[] data); 191 } 192``` 193 194Run the **idl -gen-ts -d *dir* -c dir/IIdlTestService.idl** command in the folder where the executable file is located. 195 196-*dir* next to **d** is the target output folder. For example, if the target output folder is **IIdlTestServiceTs**, run the **idl -gen-ts -d IIdlTestServiceTs -c IIdlTestServiceTs/IIdlTestService.idl** command in the folder where the executable file is located. The interface file, stub file, and proxy file are generated in the *dir* directory (**IIdlTestServiceTs** directory in this example) in the execution environment. 197 198> **NOTE** 199> 200> The generated interface class file name must be the same as that of the .idl file. Otherwise, an error occurs during code generation. 201 202For example, for an .idl file named **IIdlTestService.idl** and target output directory named **IIdlTestServiceTs**, the directory structure is similar to the following: 203 204``` 205├── IIdlTestServiceTs # IDL code output folder 206│ ├── i_idl_test_service.ts # File generated 207│ ├── idl_test_service_proxy.ts # File generated 208│ ├── idl_test_service_stub.ts # File generated 209│ └── IIdlTestService.idl # Constructed .idl file 210└── idl.exe # Executable file of IDL 211``` 212 213#### Exposing Interfaces on the Server 214 215The stub class generated by IDL is an abstract implementation of the interface class and declares all methods in the IDL file. 216 217```ts 218import {testIntTransactionCallback} from "./i_idl_test_service"; 219import {testStringTransactionCallback} from "./i_idl_test_service"; 220import {testMapTransactionCallback} from "./i_idl_test_service"; 221import {testArrayTransactionCallback} from "./i_idl_test_service"; 222import IIdlTestService from "./i_idl_test_service"; 223import rpc from "@ohos.rpc"; 224 225export default class IdlTestServiceStub extends rpc.RemoteObject implements IIdlTestService { 226 constructor(des: string) { 227 super(des); 228 } 229 230 async onRemoteMessageRequest(code: number, data: rpc.MessageSequence, reply: rpc.MessageSequence, 231 option: rpc.MessageOption): Promise<boolean> { 232 console.log("onRemoteMessageRequest called, code = " + code); 233 if (code == IdlTestServiceStub.COMMAND_TEST_INT_TRANSACTION) { 234 let _data = data.readInt(); 235 this.testIntTransaction(_data, (errCode: number, returnValue: number) => { 236 reply.writeInt(errCode); 237 if (errCode == 0) { 238 reply.writeInt(returnValue); 239 } 240 }); 241 return true; 242 } else if (code == IdlTestServiceStub.COMMAND_TEST_STRING_TRANSACTION) { 243 let _data = data.readString(); 244 this.testStringTransaction(_data, (errCode: number) => { 245 reply.writeInt(errCode); 246 }); 247 return true; 248 } else if (code == IdlTestServiceStub.COMMAND_TEST_MAP_TRANSACTION) { 249 let _data: Map<number, number> = new Map(); 250 let _dataSize = data.readInt(); 251 for (let i = 0; i < _dataSize; ++i) { 252 let key = data.readInt(); 253 let value = data.readInt(); 254 _data.set(key, value); 255 } 256 this.testMapTransaction(_data, (errCode: number) => { 257 reply.writeInt(errCode); 258 }); 259 return true; 260 } else if (code == IdlTestServiceStub.COMMAND_TEST_ARRAY_TRANSACTION) { 261 let _data = data.readStringArray(); 262 this.testArrayTransaction(_data, (errCode: number, returnValue: number) => { 263 reply.writeInt(errCode); 264 if (errCode == 0) { 265 reply.writeInt(returnValue); 266 } 267 }); 268 return true; 269 } else { 270 console.log("invalid request code" + code); 271 } 272 return false; 273 } 274 275 testIntTransaction(data: number, callback: testIntTransactionCallback): void{} 276 testStringTransaction(data: string, callback: testStringTransactionCallback): void{} 277 testMapTransaction(data: Map<number, number>, callback: testMapTransactionCallback): void{} 278 testArrayTransaction(data: string[], callback: testArrayTransactionCallback): void{} 279 280 static readonly COMMAND_TEST_INT_TRANSACTION = 1; 281 static readonly COMMAND_TEST_STRING_TRANSACTION = 2; 282 static readonly COMMAND_TEST_MAP_TRANSACTION = 3; 283 static readonly COMMAND_TEST_ARRAY_TRANSACTION = 4; 284} 285``` 286 287You need to inherit the interface class defined in the IDL file and implement the methods in the class. The following code snippet shows how to inherit the **IdlTestServiceStub** interface class and implement the **testIntTransaction**, **testStringTransaction**, **testMapTransaction**, and **testArrayTransaction** methods. 288 289```ts 290import {testIntTransactionCallback} from "./i_idl_test_service" 291import {testStringTransactionCallback} from "./i_idl_test_service" 292import {testMapTransactionCallback} from "./i_idl_test_service"; 293import {testArrayTransactionCallback} from "./i_idl_test_service"; 294import IdlTestServiceStub from "./idl_test_service_stub" 295 296 297class IdlTestImp extends IdlTestServiceStub { 298 299 testIntTransaction(data: number, callback: testIntTransactionCallback): void 300 { 301 callback(0, data + 1); 302 } 303 testStringTransaction(data: string, callback: testStringTransactionCallback): void 304 { 305 callback(0); 306 } 307 testMapTransaction(data: Map<number, number>, callback: testMapTransactionCallback): void 308 { 309 callback(0); 310 } 311 testArrayTransaction(data: string[], callback: testArrayTransactionCallback): void 312 { 313 callback(0, 1); 314 } 315} 316``` 317 318After the service implements the interface, the interface needs to be exposed to the client for connection. If your service needs to expose this interface, extend **Ability** and implement **onConnect()** to return **IRemoteObject** so that the client can interact with the service process. The following code snippet shows how to expose the **IRemoteAbility** interface to the client: 319 320```ts 321import Want from '@ohos.app.ability.Want'; 322import rpc from "@ohos.rpc"; 323 324class ServiceAbility { 325 onStart() { 326 console.info('ServiceAbility onStart'); 327 } 328 onStop() { 329 console.info('ServiceAbility onStop'); 330 } 331 onCommand(want: Want, startId: number) { 332 console.info('ServiceAbility onCommand'); 333 } 334 onConnect(want: Want) { 335 console.info('ServiceAbility onConnect'); 336 try { 337 console.log('ServiceAbility want:' + typeof(want)); 338 console.log('ServiceAbility want:' + JSON.stringify(want)); 339 console.log('ServiceAbility want name:' + want.bundleName) 340 } catch(err) { 341 console.log('ServiceAbility error:' + err) 342 } 343 console.info('ServiceAbility onConnect end'); 344 return new IdlTestImp('connect') as rpc.RemoteObject; 345 } 346 onDisconnect(want: Want) { 347 console.info('ServiceAbility onDisconnect'); 348 console.info('ServiceAbility want:' + JSON.stringify(want)); 349 } 350} 351 352export default new ServiceAbility() 353``` 354 355#### Calling Methods from the Client for IPC 356 357When the client calls **connectServiceExtensionAbility()** to connect to a ServiceAbility, the **onConnect** callback in **onAbilityConnectDone** of the client receives the **IRemoteObject** instance returned by the **onConnect()** method of the ServiceAbility. The client and ServiceAbility are in different applications. Therefore, the directory of the client application must contain a copy of the .idl file (the SDK automatically generates the proxy class). The **onConnect** callback then uses the **IRemoteObject** instance to create the **testProxy** instance of the **IdlTestServiceProxy** class and calls the related IPC method. The sample code is as follows: 358 359```ts 360import common from '@ohos.app.ability.common'; 361import Want from '@ohos.app.ability.Want'; 362import IdlTestServiceProxy from './idl_test_service_proxy' 363 364function callbackTestIntTransaction(result: number, ret: number): void { 365 if (result == 0 && ret == 124) { 366 console.log('case 1 success'); 367 } 368} 369 370function callbackTestStringTransaction(result: number): void { 371 if (result == 0) { 372 console.log('case 2 success'); 373 } 374} 375 376function callbackTestMapTransaction(result: number): void { 377 if (result == 0) { 378 console.log('case 3 success'); 379 } 380} 381 382function callbackTestArrayTransaction(result: number, ret: number): void { 383 if (result == 0 && ret == 124) { 384 console.log('case 4 success'); 385 } 386} 387 388let onAbilityConnectDone: common.ConnectOptions = { 389 onConnect: (elementName, proxy) => { 390 let testProxy: IdlTestServiceProxy = new IdlTestServiceProxy(proxy); 391 let testMap: Map<number, number> = new Map(); 392 testMap.set(1, 1); 393 testMap.set(1, 2); 394 testProxy.testIntTransaction(123, callbackTestIntTransaction); 395 testProxy.testStringTransaction('hello', callbackTestStringTransaction); 396 testProxy.testMapTransaction(testMap, callbackTestMapTransaction); 397 testProxy.testArrayTransaction(['1','2'], callbackTestMapTransaction); 398 }, 399 onDisconnect: (elementName) => { 400 console.log('onDisconnectService onDisconnect'); 401 }, 402 onFailed: (code) => { 403 console.log('onDisconnectService onFailed'); 404 } 405}; 406 407let context: common.UIAbilityContext = this.context; 408 409function connectAbility(): void { 410 let want: Want = { 411 bundleName: 'com.example.myapplicationidl', 412 abilityName: 'com.example.myapplicationidl.ServiceAbility' 413 }; 414 let connectionId = -1; 415 connectionId = context.connectServiceExtensionAbility(want, onAbilityConnectDone); 416} 417 418 419``` 420 421#### Transferring a sequenceable Object During IPC 422 423You can send a class from one process to another through IPC interfaces. However, you must ensure that the peer can use the code of this class and this class supports the **marshalling** and **unmarshalling** methods. The system uses **marshalling** and **unmarshalling** to serialize and deserialize objects into objects that can be identified by each process. 424 425**To create a class that supports the sequenceable type, perform the following operations:** 426 4271. Implement the **marshalling** method, which obtains the current state of the object and serializes the object into a **Parcel** object. 4282. Implement the **unmarshalling** method, which deserializes the object from a **Parcel** object. 429 430The following is an example of the **MySequenceable** class code: 431 432```ts 433import rpc from '@ohos.rpc'; 434export default class MySequenceable implements rpc.Sequenceable { 435 constructor(num: number, str: string) { 436 this.num = num; 437 this.str = str; 438 } 439 getNum() : number { 440 return this.num; 441 } 442 getString() : string { 443 return this.str; 444 } 445 marshalling(messageParcel: rpc.MessageParcel) { 446 messageParcel.writeInt(this.num); 447 messageParcel.writeString(this.str); 448 return true; 449 } 450 unmarshalling(messageParcel: rpc.MessageParcel) { 451 this.num = messageParcel.readInt(); 452 this.str = messageParcel.readString(); 453 return true; 454 } 455 private num: number; 456 private str: string; 457} 458``` 459 460### Development Using C++ (Automatically Generating ServiceAbility Interface Template Code During Compilation) 461 462#### Creating an IDL File 463 464You can use C++ to create IDL files. 465 466For example, create a file named **IQuickFixManager.idl** with the following content: 467 468``` 469/* 470 * Copyright (c) 2023 Huawei Device Co., Ltd. 471 * Licensed under the Apache License, Version 2.0 (the "License"); 472 * you may not use this file except in compliance with the License. 473 * You may obtain a copy of the License at 474 * 475 * http://www.apache.org/licenses/LICENSE-2.0 476 * 477 * Unless required by applicable law or agreed to in writing, software 478 * distributed under the License is distributed on an "AS IS" BASIS, 479 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 480 * See the License for the specific language governing permissions and 481 * limitations under the License. 482 */ 483 484sequenceable QuickFixInfo..OHOS.AAFwk.ApplicationQuickFixInfo; 485interface OHOS.AAFwk.IQuickFixManager { 486 void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug); 487 void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo); 488 void RevokeQuickFix([in] String bundleName); 489} 490``` 491 492#### Modifying the BUILD.gn File 493Two methods are available for modification. 494 495##### Method 1 (Recommended. IDL Files Can Be Processed in Batches and Compiled into .so Files) 496 4971. Import the IDL tool template to the current **BUILD.gn** file. 498 499 ```bash 500 # Copy the line below to the .gn file. 501 import("//foundation/ability/idl_tool/idl_config.gni") 502 ``` 503 5042. Invoke the IDL tool to generate a C++ template file. 505 506 ```bash 507 508 # Use idl_gen_interface to generate a template file. The value passed in will be used in deps. 509 idl_gen_interface("EEEFFFGGG") { 510 # Name of your .idl file, which must be in the same path as the .gn file. 511 sources = [ 512 "IAxxBxxCxx.idl", 513 "IAxxBxxCxx2.idl", 514 ] 515 516 # Based on the usage of user-defined objects in the IDL file, you must add the compilation of the corresponding .cpp file when compiling the .so file. The default value is null. 517 sources_cpp = [] 518 519 # Add configs during .so file compilation. 520 configs = [] 521 522 # Add public_deps during .so file compilation. 523 sequenceable_pub_deps = [] 524 525 # Add external_deps during .so file compilation. 526 sequeceable_ext_deps = [] 527 528 # Add innerapi_tags during .so file compilation. 529 innerapi_tags = "" 530 531 # Add sanitize during .so file compilation. 532 sanitize = "" 533 534 # Enable hitrace. The value is the uint64_t type identifier defined in the hitrace_meter.h file. You need to enter the variable name of the constant. 535 hitrace = "HITRACE_TAG_ABILITY_MANAGER" 536 537 # Enable hilog. The domain ID is a hexadecimal integer. 538 log_domainid = "0xD003900" 539 # Enable hilog. The tag name is a string, which is generally a subsystem name. 540 log_tag = "QuickFixManagerService" 541 542 # (Mandatory) Add subsystem_name during .so file compilation. The value must be the same as the actual subsystem name. For example, use the following in quick_fix: 543 subsystem_name = "ability" 544 # (Mandatory) Add part_name during .so file compilation. The value must be the same as the actual part name. For example, use the following in quick_fix: 545 part_name = "ability_runtime" 546 } 547 ``` 548 549 Configure hilog. The log_domainid and log_tag parameters must appear in pairs; otherwise, a compilation error occurs. For example, use the following in quick_fix: 550 551 ```bash 552 idl_gen_interface("quickfix_manager_interface") { 553 sources = [ 554 "IQuickFixManager.idl" 555 ] 556 hitrace = "HITRACE_TAG_ABILITY_MANAGER" 557 log_domainid = "0xD003900" 558 log_tag = "QuickFixManagerService" # An error occurs during compilation if only log_tag or log_domainid is included. 559 } 560 ``` 561 5623. Add the dependency **EEEFFFGGG** to **BUILD.gn**. 563 564 ```bash 565 deps = [ 566 # Use the value passed in idl_gen_interface, prefixed with lib and suffixed with _proxy or _stub to obtain the generated .so file name. 567 ":libEEEFFFGGG_proxy", # Add this dependency if the proxy .so file is required. 568 ":libEEEFFFGGG_stub", # Add this dependency if the stub .so file is required. 569 ] 570 ``` 571 572 The name of the dependency added to **deps** must be the same as the value passed in **idl_gen_interface**. For example, use the following in quick_fix: 573 574 ```bash 575 idl_gen_interface("quickfix_manager_interface") { 576 sources = [ 577 "IQuickFixManager.idl" 578 ] 579 hitrace = "HITRACE_TAG_ABILITY_MANAGER" 580 log_domainid = "0xD003900" 581 log_tag = "QuickFixManagerService" 582 } 583 deps = [ 584 "${ability_runtime_innerkits_path}/app_manager:app_manager", 585 ":libquickfix_manager_interface_proxy", # Value passed in idl_gen_interface, prefixed with lib and suffixed with _proxy. 586 ":libquickfix_manager_interface_stub", # Value passed in idl_gen_interface, prefixed with lib and suffixed with _stub. 587 ] 588 ``` 589 5904. Add external dependencies of the template file to **BUILD.gn**. 591 592 Add the external dependencies of the template file to **external_deps**. 593 594 If a dependency already exists, you do not need to add it again; otherwise, compilation errors may occur. 595 596 ```bash 597 external_deps = [ 598 # Mandatory dependency of the template file 599 "c_utils:utils", 600 # Mandatory dependency of the hilog output 601 "hilog:libhilog", 602 # Mandatory dependency of hitrace output (not required if hitrace is not configured in idl_gen_interface.) 603 "hitrace:hitrace_meter", 604 # Mandatory dependency of the template file 605 "ipc:ipc_core", 606 ] 607 ``` 608 609##### Method 2 610 6111. Import the IDL tool template to the current **BUILD.gn** file. 612 613 ```bash 614 # Copy the line below to the .gn file. 615 import("//foundation/ability/idl_tool/idl_config.gni") 616 ``` 617 6182. Invoke the IDL tool to generate a C++ template file. 619 620 Replace *axx_bxx_cxx* in the code below with the .cpp file names of the generated stub and proxy. 621 622 ```bash 623 idl_interface_sources = [ 624 # Change axx_bxx_cxx to the name of the .cpp file of the generated proxy. 625 "${target_gen_dir}/axx_bxx_cxx_proxy.cpp", 626 # Change axx_bxx_cxx to the name of the .cpp file of the generated stub. 627 "${target_gen_dir}/axx_bxx_cxx_stub.cpp", 628 ] 629 630 # Use idl_gen_interface to generate a template file. You need to enter the parameter name, which will be used in deps. 631 idl_gen_interface("EEEFFFGGG") { 632 # Name of your .idl file, which is in the same path as the .gn file. 633 src_idl = rebase_path("IAxxBxxCxx.idl") 634 # The template file .cpp of the proxy and stub. You can copy the line below to the .gn file. 635 dst_file = string_join(",", idl_interface_sources) 636 # Enable hitrace. The value is the uint64_t type identifier defined in the hitrace_meter.h file. You need to enter the variable name of the constant. 637 hitrace = "HITRACE_TAG_ABILITY_MANAGER" 638 # Enable hilog. The domain ID is a hexadecimal integer. 639 log_domainid = "0xD003900" 640 # Enable hilog. The tag name is a string, which is generally a subsystem name. 641 log_tag = "QuickFixManagerService" 642 } 643 ``` 644 645 The names of ***axx_bxx_cxx_*proxy.cpp** and ***axx_bxx_cxx_*stub.cpp** are the same as the corresponding .idl file names in lowercase, with an underscore (_) added for each CamelCase segment. 646 647 ```bash 648 # For example, if the .idl file is IQuickFixManager.idl, 649 then axx_bxx_cxx_proxy.cpp is quick_fix_manager_proxy.cpp 650 and axx_bxx_cxx_stub.cpp is quick_fix_manager_stub.cpp. 651 ``` 652 653 If the name of the template file to be generated starts with I, add one **I** before the interface name. 654 655 ```bash 656 # For example, if the generated template file is **quick_fix_manager_proxy.cpp**, the interface name is **IQuickFixManager**. 657 # Definition in the .idl file 658 interface OHOS.AAFwk.IQuickFixManager { 659 void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug); 660 void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo); 661 void RevokeQuickFix([in] String bundleName); 662 } 663 ``` 664 665 Configure hilog. The log_domainid and log_tag parameters must appear in pairs; otherwise, a compilation error occurs. 666 667 ```bash 668 idl_gen_interface("quickfix_manager_interface") { 669 src_idl = rebase_path("IQuickFixManager.idl") 670 dst_file = string_join(",", idl_interface_sources) 671 hitrace = "HITRACE_TAG_ABILITY_MANAGER" 672 log_domainid = "0xD003900" 673 log_tag = "QuickFixManagerService" # An error occurs during compilation if only log_tag or log_domainid is included. 674 } 675 ``` 676 6773. Add the header file path of the template file to **BUILD.gn**. 678 679 You only need to add **${target_gen_dir}** to **include_dirs**. 680 681 ```bash 682 include_dirs = [ 683 "aaa/bbb/ccc", # Path of the original header file 684 "${target_gen_dir}", # Path of the template header file 685 ] 686 ``` 687 6884. Add the path of the template file .cpp to **BUILD.gn**. 689 690 If **sources** contain ***axx_bxx_cxx_*proxy.cpp** and ***axx_bxx_cxx_*stub.cpp**, delete them and add **sources += filter_include(output_values, [ "*.cpp" ])**. 691 692 ```bash 693 output_values = get_target_outputs(":EEEFFFGGG") # Return the output file list of the target tag. Replace EEEFFFGGG. 694 sources = [ "axx_bxx_cxx_proxy.cpp" ] # Delete axx_bxx_cxx_proxy.cpp. 695 sources += filter_include(output_values, [ "*.cpp" ]) # filter_include selects the list that meets the requirements. You can copy this line directly. 696 ``` 697 6985. Add the dependency **EEEFFFGGG** to **BUILD.gn**. 699 700 ```bash 701 deps = [ 702 ":EEEFFFGGG", 703 ] 704 ``` 705 706 The name of the dependency added to **deps** must be the same as the parameter name of the **idl_gen_interface** function. 707 708 ```bash 709 idl_gen_interface("quickfix_manager_interface") { 710 src_idl = rebase_path("IQuickFixManager.idl") 711 dst_file = string_join(",", idl_interface_sources) 712 hitrace = "HITRACE_TAG_ABILITY_MANAGER" 713 log_domainid = "0xD003900" 714 log_tag = "QuickFixManagerService" 715 } 716 deps = [ 717 "${ability_runtime_innerkits_path}/app_manager:app_manager", 718 ":quickfix_manager_interface"] # Same as the parameter name of the idl_gen_interface function. 719 ``` 720 7216. Add external dependencies of the template file to **BUILD.gn**. 722 723 Add the external dependencies of the template file to **external_deps**. 724 725 If a dependency already exists, you do not need to add it again; otherwise, compilation errors may occur. 726 727 ```bash 728 external_deps = [ 729 # Mandatory dependency of the template file 730 "c_utils:utils", 731 # Mandatory dependency of the hilog output 732 "hilog:libhilog", 733 # Mandatory dependency of the hitrace output 734 "hitrace:hitrace_meter", 735 # Mandatory dependency of the template file 736 "ipc:ipc_core", 737 ] 738 ``` 739 740#### Example 741 742The following uses the quick fix service as an example: 743 7441. Create the **IQuickFixManager.idl** file. 745 746 When creating the .idl file, ensure that the interface name is the same as the .idl file name; otherwise, an error occurs during code generation. 747 748 The path of the .idl file must be the same as that of the **BUILD.gn** file of the function code. 749 750 In the example, the file is in **foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/**. 751 752 ```bash 753 /* 754 * Copyright (c) 2023 Huawei Device Co., Ltd. 755 * Licensed under the Apache License, Version 2.0 (the "License"); 756 * you may not use this file except in compliance with the License. 757 * You may obtain a copy of the License at 758 * 759 * http://www.apache.org/licenses/LICENSE-2.0 760 * 761 * Unless required by applicable law or agreed to in writing, software 762 * distributed under the License is distributed on an "AS IS" BASIS, 763 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 764 * See the License for the specific language governing permissions and 765 * limitations under the License. 766 */ 767 768 sequenceable QuickFixInfo..OHOS.AAFwk.ApplicationQuickFixInfo; 769 interface OHOS.AAFwk.IQuickFixManager { 770 void ApplyQuickFix([in] String[] quickFixFiles, [in] boolean isDebug); 771 void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo); 772 void RevokeQuickFix([in] String bundleName); 773 } 774 ``` 775 776 When creating the .idl file, change the return value of the function from int to void. 777 778 ```bash 779 # Functions in quick_fix_manager_client.h 780 int32_t ApplyQuickFix(const std::vector<std::string> &quickFixFiles); 781 int32_t GetApplyedQuickFixInfo(const std::string &bundleName, ApplicationQuickFixInfo &quickFixInfo); 782 int32_t RevokeQuickFix(const std::string &bundleName); 783 # Definition in the .idl file 784 interface OHOS.AAFwk.QuickFixManager { 785 void ApplyQuickFix([in] String[] quickFixFiles); 786 void GetApplyedQuickFixInfo([in] String bundleName, [out] ApplicationQuickFixInfo quickFixInfo); 787 void RevokeQuickFix([in] String bundleName); 788 } 789 ``` 790 7912. Modify the BUILD.gn file. 792 793 ```bash 794 # Copyright (c) 2023 Huawei Device Co., Ltd. 795 # Licensed under the Apache License, Version 2.0 (the "License"); 796 # you may not use this file except in compliance with the License. 797 # You may obtain a copy of the License at 798 # 799 # http://www.apache.org/licenses/LICENSE-2.0 800 # 801 # Unless required by applicable law or agreed to in writing, software 802 # distributed under the License is distributed on an "AS IS" BASIS, 803 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 804 # See the License for the specific language governing permissions and 805 # limitations under the License. 806 807 import("//build/ohos.gni") 808 import("//foundation/ability/ability_runtime/ability_runtime.gni") 809 import("//foundation/ability/idl_tool/idl_config.gni") 810 811 idl_interface_sources = [ 812 "${target_gen_dir}/quick_fix_manager_proxy.cpp", 813 "${target_gen_dir}/quick_fix_manager_stub.cpp", 814 ] 815 816 idl_gen_interface("quickfix_manager_interface") { 817 src_idl = rebase_path("IQuickFixManager.idl") 818 dst_file = string_join(",", idl_interface_sources) 819 hitrace = "HITRACE_TAG_ABILITY_MANAGER" 820 log_domainid = "0xD003900" 821 log_tag = "QuickFixManagerService" 822 } 823 824 config("quickfix_config") { 825 visibility = [ ":*" ] 826 include_dirs = [ 827 "include", 828 "${target_gen_dir}", 829 ] 830 cflags = [] 831 if (target_cpu == "arm") { 832 cflags += [ "-DBINDER_IPC_32BIT" ] 833 } 834 } 835 836 ohos_shared_library("quickfix_manager") { 837 configs = [ "${ability_runtime_services_path}/common:common_config" ] 838 public_configs = [ ":quickfix_config" ] 839 840 output_values = get_target_outputs(":quickfix_manager_interface") 841 sources = [ 842 "src/quick_fix_error_utils.cpp", 843 "src/quick_fix_info.cpp", 844 "src/quick_fix_load_callback.cpp", 845 "src/quick_fix_manager_client.cpp", 846 "src/quick_fix_utils.cpp", 847 ] 848 sources += filter_include(output_values, [ "*.cpp" ]) 849 defines = [ "AMS_LOG_TAG = \"QuickFixService\"" ] 850 deps = [ 851 ":quickfix_manager_interface", 852 "${ability_runtime_innerkits_path}/app_manager:app_manager", 853 ] 854 855 external_deps = [ 856 "ability_base:want", 857 "bundle_framework:appexecfwk_base", 858 "bundle_framework:appexecfwk_core", 859 "c_utils:utils", 860 "hilog:libhilog", 861 "hitrace:hitrace_meter", 862 "ipc:ipc_single", 863 "safwk:system_ability_fwk", 864 "samgr:samgr_proxy", 865 ] 866 867 innerapi_tags = [ "platformsdk" ] 868 subsystem_name = "ability" 869 part_name = "ability_runtime" 870 } 871 ``` 872 8733. Specify the path and directory structure of the generated template file. 874 875 Take rk3568 as an example. The path of the template file generated in the instance is **out/rk3568/gen/foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/**, 876 877 where **foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/** is the relative path of the .idl file. 878 879 The directory structure of the template file generated is as follows: 880 881 ```bash 882 |-- out/rk3568/gen/foundation/ability/ability_runtime/interfaces/inner_api/quick_fix/ 883 |-- iquick_fix_manager.h 884 |-- quick_fix_manager_stub.h 885 |-- quick_fix_manager_stub.cpp 886 |-- quick_fix_manager_proxy.h 887 |-- quick_fix_manager_proxy.cpp 888 ``` 889 890