diff --git a/security/FaceRecognition/README.md b/security/FaceRecognition/README.md new file mode 100644 index 0000000000000000000000000000000000000000..264cd26028e5524d260dae92689c699b53f84723 --- /dev/null +++ b/security/FaceRecognition/README.md @@ -0,0 +1,3 @@ +# Facial Recognition + +- Currently, 2D and 3D facial recognition are supported and can be used in identity authentication scenarios such as device unlocking, application login, and payment. \ No newline at end of file diff --git a/security/FaceRecognition/README_zh.md b/security/FaceRecognition/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..268953f55ed03fa37d03bd2a4e7cc66da2db2419 --- /dev/null +++ b/security/FaceRecognition/README_zh.md @@ -0,0 +1,3 @@ +# 人脸识别 + +- 当前生物特征识别支持2D人脸识别、3D人脸识别,可应用于设备解锁、应用登录、支付等身份认证场景。 \ No newline at end of file diff --git a/security/FaceRecognition/build.gradle b/security/FaceRecognition/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..e76a14f743baa5377849b43abf29dd0fe29b6478 --- /dev/null +++ b/security/FaceRecognition/build.gradle @@ -0,0 +1,34 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.huawei.ohos.app' + +ohos { + compileSdkVersion 5 + defaultConfig { + compatibleSdkVersion 4 + } +} +buildscript { + repositories { + maven { + url 'https://repo.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } + dependencies { + classpath 'com.huawei.ohos:hap:2.4.4.2' + } +} +allprojects { + repositories { + maven { + url 'https://repo.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } +} \ No newline at end of file diff --git a/security/FaceRecognition/entry/build.gradle b/security/FaceRecognition/entry/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..1324a93eda46cb945cc94de68b1cb0d1bcca10d1 --- /dev/null +++ b/security/FaceRecognition/entry/build.gradle @@ -0,0 +1,18 @@ +apply plugin: 'com.huawei.ohos.hap' +ohos { + compileSdkVersion 5 + defaultConfig { + compatibleSdkVersion 4 + } + buildTypes { + release { + proguardOpt { + proguardEnabled false + rulesFiles 'proguard-rules.pro' + } + } + } +} +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) +} diff --git a/security/FaceRecognition/entry/src/main/config.json b/security/FaceRecognition/entry/src/main/config.json new file mode 100644 index 0000000000000000000000000000000000000000..945fb5632a680582d7ba65d2f01dd3579d99fc28 --- /dev/null +++ b/security/FaceRecognition/entry/src/main/config.json @@ -0,0 +1,53 @@ +{ + "app": { + "bundleName": "ohos.samples.facerecognition", + "version": { + "code": 1000000, + "name": "1.0" + } + }, + "deviceConfig": {}, + "module": { + "package": "ohos.samples.facerecognition", + "name": ".MainAbility", + "reqCapabilities": [ + "video_support" + ], + "deviceType": [ + "default" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry", + "installationFree":false + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "portrait", + "formsEnabled": false, + "name": ".MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "$string:app_name", + "type": "page", + "launchType": "standard" + } + ], + "reqPermissions": [ + { + "name": "ohos.permission.ACCESS_BIOMETRIC" + } + ] + } +} \ No newline at end of file diff --git a/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/MainAbility.java b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/MainAbility.java new file mode 100644 index 0000000000000000000000000000000000000000..609c187f2c687179e28e29b2cfadb7fc47f0204e --- /dev/null +++ b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/MainAbility.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ohos.samples.facerecognition; + +import ohos.samples.facerecognition.slice.MainAbilitySlice; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; + +/** + * Facerecognition MainAbility + */ +public class MainAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + } +} diff --git a/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/slice/MainAbilitySlice.java b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/slice/MainAbilitySlice.java new file mode 100644 index 0000000000000000000000000000000000000000..7ee321e055c00f9f5f59fcd682a79b45df7afbfb --- /dev/null +++ b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/slice/MainAbilitySlice.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ohos.samples.facerecognition.slice; + +import ohos.samples.facerecognition.ResourceTable; +import ohos.samples.facerecognition.utils.ThreadPoolUtil; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.Text; +import ohos.agp.window.dialog.CommonDialog; +import ohos.biometrics.authentication.BiometricAuthentication; +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.eventhandler.InnerEvent; + +/** + * MainAbilitySlice + */ +public class MainAbilitySlice extends AbilitySlice { + private static final int EVENT_MESSAGE_SUCCESS = 0x1000001; + + private static final int EVENT_MESSAGE_FAIL = 0x1000002; + + private static final int BA_CHECK_NOT_ENROLLED = 4; + + private Text resultText; + + private String result; + + private EventHandler handler = new EventHandler(EventRunner.current()) { + @Override + protected void processEvent(InnerEvent event) { + switch (event.eventId) { + case EVENT_MESSAGE_SUCCESS: + showDialog(result); + resultText.setText(result); + break; + case EVENT_MESSAGE_FAIL: + resultText.setText(result); + break; + } + } + }; + + private BiometricAuthentication biometricAuthentication; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_main_ability_slice); + initComponents(); + } + + private void initComponents() { + resultText = (Text) findComponentById(ResourceTable.Id_result_text); + Component startButton = findComponentById(ResourceTable.Id_start); + Component cancelButton = findComponentById(ResourceTable.Id_cancel); + startButton.setClickedListener(this::startFaceUnlock); + cancelButton.setClickedListener(this::cancelRecognition); + } + + private synchronized void startFaceUnlock(Component component) { + try { + biometricAuthentication = BiometricAuthentication.getInstance(getAbility()); + int availability = biometricAuthentication.checkAuthenticationAvailability( + BiometricAuthentication.AuthType.AUTH_TYPE_BIOMETRIC_FACE_ONLY, + BiometricAuthentication.SecureLevel.SECURE_LEVEL_S2, true); + if (availability == 0) { + execAuthentication(); + } else if (availability == BA_CHECK_NOT_ENROLLED) { + result = "Face Unlock not enrolled, set up face Recognition first"; + } else { + result = "Biometric authentication not support"; + } + + } catch (IllegalAccessException e) { + result = "Face Recognition error "; + } + handler.sendEvent(EVENT_MESSAGE_FAIL); + } + + private void execAuthentication() { + ThreadPoolUtil.submit(() -> { + int authenticationAction = biometricAuthentication.execAuthenticationAction( + BiometricAuthentication.AuthType.AUTH_TYPE_BIOMETRIC_FACE_ONLY, + BiometricAuthentication.SecureLevel.SECURE_LEVEL_S4, true, false, null); + if (authenticationAction == 0) { + result = "Unlocked successfully"; + handler.sendEvent(EVENT_MESSAGE_SUCCESS); + } else { + result = "Authentication failed, face biometric doesn't match"; + handler.sendEvent(EVENT_MESSAGE_FAIL); + } + }); + } + + private void cancelRecognition(Component component) { + if (biometricAuthentication != null) { + biometricAuthentication.cancelAuthenticationAction(); + } + } + + private void showDialog(String message) { + Component container = LayoutScatter.getInstance(this).parse(ResourceTable.Layout_dialog_layout, null, false); + Text content = (Text) container.findComponentById(ResourceTable.Id_message); + content.setText("Recognition result:" + System.lineSeparator() + message); + CommonDialog commonDialog = new CommonDialog(this); + commonDialog.setSize(900, 400); + commonDialog.setCornerRadius(30); + commonDialog.setContentCustomComponent(container); + commonDialog.show(); + Component btnOk = container.findComponentById(ResourceTable.Id_btn_ok); + btnOk.setClickedListener(component -> commonDialog.hide()); + } +} diff --git a/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/utils/ThreadPoolUtil.java b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/utils/ThreadPoolUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..55b2df2140d090a3c41804dcd7231f715277bff6 --- /dev/null +++ b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/utils/ThreadPoolUtil.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ohos.samples.facerecognition.utils; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Global thread pool + */ +public class ThreadPoolUtil { + private static final int CORE_COUNT = 10; + + private static final int THREAD_COUNT = 20; + + private static final int WORK_QUEUE_SIZE = 50; + + private static final long KEEP_ALIVE = 10L; + + private static final AtomicInteger THREAD_ID = new AtomicInteger(1); + + private static ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_COUNT, THREAD_COUNT, KEEP_ALIVE, + TimeUnit.SECONDS, new ArrayBlockingQueue<>(WORK_QUEUE_SIZE), new CommonThreadFactory()); + + private ThreadPoolUtil() { + } + + /** + * Submit task to execute + * + * @param task runnable task + */ + public static void submit(Runnable task) { + executor.submit(task); + } + + /** + * ThreadFactory + * + */ + static class CommonThreadFactory implements ThreadFactory { + @Override + public Thread newThread(Runnable runnable) { + String threadName = null; + if (THREAD_ID.get() == Integer.MAX_VALUE) { + threadName = "threadpool-common-" + THREAD_ID.getAndSet(1); + } else { + threadName = "threadpool-common-" + THREAD_ID.incrementAndGet(); + } + return new Thread(runnable, threadName); + } + } +} diff --git a/security/FaceRecognition/entry/src/main/resources/base/element/string.json b/security/FaceRecognition/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..5616ce7d89844021b477c615b03f297c7306b441 --- /dev/null +++ b/security/FaceRecognition/entry/src/main/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "app_name", + "value": "FaceRecognition" + }, + { + "name": "mainability_description", + "value": "hap sample empty page" + } + ] +} \ No newline at end of file diff --git a/security/FaceRecognition/entry/src/main/resources/base/graphic/button_bg.xml b/security/FaceRecognition/entry/src/main/resources/base/graphic/button_bg.xml new file mode 100644 index 0000000000000000000000000000000000000000..f4a98035344fc8f1a3211c66ec8098eb24fdaf66 --- /dev/null +++ b/security/FaceRecognition/entry/src/main/resources/base/graphic/button_bg.xml @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file diff --git a/security/FaceRecognition/entry/src/main/resources/base/layout/dialog_layout.xml b/security/FaceRecognition/entry/src/main/resources/base/layout/dialog_layout.xml new file mode 100644 index 0000000000000000000000000000000000000000..92119f692a0cad4da3154205861d828d5e536084 --- /dev/null +++ b/security/FaceRecognition/entry/src/main/resources/base/layout/dialog_layout.xml @@ -0,0 +1,50 @@ + + + + + + + + +