# Face_auth ## 概述 ### 功能简介 人脸识别功能是端侧设备ä¸å¯æˆ–缺的一部分,为设备æä¾›ä¸€ç§ç”¨æˆ·è®¤è¯èƒ½åŠ›ï¼Œå¯åº”用于设备解é”ã€æ”¯ä»˜ã€åº”用登录ç‰èº«ä»½è®¤è¯åœºæ™¯ã€‚它是基于人的脸部特å¾ä¿¡æ¯è¿›è¡Œèº«ä»½è¯†åˆ«çš„一ç§ç”Ÿç‰©ç‰¹å¾è¯†åˆ«æŠ€æœ¯ï¼Œç”¨æ‘„åƒæœºæˆ–æ‘„åƒå¤´é‡‡é›†å«æœ‰äººè„¸çš„å›¾åƒæˆ–视频æµï¼Œå¹¶è‡ªåŠ¨åœ¨å›¾åƒä¸æ£€æµ‹å’Œè·Ÿè¸ªäººè„¸ï¼Œè¿›è€Œå¯¹æ£€æµ‹åˆ°çš„人脸进行脸部识别,通常也å«åšäººåƒè¯†åˆ«ã€é¢éƒ¨è¯†åˆ«ã€äººè„¸è®¤è¯ã€‚人脸识别功能整体框架如图1。 基于HDF(Hardware Driver Foundation)驱动框架开å‘çš„Face_auth驱动,能够å±è”½ç¡¬ä»¶å™¨ä»¶å·®å¼‚ï¼Œä¸ºä¸Šå±‚ç”¨æˆ·è®¤è¯æ¡†æž¶å’ŒFace_authæœåŠ¡æä¾›ç¨³å®šçš„人脸识别基础能力接å£ï¼ŒåŒ…æ‹¬äººè„¸è¯†åˆ«æ‰§è¡Œå™¨åˆ—è¡¨æŸ¥è¯¢ã€æ‰§è¡Œå™¨ä¿¡æ¯æŸ¥è¯¢ã€æŒ‡å®šäººè„¸æ¨¡æ¿ID查询模æ¿ä¿¡æ¯ã€ç”¨æˆ·è®¤è¯æ¡†æž¶å’Œæ‰§è¡Œå™¨é—´çš„人脸模æ¿ä¿¡æ¯å¯¹è´¦ã€äººè„¸å½•å…¥ã€åˆ 除ã€è®¤è¯å’Œè¯†åˆ«ç‰ã€‚ **图1** 人脸识别功能整体框架  ### 基本概念 ç”¨æˆ·è®¤è¯æ¡†æž¶ä¸Žå„åŸºç¡€è®¤è¯æœåŠ¡ç»„æˆçš„身份认è¯ç³»ç»Ÿæ”¯æŒç”¨æˆ·è®¤è¯å‡æ®è®¾ç½®ã€åˆ 除ã€è®¤è¯ç‰åŸºç¡€åŠŸèƒ½ã€‚ç³»ç»Ÿæ”¯æŒç”¨æˆ·èº«ä»½è®¤è¯ï¼Œéœ€è¦æä¾›æ•°æ®é‡‡é›†ã€å¤„ç†ã€å˜å‚¨åŠæ¯”对能力。 - 执行器 执行器是能够æä¾›ä»¥ä¸Šèƒ½åŠ›çš„å¤„ç†æ¨¡å—,å„åŸºç¡€è®¤è¯æœåŠ¡æä¾›æ‰§è¡Œå™¨èƒ½åŠ›ï¼Œè¢«èº«ä»½è®¤è¯æ¡†æž¶è°ƒåº¦å®Œæˆå„项基础能力。 - 执行器安全ç‰çº§ 执行器æä¾›èƒ½åŠ›æ—¶æ‰€åœ¨è¿è¡ŒçŽ¯å¢ƒè¾¾åˆ°çš„å®‰å…¨çº§åˆ«ã€‚ - 执行器角色 - 全功能执行器:执行器å¯ç‹¬ç«‹å¤„ç†ä¸€æ¬¡å‡æ®æ³¨å†Œå’Œèº«ä»½è®¤è¯è¯·æ±‚,å³å¯æä¾›ç”¨æˆ·è®¤è¯æ•°æ®é‡‡é›†ã€å¤„ç†ã€å‚¨å˜åŠæ¯”对能力。 - 采集器:执行器æä¾›ç”¨æˆ·è®¤è¯æ—¶çš„æ•°æ®é‡‡é›†èƒ½åŠ›ï¼Œéœ€è¦å’Œè®¤è¯å™¨é…åˆå®Œæˆç”¨æˆ·è®¤è¯ã€‚ - 认è¯å™¨ï¼šè®¤è¯å™¨æä¾›ç”¨æˆ·è®¤è¯æ—¶æ•°æ®å¤„ç†èƒ½åŠ›ï¼Œè¯»å–å˜å‚¨çš„凿®æ¨¡æ¿ä¸Žå½“å‰è®¤è¯ä¿¡æ¯å®Œæˆæ¯”对。 - 执行器类型 åŒä¸€ç§èº«ä»½è®¤è¯ç±»åž‹çš„ä¸åŒè®¤è¯æ–¹å¼ä¼šäº§ç”Ÿè®¤è¯ç®—æ³•å·®å¼‚ï¼Œè®¾å¤‡å™¨ä»¶å·®å¼‚ä¹Ÿä¼šå¯¼è‡´ç®—æ³•å·®å¼‚ï¼Œæ‰§è¡Œå™¨æ ¹æ®æ”¯æŒçš„算法类型差异或对接的器件差异,会定义ä¸åŒçš„æ‰§è¡Œå™¨ç±»åž‹ã€‚ - ç”¨æˆ·è®¤è¯æ¡†æž¶å…¬é’¥ & 执行器公钥 用户身份认è¯å¤„ç†éœ€è¦ä¿è¯ç”¨æˆ·æ•°æ®å®‰å…¨ä»¥åŠè®¤è¯ç»“æžœçš„å‡†ç¡®æ€§ï¼Œç”¨æˆ·è®¤è¯æ¡†æž¶ä¸ŽåŸºç¡€è®¤è¯æœåŠ¡é—´çš„å…³é”®äº¤äº’ä¿¡æ¯éœ€è¦åšæ•°æ®å®Œæ•´æ€§ä¿æŠ¤ï¼Œå„åŸºç¡€è®¤è¯æœåС将æä¾›çš„æ‰§è¡Œå™¨èƒ½åŠ›å¯¹æŽ¥åˆ°ç”¨æˆ·è®¤è¯æ¡†æž¶æ—¶ï¼Œéœ€è¦äº¤æ¢å„自的公钥,其ä¸ï¼š 1ï¼‰æ‰§è¡Œå™¨é€šè¿‡ç”¨æˆ·è®¤è¯æ¡†æž¶å…¬é’¥æ ¡éªŒè°ƒåº¦æŒ‡ä»¤çš„准确性。 2)执行器公钥å¯è¢«ç”¨æˆ·è®¤è¯æ¡†æž¶ç”¨äºŽæ ¡éªŒè®¤è¯ç»“æžœçš„å‡†ç¡®æ€§ï¼ŒåŒæ—¶ç”¨äºŽæ‰§è¡Œå™¨äº¤äº’è®¤è¯æ—¶çš„æ ¡éªŒäº¤äº’ä¿¡æ¯çš„完整性。 - 认è¯å‡æ®æ¨¡æ¿ 认è¯å‡æ®æ˜¯åœ¨ç”¨æˆ·è®¾ç½®è®¤è¯å‡æ®æ—¶ç”±è®¤è¯æœåŠ¡äº§ç”Ÿå¹¶å˜å‚¨ï¼Œæ¯ä¸ªæ¨¡æ¿æœ‰ä¸€ä¸ªID,用于索引模æ¿ä¿¡æ¯æ–‡ä»¶ï¼Œåœ¨è®¤è¯æ—¶è¯»å–模æ¿ä¿¡æ¯å¹¶ç”¨äºŽä¸Žå½“次认è¯è¿‡ç¨‹ä¸äº§ç”Ÿçš„è®¤è¯æ•°æ®åšå¯¹æ¯”,完æˆèº«ä»½è®¤è¯ã€‚ - 执行器对账 ç”¨æˆ·è®¤è¯æ¡†æž¶ç»Ÿä¸€ç®¡ç†ç”¨æˆ·èº«ä»½å’Œå‡æ®IDçš„æ˜ å°„å…³ç³»ï¼Œæ‰§è¡Œå™¨å¯¹æŽ¥åˆ°ç”¨æˆ·è®¤è¯æ¡†æž¶æ—¶ï¼Œä¼šè¯»å–ç”¨æˆ·èº«ä»½è®¤è¯æ¡†æž¶å†…ä¿å˜çš„该执行器的模æ¿ID列表,执行器需è¦ä¸Žè‡ªå·±ç»´æŠ¤çš„æ¨¡æ¿IDåˆ—è¡¨è¿›è¡Œæ¯”å¯¹ï¼Œå¹¶åˆ é™¤å†—ä½™ä¿¡æ¯ã€‚ - HAPs HAPs(Harmony Ability Packages),广义上指å¯ä»¥å®‰è£…在OpenHarmonyä¸Šçš„åº”ç”¨åŒ…ï¼Œæœ¬ç« èŠ‚ä¸ä»…代表Face_auth驱动的上层应用。 - IDLæŽ¥å£ æŽ¥å£å®šä¹‰è¯è¨€ï¼ˆInterface Definition Language)通过IDL编译器编译åŽï¼Œèƒ½å¤Ÿç”Ÿæˆä¸Žç¼–程è¯è¨€ç›¸å…³çš„æ–‡ä»¶ï¼šå®¢æˆ·ç«¯æ¡©æ–‡ä»¶ï¼ŒæœåŠ¡å™¨æ¡†æž¶æ–‡ä»¶ã€‚æœ¬æ–‡ä¸»è¦æ˜¯é€šè¿‡IDL接å£ç”Ÿæˆçš„客户端和æœåŠ¡ç«¯æ¥å®žçްFace_authæœåŠ¡å’Œé©±åŠ¨çš„é€šä¿¡ï¼Œè¯¦ç»†ä½¿ç”¨æ–¹æ³•å¯å‚考[IDL简介](https://gitee.com/openharmony/ability_idl_tool/blob/master/README.md)。 - IPC通信 IPC(Inter Process Communication),进程间通信是指两个进程的数æ®ä¹‹é—´äº§ç”Ÿäº¤äº’,详细原ç†å¯å‚考[IPC通信简介](https://gitee.com/openharmony/communication_ipc/blob/master/README_zh.md)。 - HDI HDI(Hardware Device Interface),硬件设备接å£ï¼Œä½äºŽåŸºç¡€ç³»ç»ŸæœåŠ¡å±‚å’Œè®¾å¤‡é©±åŠ¨å±‚ä¹‹é—´ï¼Œæ˜¯æä¾›ç»™ç¡¬ä»¶ç³»ç»ŸæœåС开å‘者使用的ã€ç»Ÿä¸€çš„硬件设备功能抽象接å£ï¼Œå…¶ç›®çš„æ˜¯ä¸ºç³»ç»ŸæœåŠ¡å±è”½åº•层硬件设备差异,具体å¯å‚考[HDI规范](../../design/hdi-design-specifications.md)。 ### è¿ä½œæœºåˆ¶ Face_auth驱动的主è¦å·¥ä½œæ˜¯ä¸ºä¸Šå±‚ç”¨æˆ·è®¤è¯æ¡†æž¶å’ŒFace_authæœåŠ¡æä¾›ç¨³å®šçš„人脸识别基础能力,ä¿è¯è®¾å¤‡ä¸Šäººè„¸è¯†åˆ«åŠŸèƒ½å¯ä»¥æ£å¸¸è¿è¡Œã€‚ å¼€å‘者å¯åŸºäºŽHDF框架对ä¸åŒèŠ¯ç‰‡è¿›è¡Œå„自驱动的开å‘åŠHDI层接å£çš„调用。 **图2** Face_authæœåŠ¡å’ŒFace_auth驱动交互  ### 约æŸä¸Žé™åˆ¶ - è¦æ±‚设备上具备摄åƒå™¨ä»¶ï¼Œä¸”人脸图åƒåƒç´ 大于100*100。 - è¦æ±‚设备上具有å¯ä¿¡æ‰§è¡ŒçŽ¯å¢ƒï¼Œäººè„¸ç‰¹å¾ä¿¡æ¯é«˜å¼ºåº¦åР坆ä¿å˜åœ¨å¯ä¿¡æ‰§è¡ŒçŽ¯å¢ƒä¸ã€‚ - 对于é¢éƒ¨ç‰¹å¾ç›¸ä¼¼çš„人ã€é¢éƒ¨ç‰¹å¾ä¸æ–å‘育的儿童,人脸特å¾åŒ¹é…率有所ä¸åŒã€‚å¦‚æžœå¯¹æ¤æ‹…忧,å¯è€ƒè™‘å…¶ä»–è®¤è¯æ–¹å¼ã€‚ ## 开呿Œ‡å¯¼ ### åœºæ™¯ä»‹ç» Face_auth驱动的主è¦å·¥ä½œæ˜¯ä¸ºä¸Šå±‚ç”¨æˆ·è®¤è¯æ¡†æž¶å’ŒFace_authæœåŠ¡æä¾›ç¨³å®šçš„人脸识别基础能力,ä¿è¯è®¾å¤‡ä¸Šäººè„¸è¯†åˆ«åŠŸèƒ½å¯ä»¥æ£å¸¸è¿è¡Œã€‚ ### 接å£è¯´æ˜Ž 注:以下接å£åˆ—举的为IDLæŽ¥å£æè¿°ç”Ÿæˆçš„对应C++è¯è¨€å‡½æ•°æŽ¥å£ï¼ŒæŽ¥å£å£°æ˜Žè§idl文件(/drivers/interface/face_auth)。 在本文ä¸ï¼Œäººè„¸å‡æ®çš„录入ã€è®¤è¯ã€è¯†åˆ«å’Œåˆ 除相关的HDI接å£å¦‚表1所示,表2ä¸çš„回调函数分别用于人脸执行器返回æ“作结果给框架和返回æ“作过程ä¸çš„æç¤ºä¿¡æ¯ç»™ä¸Šå±‚应用。 **表1** 接å£åŠŸèƒ½ä»‹ç» | 接å£åç§° | åŠŸèƒ½ä»‹ç» | | ----------------------------------- | ---------------------------------- | | GetExecutorList(std::vector\<sptr\<IAllInOneExecutor>>& allInOneExecutors) | 获å–V2_0版本执行器列表。 | | GetExecutorInfo(ExecutorInfo& info) | èŽ·å–æ‰§è¡Œå™¨ä¿¡æ¯ï¼ŒåŒ…æ‹¬æ‰§è¡Œå™¨ç±»åž‹ã€æ‰§è¡Œå™¨è§’色ã€è®¤è¯ç±»åž‹ã€å®‰å…¨ç‰çº§ã€æ‰§è¡Œå™¨å…¬é’¥ç‰ä¿¡æ¯ï¼Œç”¨äºŽå‘ç”¨æˆ·è®¤è¯æ¡†æž¶æ³¨å†Œæ‰§è¡Œå™¨ã€‚ | | OnRegisterFinish(const std::vector\<uint64_t>& templateIdList,<br/> const std::vector\<uint8_t>& frameworkPublicKey, const std::vector\<uint8_t>& extraInfo) | 执行器注册æˆåŠŸåŽï¼ŒèŽ·å–ç”¨æˆ·è®¤è¯æ¡†æž¶çš„公钥信æ¯ï¼›èŽ·å–ç”¨æˆ·è®¤è¯æ¡†æž¶çš„人脸模æ¿åˆ—表用于对账。 | | Enroll(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br/> const sptr\<IExecutorCallback>& callbackObj) | 录入人脸模æ¿ã€‚ | | Authenticate(uint64_t scheduleId, const std::vector\<uint64_t>& templateIdList,<br/> const std::vector\<uint8_t>& extraInfo, const sptr\<IExecutorCallback>& callbackObj) | 认è¯äººè„¸æ¨¡æ¿ã€‚ | | Identify(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br/> const sptr\<IExecutorCallback>& callbackObj) | 识别人脸模æ¿ã€‚ | | Delete(const std::vector\<uint64_t>& templateIdList) | åˆ é™¤äººè„¸æ¨¡æ¿ã€‚ | | Cancel(uint64_t scheduleId) | 通过scheduleIdå–æ¶ˆæŒ‡å®šå½•å…¥ã€è®¤è¯ã€è¯†åˆ«æ“作。 | | SendCommand(int32_t commandId, const std::vector\<uint8_t>& extraInfo,<br/> const sptr\<IExecutorCallback>& callbackObj) | äººè„¸è®¤è¯æœåŠ¡å‘Face_authé©±åŠ¨ä¼ é€’å‚æ•°çš„通用接å£ã€‚ | | SetBufferProducer(const sptr\<BufferProducerSequenceable> &bufferProducer) | 设置预览æµç¼“冲区。 | | GetProperty(const std::vector\<uint64_t>& templateIdList,<br/>const std::vector\<int32_t>& propertyTypes, Property& property) | èŽ·å–æ‰§è¡Œå™¨å±žæ€§ä¿¡æ¯ã€‚ | | SetCachedTemplates(const std::vector\<uint64_t> &templateIdList) | è®¾ç½®éœ€ç¼“å˜æ¨¡æ¿åˆ—表。 | | RegisterSaCommandCallback(const sptr\<ISaCommandCallback> &callbackObj) | 注册SA命令回调。 | **表2** å›žè°ƒå‡½æ•°ä»‹ç» | 接å£åç§° | åŠŸèƒ½ä»‹ç» | | ------------------------------------------------------------ | ------------------------ | | ExecutorCallbackService::OnResult(int32_t result, const std::vector\<uint8_t>& extraInfo) | 返回æ“作的最终结果。 | | ExecutorCallbackService::OnTip(int32_t tip, const std::vector\<uint8_t>& extraInfo) | 返回æ“作的过程交互信æ¯ã€‚ | | SaCommandCallbackService::OnSaCommands(const std::vector\<SaCommand>& commands) | å‘é€å‘½ä»¤åˆ—表。 | ### 开呿¥éª¤ 以Hi3516DV300å¹³å°ä¸ºä¾‹ï¼Œæˆ‘们æä¾›äº†Face_auth驱动DEMO实例,以下是目录结构åŠå„部分功能简介。 ```undefined // drivers/peripheral/face_auth ├── BUILD.gn # 编译脚本 ├── bundle.json # 组件æè¿°æ–‡ä»¶ └── hdi_service # Face_auth驱动实现 ├── BUILD.gn # 编译脚本 ├── include # 头文件 └── src # æºæ–‡ä»¶ ├── executor_impl.cpp # 认è¯ã€å½•å…¥ç‰åŠŸèƒ½æŽ¥å£å®žçް ├── face_auth_interface_driver.cpp # Face_authé©±åŠ¨å…¥å£ â””â”€â”€ face_auth_interface_service.cpp # èŽ·å–æ‰§è¡Œå™¨åˆ—表接å£å®žçް ``` 下é¢ç»“åˆDEMO实例介ç»é©±åЍ开å‘的具体æ¥éª¤ã€‚ 1. 基于HDF驱动框架,按照驱动Driver Entry程åºï¼Œå®ŒæˆFace_auth驱动开å‘,主è¦ç”±Bindã€Initã€Releaseã€Dispatch函数接å£å®žçŽ°ï¼Œè¯¦ç»†ä»£ç å‚è§[face_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/face_auth_interface_driver.cpp)文件。 ```c++ // 通过自定义的HdfFaceAuthInterfaceHost对象包å«ioService对象和真æ£çš„HDI Service实现IRemoteObject对象 struct HdfFaceAuthInterfaceHost { struct IDeviceIoService ioService; OHOS::sptr<OHOS::IRemoteObject> stub; }; // æœåŠ¡æŽ¥å£è°ƒç”¨å“åº”æŽ¥å£ int32_t FaceAuthInterfaceDriverDispatch( struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply) { IAM_LOGI("start"); if (client == nullptr || data == nullptr || reply == nullptr || client->device == nullptr || client->device->service == nullptr) { IAM_LOGE("invalid param"); return HDF_ERR_INVALID_PARAM; } auto *hdfFaceAuthInterfaceHost = CONTAINER_OF(client->device->service, struct HdfFaceAuthInterfaceHost, ioService); if (hdfFaceAuthInterfaceHost == nullptr || hdfFaceAuthInterfaceHost->stub == nullptr) { IAM_LOGE("hdfFaceAuthInterfaceHost is invalid"); return HDF_ERR_INVALID_PARAM; } OHOS::MessageParcel *dataParcel = nullptr; OHOS::MessageParcel *replyParcel = nullptr; OHOS::MessageOption option; if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { IAM_LOGE("invalid data sbuf object to dispatch"); return HDF_ERR_INVALID_PARAM; } if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { IAM_LOGE("invalid reply sbuf object to dispatch"); return HDF_ERR_INVALID_PARAM; } return hdfFaceAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); } // åˆå§‹åŒ–æŽ¥å£ int HdfFaceAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) { IAM_LOGI("start"); if (deviceObject == nullptr) { IAM_LOGE("deviceObject is nullptr"); return HDF_ERR_INVALID_PARAM; } if (!HdfDeviceSetClass(deviceObject, DEVICE_CLASS_USERAUTH)) { IAM_LOGE("set face auth hdf class failed"); return HDF_FAILURE; } return HDF_SUCCESS; } // Face_auth驱动对外æä¾›çš„æœåŠ¡ç»‘å®šåˆ°HDF框架 int HdfFaceAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) { IAM_LOGI("start"); if (deviceObject == nullptr) { IAM_LOGE("deviceObject is nullptr"); return HDF_ERR_INVALID_PARAM; } auto *hdfFaceAuthInterfaceHost = new (std::nothrow) HdfFaceAuthInterfaceHost; if (hdfFaceAuthInterfaceHost == nullptr) { IAM_LOGE("failed to create HdfFaceAuthInterfaceHost object"); return HDF_FAILURE; } hdfFaceAuthInterfaceHost->ioService.Dispatch = FaceAuthInterfaceDriverDispatch; hdfFaceAuthInterfaceHost->ioService.Open = NULL; hdfFaceAuthInterfaceHost->ioService.Release = NULL; auto serviceImpl = IFaceAuthInterface::Get(true); if (serviceImpl == nullptr) { IAM_LOGE("failed to get of implement service"); delete hdfFaceAuthInterfaceHost; return HDF_FAILURE; } hdfFaceAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, IFaceAuthInterface::GetDescriptor()); if (hdfFaceAuthInterfaceHost->stub == nullptr) { IAM_LOGE("failed to get stub object"); delete hdfFaceAuthInterfaceHost; return HDF_FAILURE; } deviceObject->service = &hdfFaceAuthInterfaceHost->ioService; IAM_LOGI("success"); return HDF_SUCCESS; } // 释放Face_auth驱动ä¸çš„èµ„æº void HdfFaceAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject) { IAM_LOGI("start"); if (deviceObject == nullptr || deviceObject->service == nullptr) { IAM_LOGE("deviceObject is invalid"); return; } auto *hdfFaceAuthInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfFaceAuthInterfaceHost, ioService); if (hdfFaceAuthInterfaceHost == nullptr) { IAM_LOGE("hdfFaceAuthInterfaceHost is nullptr"); return; } delete hdfFaceAuthInterfaceHost; IAM_LOGI("success"); } // 注册Face_authé©±åŠ¨å…¥å£æ•°æ®ç»“构体对象 struct HdfDriverEntry g_faceAuthInterfaceDriverEntry = { .moduleVersion = 1, .moduleName = "drivers_peripheral_face_auth", .Bind = HdfFaceAuthInterfaceDriverBind, .Init = HdfFaceAuthInterfaceDriverInit, .Release = HdfFaceAuthInterfaceDriverRelease, }; // 调用HDF_INITå°†é©±åŠ¨å…¥å£æ³¨å†Œåˆ°HDF框架ä¸ã€‚åœ¨åŠ è½½é©±åŠ¨æ—¶HDF框架会先调用Bind函数,å†è°ƒç”¨Initå‡½æ•°åŠ è½½è¯¥é©±åŠ¨ã€‚å½“Init调用异常时,HDF框架会调用Release释放驱动资æºå¹¶é€€å‡º HDF_INIT(g_faceAuthInterfaceDriverEntry); ``` 2. å®žçŽ°èŽ·å–æ‰§è¡Œå™¨åˆ—表接å£ï¼Œè¯¦ç»†ä»£ç å‚è§[face_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/face_auth_interface_service.cpp)文件。 ```c++ // 执行器实现类 class AllInOneExecutorImpl : public IAllInOneExecutor { public: AllInOneExecutorImpl(struct ExecutorInfo executorInfo); virtual ~AllInOneExecutorImpl() {} private: struct ExecutorInfo executorInfo_; // æ‰§è¡Œå™¨ä¿¡æ¯ }; static constexpr uint16_t SENSOR_ID = 123; // 执行器sensorID static constexpr uint32_t EXECUTOR_TYPE = 123; // 执行器类型 static constexpr size_t PUBLIC_KEY_LEN = 32; // 执行器32å—节公钥 // 创建HDIæœåŠ¡å¯¹è±¡ extern "C" IFaceAuthInterface *FaceAuthInterfaceImplGetInstance(void) { auto faceAuthInterfaceService = new (std::nothrow) FaceAuthInterfaceService(); if (faceAuthInterfaceService == nullptr) { IAM_LOGE("faceAuthInterfaceService is nullptr"); return nullptr; } return faceAuthInterfaceService; } // 获å–V2_0执行器列表实现 int32_t GetExecutorList(std::vector<sptr<IAllInOneExecutor>> &executorList) { IAM_LOGI("interface mock start"); for (auto executor : executorList_) { executorList.push_back(executor); } IAM_LOGI("interface mock success"); return HDF_SUCCESS; } ``` 3. 实现执行器æ¯ä¸ªåŠŸèƒ½æŽ¥å£ï¼Œè¯¦ç»†ä»£ç å‚è§[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)文件。 ```c++ // å®žçŽ°èŽ·å–æ‰§è¡Œå™¨ä¿¡æ¯æŽ¥å£ int32_t AllInOneExecutorImpl::GetExecutorInfo(ExecutorInfo &executorInfo) { IAM_LOGI("interface mock start"); executorInfo = executorInfo_; IAM_LOGI("get executor information success"); return HDF_SUCCESS; } // 实现执行器注册æˆåŠŸåŽï¼ŒèŽ·å–ç”¨æˆ·è®¤è¯æ¡†æž¶çš„公钥信æ¯ã€èŽ·å–ç”¨æˆ·è®¤è¯æ¡†æž¶çš„æ¨¡æ¿åˆ—表接å£ã€‚将公钥信æ¯ä¿æŒï¼Œæ¨¡æ¿åˆ—表用于和本地的模æ¿åšå¯¹è´¦ int32_t AllInOneExecutorImpl::OnRegisterFinish(const std::vector<uint64_t> &templateIdList, const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo) { IAM_LOGI("interface mock start"); static_cast<void>(templateIdList); static_cast<void>(extraInfo); static_cast<void>(frameworkPublicKey); IAM_LOGI("register finish"); return HDF_SUCCESS; } // å®žçŽ°äººè„¸å½•å…¥æŽ¥å£ int32_t AllInOneExecutorImpl::Enroll( uint64_t scheduleId, const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) { IAM_LOGI("interface mock start"); static_cast<void>(scheduleId); static_cast<void>(extraInfo); if (callbackObj == nullptr) { IAM_LOGE("callbackObj is nullptr"); return HDF_ERR_INVALID_PARAM; } IAM_LOGI("enroll, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT); int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); if (ret != HDF_SUCCESS) { IAM_LOGE("callback result is %{public}d", ret); return HDF_FAILURE; } return HDF_SUCCESS; } // å®žçŽ°äººè„¸è®¤è¯æŽ¥å£ int32_t AllInOneExecutorImpl::Authenticate(uint64_t scheduleId, const std::vector<uint64_t> &templateIdList, const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) { IAM_LOGI("interface mock start"); static_cast<void>(scheduleId); static_cast<void>(templateIdList); static_cast<void>(extraInfo); if (callbackObj == nullptr) { IAM_LOGE("callbackObj is nullptr"); return HDF_ERR_INVALID_PARAM; } IAM_LOGI("authenticate, result is %{public}d", ResultCode::NOT_ENROLLED); int32_t ret = callbackObj->OnResult(ResultCode::NOT_ENROLLED, {}); if (ret != HDF_SUCCESS) { IAM_LOGE("callback result is %{public}d", ret); return HDF_FAILURE; } return HDF_SUCCESS; } // å®žçŽ°äººè„¸è¯†åˆ«æŽ¥å£ int32_t AllInOneExecutorImpl::Identify( uint64_t scheduleId, const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) { IAM_LOGI("interface mock start"); static_cast<void>(scheduleId); static_cast<void>(extraInfo); if (callbackObj == nullptr) { IAM_LOGE("callbackObj is nullptr"); return HDF_ERR_INVALID_PARAM; } IAM_LOGI("identify, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT); int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); if (ret != HDF_SUCCESS) { IAM_LOGE("callback result is %{public}d", ret); return HDF_FAILURE; } return HDF_SUCCESS; } // å®žçŽ°åˆ é™¤äººè„¸æ¨¡æ¿æŽ¥å£ int32_t AllInOneExecutorImpl::Delete(const std::vector<uint64_t> &templateIdList) { IAM_LOGI("interface mock start"); static_cast<void>(templateIdList); IAM_LOGI("delete success"); return HDF_SUCCESS; } // 实现通过scheduleIdå–æ¶ˆæŒ‡å®šæ“ä½œæŽ¥å£ int32_t AllInOneExecutorImpl::Cancel(uint64_t scheduleId) { IAM_LOGI("interface mock start"); static_cast<void>(scheduleId); IAM_LOGI("cancel success"); return HDF_SUCCESS; } // å®žçŽ°äººè„¸è®¤è¯æœåŠ¡å‘Face_authé©±åŠ¨ä¼ é€’å‚æ•°çš„通用接å£ï¼Œå½“å‰éœ€è¦å®žçŽ°å†»ç»“ä¸Žè§£é”æ¨¡æ¿å‘½ä»¤ int32_t AllInOneExecutorImpl::SendCommand( int32_t commandId, const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) { IAM_LOGI("interface mock start"); static_cast<void>(extraInfo); if (callbackObj == nullptr) { IAM_LOGE("callbackObj is nullptr"); return HDF_ERR_INVALID_PARAM; } int32_t ret; switch (commandId) { case DriverCommandId::LOCK_TEMPLATE: IAM_LOGI("lock template, result is %{public}d", ResultCode::SUCCESS); ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); if (ret != HDF_SUCCESS) { IAM_LOGE("callback result is %{public}d", ret); return HDF_FAILURE; } break; case DriverCommandId::UNLOCK_TEMPLATE: IAM_LOGI("unlock template, result is %{public}d", ResultCode::SUCCESS); ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); if (ret != HDF_SUCCESS) { IAM_LOGE("callback result is %{public}d", ret); return HDF_FAILURE; } break; case DriverCommandId::INIT_ALGORITHM: IAM_LOGI("init algorithm, result is %{public}d", ResultCode::SUCCESS); ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); if (ret != HDF_SUCCESS) { IAM_LOGE("callback result is %{public}d", ret); return HDF_FAILURE; } break; default: IAM_LOGD("not support DriverCommandId : %{public}d", commandId); ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); if (ret != HDF_SUCCESS) { IAM_LOGE("callback result is %{public}d", ret); return HDF_FAILURE; } } return HDF_SUCCESS; } // 实现设置预览æµç¼“å†²åŒºæŽ¥å£ int32_t FaceAuthInterfaceService::SetBufferProducer(const sptr<BufferProducerSequenceable> &bufferProducer) { IAM_LOGI("interface mock start set buffer producer %{public}s", UserIam::Common::GetPointerNullStateString(bufferProducer.GetRefPtr()).c_str()); return HDF_SUCCESS; } // å®žçŽ°èŽ·å–æ‰§è¡Œå™¨å±žæ€§æŽ¥å£ int32_t AllInOneExecutorImpl::GetProperty( const std::vector<uint64_t> &templateIdList, const std::vector<int32_t> &propertyTypes, Property &property) { IAM_LOGI("interface mock start"); property = {}; IAM_LOGI("get property success"); return HDF_SUCCESS; } // å®žçŽ°è®¾ç½®éœ€ç¼“å˜æ¨¡æ¿åˆ—è¡¨æŽ¥å£ int32_t AllInOneExecutorImpl::SetCachedTemplates(const std::vector<uint64_t> &templateIdList) { IAM_LOGI("interface mock start"); IAM_LOGI("set cached templates success"); return HDF_SUCCESS; } // 实现注册SAå‘½ä»¤å›žè°ƒæŽ¥å£ int32_t AllInOneExecutorImpl::RegisterSaCommandCallback(const sptr<ISaCommandCallback> &callbackObj) { IAM_LOGI("interface mock start"); IAM_LOGI("register sa command callback success"); return HDF_SUCCESS; } ``` 4. ç”¨æˆ·èº«ä»½è®¤è¯æ¡†æž¶æ”¯æŒå¤šdriverï¼Œå½“å¢žåŠ driver或者修改driverä¿¡æ¯ï¼Œéœ€è¦ä¿®æ”¹å¦‚下文件ä¸serviceName2Config。 ```c++ // base/user_iam/face_auth/services/src/face_auth_service.cpp void FaceAuthService::StartDriverManager() { IAM_LOGI("start"); int32_t ret = UserAuth::IDriverManager::Start(HDI_NAME_2_CONFIG); if (ret != FACE_AUTH_SUCCESS) { IAM_LOGE("start driver manager failed"); } } ``` ### è°ƒæµ‹éªŒè¯ é©±åŠ¨å¼€å‘完æˆåŽï¼Œé€šè¿‡[用户认è¯API接å£](../../application-dev/reference/apis-user-authentication-kit/js-apis-useriam-userauth.md)å¼€å‘HAP应用,基于RK3568å¹³å°éªŒè¯ã€‚认è¯å’Œå–消功能验è¯çš„æµ‹è¯•代ç 如下: 1.å‘起认è¯å¹¶èŽ·å–认è¯ç»“果的测试代ç 如下: ```ts // API version 10 import type {BusinessError} from '@ohos.base'; import userIAM_userAuth from '@ohos.userIAM.userAuth'; // 设置认è¯å‚æ•° const authParam: userIAM_userAuth.AuthParam = { challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FACE], authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, }; // é…置认è¯ç•Œé¢ const widgetParam: userIAM_userAuth.WidgetParam = { title: '请进行身份认è¯', }; try { // 获å–认è¯å¯¹è±¡ let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); console.info('get userAuth instance success'); // 订阅认è¯ç»“æžœ userAuthInstance.on('result', { onResult(result) { console.info(`userAuthInstance callback result: ${JSON.stringify(result)}`); // å¯åœ¨è®¤è¯ç»“æŸæˆ–其他业务需è¦åœºæ™¯ï¼Œå–消订阅认è¯ç»“æžœ userAuthInstance.off('result'); } }); console.info('auth on success'); userAuthInstance.start(); console.info('auth start success'); } catch (error) { const err: BusinessError = error as BusinessError; console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); } ``` 2.å–æ¶ˆè®¤è¯çš„æµ‹è¯•代ç 如下: ```ts // API version 10 import type {BusinessError} from '@ohos.base'; import userIAM_userAuth from '@ohos.userIAM.userAuth'; const authParam: userIAM_userAuth.AuthParam = { challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FACE], authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, }; const widgetParam: userIAM_userAuth.WidgetParam = { title: '请进行身份认è¯', }; try { // 获å–认è¯å¯¹è±¡ let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); console.info('get userAuth instance success'); // å¼€å§‹è®¤è¯ userAuthInstance.start(); console.info('auth start success'); // å–æ¶ˆè®¤è¯ userAuthInstance.cancel(); console.info('auth cancel success'); } catch (error) { const err: BusinessError = error as BusinessError; console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); } ```