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![IDL-interface-description](./figures/IDL-interface-description.png)
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![IPC-RPC-communication-model](./figures/IPC-RPC-communication-model.png)
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&lt;T&gt;**. 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&lt;T&gt;           | 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![SDKpath](./figures/SDKpath.png)
162
163![SDKpath](./figures/SDKpath2.png)
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