1# Using AppServiceExtensionAbility for Background Services 2<!--Kit: Ability Kit--> 3<!--Subsystem: Ability--> 4<!--Owner: @yewei0794--> 5<!--Designer: @jsjzju--> 6<!--Tester: @lixueqing513--> 7<!--Adviser: @huipeizi--> 8 9## Overview 10 11Starting from API version 20, you can use the [AppServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-appServiceExtensionAbility.md) component to provide backend services. This component is designed primarily for common enterprise applications on 2-in-1 devices, for example, EDR software for network security or MDM software for fleet management. 12 13## Available APIs 14 15You can invoke an AppServiceExtensionAbility from a UIAbility in two ways: starting or connecting. The comparison between the two methods is as follows. 16 17| Invocation Method| API| Description| 18| -------- | -------- | -------- | 19| Start| [startAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#startappserviceextensionability20) | After a UIAbility starts an AppServiceExtensionAbility, they have a weak association. The AppServiceExtensionAbility keeps running even after the UIAbility exits.| 20| Connect| [connectAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#connectappserviceextensionability20) | After a UIAbility connects to an AppServiceExtensionAbility, they have a strong association. The AppServiceExtensionAbility exits along with the UIAbility when the latter exits.| 21 22## Constraints 23 24- The AppServiceExtensionAbility takes effect only on 2-in-1 devices. 25 26- To integrate an AppServiceExtensionAbility, applications must request the ACL permission (ohos.permission.SUPPORT_APP_SERVICE_EXTENSION). This ACL permission is available only for enterprise applications. 27 28- If the [AppServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-appServiceExtensionAbility.md) instance is not started, the caller must be the application to which the [AppServiceExtensionAbility](js-apis-app-ability-appServiceExtensionAbility.md) instance belongs or an application in the application list supported by the AppServiceExtensionAbility instance (configured in the **appIdentifierAllowList** property of [extensionAbilities](../quick-start/module-configuration-file.md#extensionabilities)). 29 30- APIs related to [Window](../reference/apis-arkui/arkts-apis-window.md) cannot be called in the AppServiceExtensionAbility. 31 32## Working Principles 33 34- In this document, the component that starts or connects to an AppServiceExtensionAbility is called the client, and the AppServiceExtensionAbility is called the server. 35 36- If an AppServiceExtensionAbility is started only by means of connecting, its lifecycle is controlled by the client. A new connection is set up each time the client calls [connectAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#connectappserviceextensionability20). When the client exits or calls [disconnectAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#disconnectappserviceextensionability20), the connection is interrupted. After all connections are interrupted, the AppServiceExtensionAbility automatically exits. 37 38- Once an AppServiceExtensionAbility is started by means of starting, it will not exit automatically. Applications can call [stopAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#stopappserviceextensionability20) to stop it. 39 40- When the AppServiceExtensionAbility is started by means of starting and has no active connections, its process may be suspended. For details, see [Introduction to Background Tasks Kit](../task-management/background-task-overview.md). 41 42## Implementing a Background Service 43 44### Creating a Background Service 45 46To manually create an AppServiceExtensionAbility in the DevEco Studio project, perform the following steps: 47 481. In the **ets** directory of a module in the project, right-click and choose **New > Directory** to create a directory named **AppServiceExtAbility**. 49 502. Right-click the **AppServiceExtAbility** directory, and choose **New > ArkTS File** to create a file named **AppServiceExtAbility.ets**. 51 52 ``` 53 ├── ets 54 │ ├── AppServiceExtAbility 55 │ │ ├── AppServiceExtAbility.ets 56 └ 57 ``` 58 593. In the **AppServiceExtAbility.ets** file, import the [AppServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-appServiceExtensionAbility.md) module. Customize a class that inherits from AppServiceExtensionAbility and implement the lifecycle callbacks. 60 61 ```ts 62 import { AppServiceExtensionAbility, Want } from '@kit.AbilityKit'; 63 import { rpc } from '@kit.IPCKit'; 64 import { hilog } from '@kit.PerformanceAnalysisKit'; 65 66 const TAG: string = '[AppServiceExtAbility]'; 67 const DOMAIN_NUMBER: number = 0xFF00; 68 69 class StubTest extends rpc.RemoteObject { 70 constructor(des: string) { 71 super(des); 72 } 73 } 74 75 export default class AppServiceExtAbility extends AppServiceExtensionAbility { 76 onCreate(want: Want): void { 77 let appServiceExtensionContext = this.context; 78 hilog.info(DOMAIN_NUMBER, TAG, `onCreate, want: ${want.abilityName}`); 79 }; 80 81 onRequest(want: Want, startId: number): void { 82 hilog.info(DOMAIN_NUMBER, TAG, `onRequest, want: ${want.abilityName}`); 83 }; 84 85 onConnect(want: Want): rpc.RemoteObject { 86 hilog.info(DOMAIN_NUMBER, TAG, `onConnect, want: ${want.abilityName}`); 87 return new StubTest("test"); 88 }; 89 90 onDisconnect(want: Want): void { 91 hilog.info(DOMAIN_NUMBER, TAG, `onDisconnect, want: ${want.abilityName}`); 92 }; 93 94 onDestroy(): void { 95 hilog.info(DOMAIN_NUMBER, TAG, 'onDestroy'); 96 }; 97 }; 98 ``` 99 1004. Register the AppServiceExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) of the module in the project. Set **type** to **"appService"** and **srcEntry** to the code path of the AppServiceExtensionAbility component. 101 102 ```json 103 { 104 "module": { 105 // ... 106 "extensionAbilities": [ 107 { 108 "name": "AppServiceExtAbility", 109 "icon": "$media:icon", 110 "description": "appService", 111 "type": "appService", 112 "exported": true, 113 "srcEntry": "./ets/AppServiceExtAbility/AppServiceExtAbility.ets" 114 } 115 ] 116 } 117 } 118 ``` 119 120### Starting a Background Service 121 122An application uses [startAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#startappserviceextensionability20) to start a background service. The [onRequest()](../reference/apis-ability-kit/js-apis-app-ability-appServiceExtensionAbility.md#onrequest) callback is invoked, through which the background service receives the [Want](../reference/apis-ability-kit/js-apis-app-ability-want.md) object passed by the caller. After the background service is started, its lifecycle is independent of the client. In other words, even if the client is destroyed, the background service remains alive. Therefore, the background service must be stopped by calling [terminateSelf()](../reference/apis-ability-kit/js-apis-inner-application-appServiceExtensionContext.md#terminateself) when its work is complete. Alternatively, another component can call [stopAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#stopappserviceextensionability20) to stop the background service. 123 124 125- Start a new [AppServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-appServiceExtensionAbility.md) in an application. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). 126 127 ```ts 128 import { common, Want } from '@kit.AbilityKit'; 129 import { hilog } from '@kit.PerformanceAnalysisKit'; 130 import { BusinessError } from '@kit.BasicServicesKit'; 131 132 const TAG: string = '[Page_AppServiceExtensionAbility]'; 133 const DOMAIN_NUMBER: number = 0xFF00; 134 135 @Entry 136 @Component 137 struct Page_AppServiceExtensionAbility { 138 build() { 139 Column() { 140 //... 141 List({ initialIndex: 0 }) { 142 ListItem() { 143 Row() { 144 //... 145 } 146 .onClick(() => { 147 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; // UIAbilityContext 148 let want: Want = { 149 deviceId: '', 150 bundleName: 'com.samples.stagemodelabilitydevelop', 151 abilityName: 'AppServiceExtAbility' 152 }; 153 context.startAppServiceExtensionAbility(want).then(() => { 154 hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting AppServiceExtensionAbility.'); 155 // The background service is started. 156 this.getUIContext().getPromptAction().showToast({ 157 message: 'SuccessfullyStartBackendService' 158 }); 159 }).catch((err: BusinessError) => { 160 hilog.error(DOMAIN_NUMBER, TAG, 161 `Failed to start AppServiceExtensionAbility. Code is ${err.code}, message is ${err.message}`); 162 }); 163 }) 164 } 165 166 //... 167 } 168 169 //... 170 } 171 172 //... 173 } 174 } 175 ``` 176 177- Stop the [AppServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-appServiceExtensionAbility.md) in the application. 178 179 ```ts 180 import { common, Want } from '@kit.AbilityKit'; 181 import { hilog } from '@kit.PerformanceAnalysisKit'; 182 import { BusinessError } from '@kit.BasicServicesKit'; 183 184 const TAG: string = '[Page_AppServiceExtensionAbility]'; 185 const DOMAIN_NUMBER: number = 0xFF00; 186 187 @Entry 188 @Component 189 struct Page_AppServiceExtensionAbility { 190 build() { 191 Column() { 192 //... 193 List({ initialIndex: 0 }) { 194 ListItem() { 195 Row() { 196 //... 197 } 198 .onClick(() => { 199 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; // UIAbilityContext 200 let want: Want = { 201 deviceId: '', 202 bundleName: 'com.samples.stagemodelabilitydevelop', 203 abilityName: 'AppServiceExtAbility' 204 }; 205 context.stopAppServiceExtensionAbility(want).then(() => { 206 hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in stopping AppServiceExtensionAbility.'); 207 this.getUIContext().getPromptAction().showToast({ 208 message: 'SuccessfullyStoppedAStartedBackendService' 209 }); 210 }).catch((err: BusinessError) => { 211 hilog.error(DOMAIN_NUMBER, TAG, 212 `Failed to stop AppServiceExtensionAbility. Code is ${err.code}, message is ${err.message}`); 213 }); 214 }) 215 } 216 217 //... 218 } 219 220 //... 221 } 222 223 //... 224 } 225 } 226 ``` 227 228- Enable the [AppServiceExtensionAbility](../reference/apis-ability-kit/js-apis-app-ability-appServiceExtensionAbility.md) to stop itself. 229 230 ```ts 231 import { AppServiceExtensionAbility } from '@kit.AbilityKit'; 232 import { BusinessError } from '@kit.BasicServicesKit'; 233 import { hilog } from '@kit.PerformanceAnalysisKit'; 234 235 const TAG: string = '[AppServiceExtensionAbility]'; 236 237 export default class AppServiceExtension extends AppServiceExtensionAbility { 238 onCreate() { 239 // Execute the service logic. 240 this.context.terminateSelf().then(() => { 241 hilog.info(0x0000, TAG, '----------- terminateSelf succeed -----------'); 242 }).catch((error: BusinessError) => { 243 hilog.error(0x0000, TAG, `terminateSelf failed, error.code: ${error.code}, error.message: $ {error.message}`); 244 }); 245 } 246 } 247 ``` 248 249### Connecting to a Background Service 250 251The client can connect to a background service (specified in the Want object) through [connectAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#connectappserviceextensionability20). The [onConnect()](../reference/apis-ability-kit/js-apis-app-ability-appServiceExtensionAbility.md#onconnect) callback is invoked, through which the background service receives the [Want](../reference/apis-ability-kit/js-apis-app-ability-want.md) object passed by the client. In this way, a persistent connection is established. 252 253The AppServiceExtensionAbility returns an [IRemoteObject](../reference/apis-ipc-kit/js-apis-rpc.md#iremoteobject) object in [onConnect()](../reference/apis-ability-kit/js-apis-inner-ability-connectOptions.md#onconnect). This object is then delivered as an input parameter to the client's [onConnect()](../reference/apis-ability-kit/js-apis-inner-ability-connectOptions.md#onconnect). Through this IRemoteObject, you can define communication interfaces for RPC interaction between the client and server. Multiple clients can simultaneously connect to the same background service. After a client finishes the interaction, it must call [disconnectAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#disconnectappserviceextensionability20) to disconnect from the service. If all clients connected to a background service are disconnected, the system destroys the service. 254 255- Call [connectAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#connectappserviceextensionability20) to establish a connection to a background service. For details about how to obtain the context, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability). 256 257 ```ts 258 import { common, Want } from '@kit.AbilityKit'; 259 import { rpc } from '@kit.IPCKit'; 260 import { hilog } from '@kit.PerformanceAnalysisKit'; 261 262 const TAG: string = '[Page_AppServiceExtensionAbility]'; 263 const DOMAIN_NUMBER: number = 0xFF00; 264 265 let connectionId: number; 266 let want: Want = { 267 deviceId: '', 268 bundleName: 'com.samples.stagemodelabilitydevelop', 269 abilityName: 'AppServiceExtAbility' 270 }; 271 272 let options: common.ConnectOptions = { 273 onConnect(elementName, remote: rpc.IRemoteObject): void { 274 hilog.info(DOMAIN_NUMBER, TAG, 'onConnect callback'); 275 if (remote === null) { 276 hilog.info(DOMAIN_NUMBER, TAG, `onConnect remote is null`); 277 return; 278 } 279 // Use remote for communication. 280 }, 281 onDisconnect(elementName): void { 282 hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback'); 283 }, 284 onFailed(code: number): void { 285 hilog.info(DOMAIN_NUMBER, TAG, 'onFailed callback', JSON.stringify(code)); 286 } 287 }; 288 289 @Entry 290 @Component 291 struct Page_AppServiceExtensionAbility { 292 build() { 293 Column() { 294 //... 295 List({ initialIndex: 0 }) { 296 ListItem() { 297 Row() { 298 //... 299 } 300 .onClick(() => { 301 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; // UIAbilityContext 302 // Save the connection ID, which will be used when the background service is disconnected. 303 connectionId = context.connectAppServiceExtensionAbility(want, options); 304 // The background service is connected. 305 this.getUIContext().getPromptAction().showToast({ 306 message: 'SuccessfullyConnectBackendService' 307 }); 308 hilog.info(DOMAIN_NUMBER, TAG, `connectionId is : ${connectionId}`); 309 }) 310 } 311 312 //... 313 } 314 315 //... 316 } 317 318 //... 319 } 320 } 321 ``` 322 323- Use [disconnectAppServiceExtensionAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#disconnectappserviceextensionability20) to disconnect from the background service. 324 325 ```ts 326 import { common } from '@kit.AbilityKit'; 327 import { hilog } from '@kit.PerformanceAnalysisKit'; 328 import { BusinessError } from '@kit.BasicServicesKit'; 329 330 const TAG: string = '[Page_AppServiceExtensionAbility]'; 331 const DOMAIN_NUMBER: number = 0xFF00; 332 333 let connectionId: number; 334 335 @Entry 336 @Component 337 struct Page_AppServiceExtensionAbility { 338 build() { 339 Column() { 340 //... 341 List({ initialIndex: 0 }) { 342 ListItem() { 343 Row() { 344 //... 345 } 346 .onClick(() => { 347 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; // UIAbilityContext 348 // connectionId is returned when connectServiceExtensionAbility is called and needs to be manually maintained. 349 context.disconnectAppServiceExtensionAbility(connectionId).then(() => { 350 hilog.info(DOMAIN_NUMBER, TAG, 'disconnectAppServiceExtensionAbility success'); 351 // The background service is disconnected. 352 this.getUIContext().getPromptAction().showToast({ 353 message: 'SuccessfullyDisconnectBackendService' 354 }); 355 }).catch((error: BusinessError) => { 356 hilog.error(DOMAIN_NUMBER, TAG, 'disconnectAppServiceExtensionAbility failed'); 357 }); 358 }) 359 } 360 361 //... 362 } 363 364 //... 365 } 366 367 //... 368 } 369 } 370 ``` 371 372## Communication Between the Client and Server 373 374After obtaining the [rpc.IRemoteObject](../reference/apis-ipc-kit/js-apis-rpc.md#iremoteobject) from the [onConnect()](../reference/apis-ability-kit/js-apis-inner-ability-connectOptions.md#onconnect) lifecycle callback, the client can communicate with the AppServiceExtensionAbility. 375 376Call [sendMessageRequest](../reference/apis-ipc-kit/js-apis-rpc.md#sendmessagerequest9) to send messages to the server. 377 378```ts 379import { common } from '@kit.AbilityKit'; 380import { rpc } from '@kit.IPCKit'; 381import { hilog } from '@kit.PerformanceAnalysisKit'; 382import { BusinessError } from '@kit.BasicServicesKit'; 383 384const TAG: string = '[Page_CollaborateAbility]'; 385const DOMAIN_NUMBER: number = 0xFF00; 386const REQUEST_CODE = 1; 387let options: common.ConnectOptions = { 388 onConnect(elementName, remote): void { 389 hilog.info(DOMAIN_NUMBER, TAG, 'onConnect callback'); 390 if (remote === null) { 391 hilog.info(DOMAIN_NUMBER, TAG, `onConnect remote is null`); 392 return; 393 } 394 let option = new rpc.MessageOption(); 395 let data = new rpc.MessageSequence(); 396 let reply = new rpc.MessageSequence(); 397 398 data.writeInt(99); 399 // You can send data to the target application for corresponding operations. 400 // @param code Indicates the service request code sent by the client. 401 // @param data Indicates the {@link MessageSequence} object sent by the client. 402 // @param reply Indicates the response message object sent by the remote service. 403 // @param options Specifies whether the operation is synchronous or asynchronous. 404 // @return Returns {@code true} if the operation is successful; returns {@code false} otherwise. 405 406 remote.sendMessageRequest(REQUEST_CODE, data, reply, option).then((ret: rpc.RequestResult) => { 407 let errCode = reply.readInt(); // Receive the information (100) returned by the target device if the connection is successful. 408 let msg: number = 0; 409 if (errCode === 0) { 410 msg = reply.readInt(); 411 } 412 // The background service is connected. 413 hilog.info(DOMAIN_NUMBER, TAG, `sendRequest success, msg:${msg}`); 414 }).catch((error: BusinessError) => { 415 hilog.info(DOMAIN_NUMBER, TAG, `sendRequest failed, ${JSON.stringify(error)}`); 416 }); 417 }, 418 onDisconnect(elementName): void { 419 hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback'); 420 }, 421 onFailed(code): void { 422 hilog.info(DOMAIN_NUMBER, TAG, 'onFailed callback'); 423 } 424}; 425// Call the code related to connectAppServiceExtension. 426``` 427 428## Client Identity Verification by the Server 429 430If your AppServiceExtensionAbility provides sensitive operations, verify the client's identity with one of the following approaches. 431 432<!--Del--> 433### Verifying the Client Identity Based on callerUid 434 435Call [getCallingUid()](../reference/apis-ipc-kit/js-apis-rpc.md#getcallinguid) to obtain the UID of the client, and then call [getBundleNameByUid()](../reference/apis-ability-kit/js-apis-bundleManager-sys.md#bundlemanagergetbundlenamebyuid14) to obtain the corresponding bundle name. In this way, the client identity is verified. Note that [getBundleNameByUid()](../reference/apis-ability-kit/js-apis-bundleManager-sys.md#bundlemanagergetbundlenamebyuid14) is asynchronous, and therefore the server cannot return the verification result to the client. This verification mode applies when the client sends an asynchronous task request to the server. The sample code is as follows: 436 437```ts 438import { AppServiceExtensionAbility } from '@kit.AbilityKit'; 439import { bundleManager } from '@kit.AbilityKit'; 440import { rpc } from '@kit.IPCKit'; 441import { hilog } from '@kit.PerformanceAnalysisKit'; 442import { BusinessError } from '@kit.BasicServicesKit'; 443 444const TAG: string = "[AppServiceExtImpl]"; 445const DOMAIN_NUMBER: number = 0xFF00; 446 447// You need to implement APIs in this class. 448class Stub extends rpc.RemoteObject { 449 onRemoteMessageRequest( 450 code: number, 451 data: rpc.MessageSequence, 452 reply: rpc.MessageSequence, 453 options: rpc.MessageOption): boolean | Promise<boolean> { 454 // Implement service logic. 455 let callerUid = rpc.IPCSkeleton.getCallingUid(); 456 bundleManager.getBundleNameByUid(callerUid).then((callerBundleName) => { 457 hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid: ' + callerBundleName); 458 // Identify the bundle name of the client. 459 if (callerBundleName !== 'com.samples.stagemodelabilitydevelop') { // The verification fails. 460 hilog.info(DOMAIN_NUMBER, TAG, 'The caller bundle is not in trustlist, reject'); 461 return; 462 } 463 // The verification is successful, and service logic is executed normally. 464 }).catch((err: BusinessError) => { 465 hilog.error(DOMAIN_NUMBER, TAG, 'getBundleNameByUid failed: ' + err.message); 466 }); 467 return true; 468 } 469} 470 471export default class AppServiceExtension extends AppServiceExtensionAbility { 472 onConnect(want: Want): rpc.RemoteObject { 473 return new Stub('test'); 474 } 475 // Other lifecycle states. 476} 477``` 478<!--DelEnd--> 479 480### Verifying the Client Identity Based on callerTokenId 481 482Call [getCallingTokenId()](../reference/apis-ipc-kit/js-apis-rpc.md#getcallingtokenid8) to obtain the token ID of the client, and then call [verifyAccessTokenSync()](../reference/apis-ability-kit/js-apis-abilityAccessCtrl.md#verifyaccesstokensync9) to check whether the client has the required permission. Currently, the system does not support permission customization. Therefore, only [system-defined permissions](../security/AccessToken/app-permissions.md) can be verified. The sample code is as follows: 483 484```ts 485import { AppServiceExtensionAbility } from '@kit.AbilityKit'; 486import { abilityAccessCtrl, bundleManager } from '@kit.AbilityKit'; 487import { rpc } from '@kit.IPCKit'; 488import { hilog } from '@kit.PerformanceAnalysisKit'; 489import { BusinessError } from '@kit.BasicServicesKit'; 490 491const TAG: string = '[AppServiceExtImpl]'; 492const DOMAIN_NUMBER: number = 0xFF00; 493 494// You need to implement APIs in this class. 495 496class Stub extends rpc.RemoteObject { 497 onRemoteMessageRequest( 498 code: number, 499 data: rpc.MessageSequence, 500 reply: rpc.MessageSequence, 501 options: rpc.MessageOption): boolean | Promise<boolean> { 502 // Implement service logic. 503 hilog.info(DOMAIN_NUMBER, TAG, `onRemoteMessageRequest: ${data}`); 504 let callerUid = rpc.IPCSkeleton.getCallingUid(); 505 bundleManager.getBundleNameByUid(callerUid).then((callerBundleName) => { 506 hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid: ' + callerBundleName); 507 // Identify the bundle name of the client. 508 if (callerBundleName !== 'com.samples.stagemodelabilitydevelop') { // The verification fails. 509 hilog.info(DOMAIN_NUMBER, TAG, 'The caller bundle is not in trustlist, reject'); 510 return; 511 } 512 // The verification is successful, and service logic is executed normally. 513 }).catch((err: BusinessError) => { 514 hilog.error(DOMAIN_NUMBER, TAG, 'getBundleNameByUid failed: ' + err.message); 515 }); 516 517 let callerTokenId = rpc.IPCSkeleton.getCallingTokenId(); 518 let accessManger = abilityAccessCtrl.createAtManager(); 519 // The permission to be verified varies depending on the service requirements. ohos.permission.GET_BUNDLE_INFO_PRIVILEGED is only an example. 520 let grantStatus = accessManger.verifyAccessTokenSync(callerTokenId, 'ohos.permission.GET_BUNDLE_INFO_PRIVILEGED'); 521 if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) { 522 hilog.error(DOMAIN_NUMBER, TAG, 'PERMISSION_DENIED'); 523 return false; 524 } 525 hilog.info(DOMAIN_NUMBER, TAG, 'verify access token success.'); 526 return true; 527 } 528} 529 530export default class AppServiceExtension extends AppServiceExtensionAbility { 531 onConnect(want: Want): rpc.RemoteObject { 532 return new Stub('test'); 533 } 534 // Other lifecycle states. 535} 536``` 537