1# Facial Authentication 2 3## Overview 4 5### Function 6 7Facial authentication provides user authentication capabilities in identity authentication scenarios, such as device unlocking, payment, and app logins. It uses biometric recognition technologies to identify individuals based on facial characteristics. A camera is used to collect images or video streams that contain human faces, and automatically detect, track, and recognize human faces. Facial authentication is also called facial recognition. The figure below shows the architecture of facial authentication. 8 9The face authentication (Face_auth) driver is developed based on the Hardware Driver Foundation (HDF). It shields hardware differences and provides stable facial authentication capabilities for the user authentication framework (User_auth) and Face_auth service. The facial authentication capabilities include obtaining facial recognition executor list, executor information, and template information by template ID, comparing face image template information of the executor and that of User_auth, enrolling or deleting face images, and performing facial authentication. 10 11**Figure 1** Facial authentication architecture 12 13 14 15### Basic Concepts 16 17The identity authentication consists of User_auth and basic authentication services (including PIN authentication and facial authentication). It supports basic functions such as setting and deleting user credentials and performing authentication. The system supports user identity authentication and data collection, processing, storage, and comparison. 18- Executor 19 20 The executor collects, processes, stores, and compares data for authentication. Each authentication service provides the executor capabilities, which are scheduled by User_auth to implement basic capabilities. 21 22- Executor security level 23 24 Security level of the runtime environment when an executor provides capabilities. 25 26- Executor role 27 28 - Executor: independently completes the entire process of credential registration and identity authentication. The executor can collect, process, store, and compare data to complete the authentication. 29 30 - Collector: only collects data during user authentication. It needs to work with the authenticator to complete user authentication. 31 32 - Authenticator: only processes data, obtains the stored credential template, and compares it with the authentication information generated. 33 34- Executor type 35 36 The authentication algorithm varies depending on the authentication mode and device used. Different executor types are defined based on the supported algorithm type or the device in use. 37 38- User_auth public key & executor public key 39 40 To ensure user data security and authentication result accuracy, measures must be taken to protect the integrity of the key information exchanged between User_auth and basic authentication services. Public keys must be exchanged when the executor provided by a basic authentication service interworks with User_auth. 41 42 The executor uses the User_auth public key to verify scheduling instructions. 43 44 User_auth uses the executor public key to verify the authentication result accuracy and the integrity of the information exchanged with the executor. 45 46- Authentication credential template 47 48 Authentication credentials are generated and stored by the authentication service when users set authentication credentials. Each template has an ID to index a set of template information files. The template information needs to be compared with the authentication data generated during authentication to complete identity authentication. 49 50- Data verification by the executor 51 52 User_auth manages the mappings between user identities and credential IDs in a unified manner. When connecting to User_auth, the executor obtains the template ID list from User_auth and updates its template ID list based on the template ID list obtained. 53 54- HAPs 55 56 In a broad sense, Harmony Ability Packages (HAPs) are application packages that can be installed on OpenHarmony. In this document, the HAPs only refer to the upper-layer applications of the Face_auth driver. 57 58- IDL interface 59 60 An Interface Definition Language (IDL) is a language that lets a program or object written in one language communicate with another program written in an unknown language. An IDL compiler generates client stub files and server framework files. This document describes how to use the client and server generated by the IDL interface to implement communication between the Face_auth service and driver. For details, see [IDL](https://gitee.com/openharmony/ability_idl_tool/blob/master/README.md). 61 62- IPC 63 64 Inter-process communication (IPC) implements data exchange between two processes. For details, see [IPC](https://gitee.com/openharmony/communication_ipc/blob/master/README.md). 65 66- HDI 67 68 The hardware device interface (HDI) is located between the basic system service layer and the device driver layer. It provides APIs for abstracting hardware device functions, which shields underlying hardware device differences for system services. For details, see [HDI Specifications](../../design/hdi-design-specifications.md). 69 70### Working Principles 71 72The Face_auth driver provides basic facial authentication capabilities for the User_auth and Face_auth service to ensure successful facial authentication. 73You can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use. 74 75**Figure 2** Face_auth service and Face_auth driver interaction 76 77 78 79### Constraints 80 81- To implement facial authentication, the device must have a camera and the face image must be greater than 100 x 100 pixels. 82- A Trusted Execution Environment (TEE) must be available, and facial feature information must be encrypted and stored in a TEE. 83- The face matching accuracy varies with people with similar looks and children whose facial features keep changing. If you are concerned about this, consider using other authentication modes. 84 85## Development Guidelines 86 87### When to Use 88 89The Face_auth driver provides basic facial authentication capabilities for the User_auth and Face_auth service to ensure successful facial authentication. 90 91### Available APIs 92 93The following table describes the C++ APIs generated from the Interface Definition Language (IDL) interface description. For details about the interface declaration, see the .idl file in **/drivers/interface/face_auth/**. 94 95**Table 1** describes the HDI APIs for face credential enrollment, authentication, recognition, and deletion. **Table 2** describes the callbacks used to return the executor operation result to the framework or return the authentication tip information to upper-layer applications. 96 97**Table 1** Available APIs 98 99| API | Description | 100| ----------------------------------- | ---------------------------------- | 101| GetExecutorList(std::vector\<sptr\<IAllInOneExecutor>>& allInOneExecutors) | Obtains the executor list of V2_0. | 102| GetExecutorInfo(ExecutorInfo& info) | Obtains the executor information, including the executor type, executor role, authentication type, security level, and executor public key. | 103| OnRegisterFinish(const std::vector\<uint64_t>& templateIdList,<br> const std::vector\<uint8_t>& frameworkPublicKey, const std::vector\<uint8_t>& extraInfo) | Obtains the public key and template ID list from User_auth after the executor is registered successfully. | 104| Enroll(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br> const sptr\<IExecutorCallback>& callbackObj) | Enrolls a face image template. | 105| Authenticate(uint64_t scheduleId, const std::vector\<uint64_t>& templateIdList,<br> const std::vector\<uint8_t>& extraInfo, const sptr\<IExecutorCallback>& callbackObj) | Performs facial authentication. | 106| Identify(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br> const sptr\<IExecutorCallback>& callbackObj) | Performs facial identification. | 107| Delete(const std::vector\<uint64_t>& templateIdList) | Deletes a face image template. | 108| Cancel(uint64_t scheduleId) | Cancels a face enrollment, authentication, or identification operation based on the **scheduleId**. | 109| SendCommand(int32_t commandId, const std::vector\<uint8_t>& extraInfo,<br> const sptr\<IExecutorCallback>& callbackObj) | Sends commands to the Face_auth service. | 110| SetBufferProducer(const sptr\<BufferProducerSequenceable> &bufferProducer) | Sets the preview stream buffer. | 111| GetProperty(const std::vector\<uint64_t>& templateIdList,<br>const std::vector\<int32_t>& propertyTypes, Property& property) | Obtains executor property information. | 112| SetCachedTemplates(const std::vector\<uint64_t> &templateIdList) | Sets a list of templates to be cached. | 113| RegisterSaCommandCallback(const sptr\<ISaCommandCallback> &callbackObj) | Registers a callback to be invoked when an SA command is executed. | 114 115**Table 2** Callbacks 116 117| API | Description | 118| ------------------------------------------------------------ | ------------------------ | 119| ExecutorCallbackService::OnResult(int32_t result, const std::vector\<uint8_t>& extraInfo) | Called to return the operation result. | 120| ExecutorCallbackService::OnTip(int32_t tip, const std::vector\<uint8_t>& extraInfo) | Called to return the interaction information about the operation process. | 121| SaCommandCallbackService::OnSaCommands(const std::vector\<SaCommand>& commands) | Called to send the command list. | 122 123### How to Develop 124 125The following uses the Hi3516D V300 development board as an example to demonstrate how to develop the Face_auth driver. <br/>The directory structure is as follows: 126 127```undefined 128// drivers/peripheral/face_auth 129├── BUILD.gn # Build script 130├── bundle.json # Component description file 131└── hdi_service # Face_auth driver implementation 132 ├── BUILD.gn # Build script 133 ├── include # Header files 134 └── src # Source files 135 ├── executor_impl.cpp # Implementation of authentication and enrollment APIs 136 ├── face_auth_interface_driver.cpp # Face_auth driver entry 137 └── face_auth_interface_service.cpp # Implementation of the APIs for obtaining the executor list 138``` 139 140The development procedure is as follows: 141 1421. Develop the Face_auth driver based on the HDF. The **Bind()**, **Init()**, **Release()**, and **Dispatch()** functions are used. For details about the code, see [face_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/face_auth_interface_driver.cpp). 143 144 ```c++ 145 // Create an IRemoteObject object by using the custom HdfFaceAuthInterfaceHost object, which consists of the IoService object and HDI service. 146 struct HdfFaceAuthInterfaceHost { 147 struct IDeviceIoService ioService; 148 OHOS::sptr<OHOS::IRemoteObject> stub; 149 }; 150 151 // Enable the IPC service to call the response API. 152 int32_t FaceAuthInterfaceDriverDispatch( 153 struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply) 154 { 155 IAM_LOGI("start"); 156 if (client == nullptr || data == nullptr || reply == nullptr || client->device == nullptr || 157 client->device->service == nullptr) { 158 IAM_LOGE("invalid param"); 159 return HDF_ERR_INVALID_PARAM; 160 } 161 162 auto *hdfFaceAuthInterfaceHost = CONTAINER_OF(client->device->service, struct HdfFaceAuthInterfaceHost, ioService); 163 if (hdfFaceAuthInterfaceHost == nullptr || hdfFaceAuthInterfaceHost->stub == nullptr) { 164 IAM_LOGE("hdfFaceAuthInterfaceHost is invalid"); 165 return HDF_ERR_INVALID_PARAM; 166 } 167 168 OHOS::MessageParcel *dataParcel = nullptr; 169 OHOS::MessageParcel *replyParcel = nullptr; 170 OHOS::MessageOption option; 171 172 if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { 173 IAM_LOGE("invalid data sbuf object to dispatch"); 174 return HDF_ERR_INVALID_PARAM; 175 } 176 if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { 177 IAM_LOGE("invalid reply sbuf object to dispatch"); 178 return HDF_ERR_INVALID_PARAM; 179 } 180 181 return hdfFaceAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); 182 } 183 184 // Initialize the HdfFaceAuthInterfaceDriver object. 185 int HdfFaceAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) 186 { 187 IAM_LOGI("start"); 188 if (deviceObject == nullptr) { 189 IAM_LOGE("deviceObject is nullptr"); 190 return HDF_ERR_INVALID_PARAM; 191 } 192 if (!HdfDeviceSetClass(deviceObject, DEVICE_CLASS_USERAUTH)) { 193 IAM_LOGE("set face auth hdf class failed"); 194 return HDF_FAILURE; 195 } 196 return HDF_SUCCESS; 197 } 198 199 // Bind the service provided by the Face_auth driver to the HDF. 200 int HdfFaceAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) 201 { 202 IAM_LOGI("start"); 203 if (deviceObject == nullptr) { 204 IAM_LOGE("deviceObject is nullptr"); 205 return HDF_ERR_INVALID_PARAM; 206 } 207 auto *hdfFaceAuthInterfaceHost = new (std::nothrow) HdfFaceAuthInterfaceHost; 208 if (hdfFaceAuthInterfaceHost == nullptr) { 209 IAM_LOGE("failed to create HdfFaceAuthInterfaceHost object"); 210 return HDF_FAILURE; 211 } 212 213 hdfFaceAuthInterfaceHost->ioService.Dispatch = FaceAuthInterfaceDriverDispatch; 214 hdfFaceAuthInterfaceHost->ioService.Open = NULL; 215 hdfFaceAuthInterfaceHost->ioService.Release = NULL; 216 217 auto serviceImpl = IFaceAuthInterface::Get(true); 218 if (serviceImpl == nullptr) { 219 IAM_LOGE("failed to get of implement service"); 220 delete hdfFaceAuthInterfaceHost; 221 return HDF_FAILURE; 222 } 223 224 hdfFaceAuthInterfaceHost->stub = 225 OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, IFaceAuthInterface::GetDescriptor()); 226 if (hdfFaceAuthInterfaceHost->stub == nullptr) { 227 IAM_LOGE("failed to get stub object"); 228 delete hdfFaceAuthInterfaceHost; 229 return HDF_FAILURE; 230 } 231 232 deviceObject->service = &hdfFaceAuthInterfaceHost->ioService; 233 IAM_LOGI("success"); 234 return HDF_SUCCESS; 235 } 236 237 // Release resources of the Face_auth driver. 238 void HdfFaceAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject) 239 { 240 IAM_LOGI("start"); 241 if (deviceObject == nullptr || deviceObject->service == nullptr) { 242 IAM_LOGE("deviceObject is invalid"); 243 return; 244 } 245 auto *hdfFaceAuthInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfFaceAuthInterfaceHost, ioService); 246 if (hdfFaceAuthInterfaceHost == nullptr) { 247 IAM_LOGE("hdfFaceAuthInterfaceHost is nullptr"); 248 return; 249 } 250 delete hdfFaceAuthInterfaceHost; 251 IAM_LOGI("success"); 252 } 253 254 // Register the entry data structure object of the Face_auth driver. 255 struct HdfDriverEntry g_faceAuthInterfaceDriverEntry = { 256 .moduleVersion = 1, 257 .moduleName = "drivers_peripheral_face_auth", 258 .Bind = HdfFaceAuthInterfaceDriverBind, 259 .Init = HdfFaceAuthInterfaceDriverInit, 260 .Release = HdfFaceAuthInterfaceDriverRelease, 261 }; 262 263 // Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls the Bind() function and then the Init() function. If the Init() function fails to be called, the HDF will call Release() to release driver resources and exit the driver model. 264 HDF_INIT(g_faceAuthInterfaceDriverEntry); 265 ``` 266 2672. Implement the APIs for obtaining the executor list. For details about the code, see [face_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/face_auth_interface_service.cpp). 268 269 ```c++ 270 // Executor implementation class 271 class AllInOneExecutorImpl : public IAllInOneExecutor { 272 public: 273 AllInOneExecutorImpl(struct ExecutorInfo executorInfo); 274 virtual ~AllInOneExecutorImpl() {} 275 276 private: 277 struct ExecutorInfo executorInfo_; // Executor information 278 }; 279 280 static constexpr uint16_t SENSOR_ID = 123; // Executor sensor ID 281 static constexpr uint32_t EXECUTOR_TYPE = 123; // Executor type 282 static constexpr size_t PUBLIC_KEY_LEN = 32; //32-byte public key of the executor 283 284 // Create an HDI service object. 285 extern "C" IFaceAuthInterface *FaceAuthInterfaceImplGetInstance(void) 286 { 287 auto faceAuthInterfaceService = new (std::nothrow) FaceAuthInterfaceService(); 288 if (faceAuthInterfaceService == nullptr) { 289 IAM_LOGE("faceAuthInterfaceService is nullptr"); 290 return nullptr; 291 } 292 return faceAuthInterfaceService; 293 } 294 295 // Obtain the executor list of V2_0. 296 int32_t GetExecutorList(std::vector<sptr<IAllInOneExecutor>> &executorList) 297 { 298 IAM_LOGI("interface mock start"); 299 for (auto executor : executorList_) { 300 executorList.push_back(executor); 301 } 302 IAM_LOGI("interface mock success"); 303 return HDF_SUCCESS; 304 } 305 ``` 306 3073. Implement each function of the executor. For details about the code, see [all_in_one_executor_impl.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/all_in_one_executor_impl.cpp). 308 309 ```c++ 310 // Obtain the executor information. 311 int32_t AllInOneExecutorImpl::GetExecutorInfo(ExecutorInfo &executorInfo) 312 { 313 IAM_LOGI("interface mock start"); 314 executorInfo = executorInfo_; 315 IAM_LOGI("get executor information success"); 316 return HDF_SUCCESS; 317 } 318 319 // After the executor is successfully registered, obtain the public key and template ID list from User_auth and save the public key. The executor compares its template ID list with the template ID list obtained and updates its template ID list. 320 int32_t AllInOneExecutorImpl::OnRegisterFinish(const std::vector<uint64_t> &templateIdList, 321 const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo) 322 { 323 IAM_LOGI("interface mock start"); 324 static_cast<void>(templateIdList); 325 static_cast<void>(extraInfo); 326 static_cast<void>(frameworkPublicKey); 327 IAM_LOGI("register finish"); 328 return HDF_SUCCESS; 329 } 330 331 // Enroll a face image. 332 int32_t AllInOneExecutorImpl::Enroll( 333 uint64_t scheduleId, const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) 334 { 335 IAM_LOGI("interface mock start"); 336 static_cast<void>(scheduleId); 337 static_cast<void>(extraInfo); 338 if (callbackObj == nullptr) { 339 IAM_LOGE("callbackObj is nullptr"); 340 return HDF_ERR_INVALID_PARAM; 341 } 342 IAM_LOGI("enroll, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT); 343 int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); 344 if (ret != HDF_SUCCESS) { 345 IAM_LOGE("callback result is %{public}d", ret); 346 return HDF_FAILURE; 347 } 348 return HDF_SUCCESS; 349 } 350 351 // Start facial authentication. 352 int32_t AllInOneExecutorImpl::Authenticate(uint64_t scheduleId, const std::vector<uint64_t> &templateIdList, 353 const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) 354 { 355 IAM_LOGI("interface mock start"); 356 static_cast<void>(scheduleId); 357 static_cast<void>(templateIdList); 358 static_cast<void>(extraInfo); 359 if (callbackObj == nullptr) { 360 IAM_LOGE("callbackObj is nullptr"); 361 return HDF_ERR_INVALID_PARAM; 362 } 363 IAM_LOGI("authenticate, result is %{public}d", ResultCode::NOT_ENROLLED); 364 int32_t ret = callbackObj->OnResult(ResultCode::NOT_ENROLLED, {}); 365 if (ret != HDF_SUCCESS) { 366 IAM_LOGE("callback result is %{public}d", ret); 367 return HDF_FAILURE; 368 } 369 return HDF_SUCCESS; 370 } 371 372 // Perform facial recognition. 373 int32_t AllInOneExecutorImpl::Identify( 374 uint64_t scheduleId, const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) 375 { 376 IAM_LOGI("interface mock start"); 377 static_cast<void>(scheduleId); 378 static_cast<void>(extraInfo); 379 if (callbackObj == nullptr) { 380 IAM_LOGE("callbackObj is nullptr"); 381 return HDF_ERR_INVALID_PARAM; 382 } 383 IAM_LOGI("identify, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT); 384 int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); 385 if (ret != HDF_SUCCESS) { 386 IAM_LOGE("callback result is %{public}d", ret); 387 return HDF_FAILURE; 388 } 389 return HDF_SUCCESS; 390 } 391 392 // Delete the face image template. 393 int32_t AllInOneExecutorImpl::Delete(const std::vector<uint64_t> &templateIdList) 394 { 395 IAM_LOGI("interface mock start"); 396 static_cast<void>(templateIdList); 397 IAM_LOGI("delete success"); 398 return HDF_SUCCESS; 399 } 400 401 // Cancel the operation based on the specified scheduleId. 402 int32_t AllInOneExecutorImpl::Cancel(uint64_t scheduleId) 403 { 404 IAM_LOGI("interface mock start"); 405 static_cast<void>(scheduleId); 406 IAM_LOGI("cancel success"); 407 return HDF_SUCCESS; 408 } 409 410 // Send template locking or unlocking command from the Face_auth service to the Face_auth driver. 411 int32_t AllInOneExecutorImpl::SendCommand( 412 int32_t commandId, const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) 413 { 414 IAM_LOGI("interface mock start"); 415 static_cast<void>(extraInfo); 416 if (callbackObj == nullptr) { 417 IAM_LOGE("callbackObj is nullptr"); 418 return HDF_ERR_INVALID_PARAM; 419 } 420 int32_t ret; 421 switch (commandId) { 422 case DriverCommandId::LOCK_TEMPLATE: 423 IAM_LOGI("lock template, result is %{public}d", ResultCode::SUCCESS); 424 ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); 425 if (ret != HDF_SUCCESS) { 426 IAM_LOGE("callback result is %{public}d", ret); 427 return HDF_FAILURE; 428 } 429 break; 430 case DriverCommandId::UNLOCK_TEMPLATE: 431 IAM_LOGI("unlock template, result is %{public}d", ResultCode::SUCCESS); 432 ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); 433 if (ret != HDF_SUCCESS) { 434 IAM_LOGE("callback result is %{public}d", ret); 435 return HDF_FAILURE; 436 } 437 break; 438 case DriverCommandId::INIT_ALGORITHM: 439 IAM_LOGI("init algorithm, result is %{public}d", ResultCode::SUCCESS); 440 ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); 441 if (ret != HDF_SUCCESS) { 442 IAM_LOGE("callback result is %{public}d", ret); 443 return HDF_FAILURE; 444 } 445 break; 446 default: 447 IAM_LOGD("not support DriverCommandId : %{public}d", commandId); 448 ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); 449 if (ret != HDF_SUCCESS) { 450 IAM_LOGE("callback result is %{public}d", ret); 451 return HDF_FAILURE; 452 } 453 } 454 return HDF_SUCCESS; 455 } 456 457 // Set the preview stream buffer. 458 int32_t FaceAuthInterfaceService::SetBufferProducer(const sptr<BufferProducerSequenceable> &bufferProducer) 459 { 460 IAM_LOGI("interface mock start set buffer producer %{public}s", 461 UserIam::Common::GetPointerNullStateString(bufferProducer.GetRefPtr()).c_str()); 462 return HDF_SUCCESS; 463 } 464 465 // Obtaining executor properties. 466 int32_t AllInOneExecutorImpl::GetProperty( 467 const std::vector<uint64_t> &templateIdList, const std::vector<int32_t> &propertyTypes, Property &property) 468 { 469 IAM_LOGI("interface mock start"); 470 property = {}; 471 IAM_LOGI("get property success"); 472 return HDF_SUCCESS; 473 } 474 475 // Set a list of templates to be cached. 476 int32_t AllInOneExecutorImpl::SetCachedTemplates(const std::vector<uint64_t> &templateIdList) 477 { 478 IAM_LOGI("interface mock start"); 479 IAM_LOGI("set cached templates success"); 480 return HDF_SUCCESS; 481 } 482 483 // Register the callback to be invoked when the SA command is executed. 484 int32_t AllInOneExecutorImpl::RegisterSaCommandCallback(const sptr<ISaCommandCallback> &callbackObj) 485 { 486 IAM_LOGI("interface mock start"); 487 IAM_LOGI("register sa command callback success"); 488 return HDF_SUCCESS; 489 } 490 ``` 491 4924. Modify **serviceName2Config** in the **face_auth_service.cpp** file if you need to add a driver or modify driver information. 493 494 ```c++ 495 // base/user_iam/face_auth/services/src/face_auth_service.cpp 496 void FaceAuthService::StartDriverManager() 497 { 498 IAM_LOGI("start"); 499 int32_t ret = UserAuth::IDriverManager::Start(HDI_NAME_2_CONFIG); 500 if (ret != FACE_AUTH_SUCCESS) { 501 IAM_LOGE("start driver manager failed"); 502 } 503 } 504 ``` 505 506### Verification 507 508Use the [User Authentication APIs](../../application-dev/reference/apis-user-authentication-kit/js-apis-useriam-userauth.md) to develop a HAP and verify the application on the RK3568 platform. The sample code for starting and canceling an authentication is as follows: 509 5101. Initiate a request for user authentication and obtain the authentication result. 511 512```ts 513 // API version 10 514 import type {BusinessError} from '@ohos.base'; 515 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 516 517 // Set authentication parameters. 518 const authParam: userIAM_userAuth.AuthParam = { 519 challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), 520 authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FACE], 521 authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, 522 }; 523 524 // Set the authentication page. 525 const widgetParam: userIAM_userAuth.WidgetParam = { 526 title: 'Verify identity', 527 }; 528 529 try { 530 // Obtain an authentication object. 531 let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); 532 console.info('get userAuth instance success'); 533 // Subscribe to the authentication result. 534 userAuthInstance.on('result', { 535 onResult(result) { 536 console.info(`userAuthInstance callback result: ${JSON.stringify(result)}`); 537 // Unsubscribe from the authentication result if required. 538 userAuthInstance.off('result'); 539 } 540 }); 541 console.info('auth on success'); 542 userAuthInstance.start(); 543 console.info('auth start success'); 544 } catch (error) { 545 const err: BusinessError = error as BusinessError; 546 console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); 547 } 548``` 549 5502. Cancel an authentication. 551```ts 552 // API version 10 553 import type {BusinessError} from '@ohos.base'; 554 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 555 556 const authParam: userIAM_userAuth.AuthParam = { 557 challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), 558 authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FACE], 559 authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, 560 }; 561 562 const widgetParam: userIAM_userAuth.WidgetParam = { 563 title: 'Verify identity', 564 }; 565 566 try { 567 // Obtain an authentication object. 568 let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); 569 console.info('get userAuth instance success'); 570 // Start user authentication. 571 userAuthInstance.start(); 572 console.info('auth start success'); 573 // Cancel the authentication. 574 userAuthInstance.cancel(); 575 console.info('auth cancel success'); 576 } catch (error) { 577 const err: BusinessError = error as BusinessError; 578 console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); 579 } 580``` 581