Android支持Smart Lock 人脸解锁

简介: Android支持Smart Lock 人脸解锁

平台


RK3288 + Android 7.1


需求


支持人脸解锁


方案说明


使用Smart Lock 中的 "可信面孔" 功能实现人脸解锁


实现步骤


内置GMS(若PUSH进去, 请重置)

GMS包内容如下:

drwxrwxrwx 2 root root 4096 2013-01-21 17:32 FaceLock
drwxrwxrwx 2 root root 4096 2013-01-21 17:32 GoogleBackupTransport
drwxrwxrwx 2 root root 4096 2013-01-21 17:32 GoogleContactsSyncAdapter
drwxrwxrwx 3 root root 4096 2013-01-21 17:32 GoogleGmsCore
drwxrwxrwx 2 root root 4096 2013-01-21 17:32 GoogleLoginService
drwxrwxrwx 2 root root 4096 2013-01-21 17:33 GooglePartnerSetup
drwxrwxrwx 3 root root 4096 2013-01-21 17:32 GooglePlay
drwxrwxrwx 2 root root 4096 2013-01-21 17:33 GoogleServicesFramework


确认FaceLock是否已安装

rk3288:/system/priv-app # dumpsys package com.android.facelock                                                                 
Permissions:
  Permission [com.google.android.gms.auth.permission.FACE_UNLOCK] (e0424d2):
    sourcePackage=com.android.facelock
    uid=10024 gids=null type=0 prot=signature
    perm=Permission{767d9a3 com.google.android.gms.auth.permission.FACE_UNLOCK}
    packageSetting=PackageSetting{29984a0 com.android.facelock/10024}
Key Set Manager:
  [com.android.facelock]
      Signing KeySets: 6
Packages:
  Package [com.android.facelock] (29984a0):
    userId=10024
    pkg=Package{5866859 com.android.facelock}
    codePath=/system/priv-app/FaceLock
    resourcePath=/system/priv-app/FaceLock
    legacyNativeLibraryDir=/system/priv-app/FaceLock/lib
    primaryCpuAbi=null
    secondaryCpuAbi=null
    versionCode=25 minSdk=15 targetSdk=25
    versionName=7.1.2
    splits=[base]
    apkSigningVersion=2
    applicationInfo=ApplicationInfo{bdbbc1e com.android.facelock}
    flags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ]
    privateFlags=[ PRIVILEGED RESIZEABLE_ACTIVITIES ]
    dataDir=/data/user/0/com.android.facelock
    supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity]
    timeStamp=2019-10-15 10:09:32
    firstInstallTime=2019-10-15 10:09:32
    lastUpdateTime=2019-10-15 10:09:32
    signatures=PackageSignatures{d146cff [e3ca78d8]}
    installPermissionsFixed=false installStatus=1
    pkgFlags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ]
    declared permissions:
      com.google.android.gms.auth.permission.FACE_UNLOCK: prot=signature, INSTALLED
    requested permissions:
      android.permission.CAMERA
      com.google.android.gms.auth.permission.FACE_UNLOCK
    install permissions:
      com.google.android.gms.auth.permission.FACE_UNLOCK: granted=true
    User 0: ceDataInode=513 installed=true hidden=false suspended=false stopped=false notLaunched=false enabled=0
      runtime permissions:
Dexopt state:
  [com.android.facelock]
    Instruction Set: arm
      path: /system/priv-app/FaceLock/FaceLock.apk
      status: /data/dalvik-cache/arm/system@priv-app@FaceLock@FaceLock.apk@classes.dex [compilation_filter=interpret-onl
      y, status=kOatUpToDate]
Compiler stats:
  [com.android.facelock]
     FaceLock.apk - 252


连接VPN

内置的GMS包版本较旧, 需要联接GOOGLE更新和支持库等内容.

设置锁屏方式

设置>安全>屏幕锁定

要使用smart lock, 需设置屏幕锁定方式为图案/PIN码/密码

打开 可信面孔

设置>安全>Smart Lock > 可信面孔, 按操作即可


杂项


一些问题

在GMS更新的过程中, Smart Lock中的选项可能出现的个数在0-3之间, 不稳定

Smart Lock的人脸解锁并不会直接跳过锁屏, 在实际使用过程中, 用户使用电源唤醒设备, 设备开始识别人脸, 识别成功后, 屏幕下方会有解锁动画, 表示已成功解锁, 但 不会 直接进入系统, 需要用户执行上滑动画以完成解锁动作.

在Android Q(10)开始, GOOGLE出于安全原因, 删除了可信面孔

锁屏相关代码

锁屏程序接收面部识别广播

|--frameworks/base/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java


//人脸解锁广播
    private static final String ACTION_FACE_UNLOCK_STARTED
            = "com.android.facelock.FACE_UNLOCK_STARTED";
    private static final String ACTION_FACE_UNLOCK_STOPPED
            = "com.android.facelock.FACE_UNLOCK_STOPPED";
    private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) {
                mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
            } else if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
                        intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
            } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) {
                Trace.beginSection("KeyguardUpdateMonitor.mBroadcastAllReceiver#onReceive ACTION_FACE_UNLOCK_STARTED");
                mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1,
                        getSendingUserId()));
                Trace.endSection();
            } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) {
                mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0,
                        getSendingUserId()));
            } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
                    .equals(action)) {
                mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
            } else if (ACTION_USER_UNLOCKED.equals(action)) {
                mHandler.sendEmptyMessage(MSG_USER_UNLOCKED);
            }
        }
    };
//mHandler 消息处理
                 case MSG_FACE_UNLOCK_STATE_CHANGED:
                    Trace.beginSection("KeyguardUpdateMonitor#handler MSG_FACE_UNLOCK_STATE_CHANGED");
                    handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
                    Trace.endSection();
                    break;
    private void handleFaceUnlockStateChanged(boolean running, int userId) {
        mUserFaceUnlockRunning.put(userId, running);
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onFaceUnlockStateChanged(running, userId);
            }
        }
    }
|--frameworks/base/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
//空函数
    /**
     * Called when the state of face unlock changed.
     */
    public void onFaceUnlockStateChanged(boolean running, int userId) { }
|--frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
    private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
  //...
        @Override
        public void onFaceUnlockStateChanged(boolean running, int userId) {
            update(false /* updateAlways */);
        }
  }
    private void update(boolean updateAlways) {
        Trace.beginSection("UnlockMethodCache#update");
        int user = KeyguardUpdateMonitor.getCurrentUser();
        boolean secure = mLockPatternUtils.isSecure(user);
        boolean canSkipBouncer = !secure ||  mKeyguardUpdateMonitor.getUserCanSkipBouncer(user);
        boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
        boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
        boolean faceUnlockRunning = mKeyguardUpdateMonitor.isFaceUnlockRunning(user)
                && trustManaged;
        boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer ||
                trustManaged != mTrustManaged  || faceUnlockRunning != mFaceUnlockRunning;
        if (changed || updateAlways) {
            mSecure = secure;
            mCanSkipBouncer = canSkipBouncer;
            mTrusted = trusted;
            mTrustManaged = trustManaged;
            mFaceUnlockRunning = faceUnlockRunning;
            notifyListeners();
        }
        Trace.endSection();
    }
  private void notifyListeners() {
        for (OnUnlockMethodChangedListener listener : mListeners) {
            listener.onUnlockMethodStateChanged();
        }
    }
|--frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
    @Override  // UnlockMethodCache.OnUnlockMethodChangedListener
    public void onUnlockMethodStateChanged() {
        logStateToEventlog();
    }
    private void logStateToEventlog() {
        boolean isShowing = mStatusBarKeyguardViewManager.isShowing();
        boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded();
        boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
        boolean isSecure = mUnlockMethodCache.isMethodSecure();
        boolean canSkipBouncer = mUnlockMethodCache.canSkipBouncer();
        int stateFingerprint = getLoggingFingerprint(mState,
                isShowing,
                isOccluded,
                isBouncerShowing,
                isSecure,
                canSkipBouncer);
        if (stateFingerprint != mLastLoggedStateFingerprint) {
            EventLogTags.writeSysuiStatusBarState(mState,
                    isShowing ? 1 : 0,
                    isOccluded ? 1 : 0,
                    isBouncerShowing ? 1 : 0,
                    isSecure ? 1 : 0,
                    canSkipBouncer ? 1 : 0);
            mLastLoggedStateFingerprint = stateFingerprint;
        }
    }
|--frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
        UnlockMethodCache.OnUnlockMethodChangedListener,
        AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
    @Override
    public void onUnlockMethodStateChanged() {
        mLockIcon.update();
        updateCameraVisibility();
    }
}
|--frameworks/base/services/core/java/com/android/server/trust/TrustManagerService.java
     public void updateTrust(int userId, int flags) {
        boolean managed = aggregateIsTrustManaged(userId);
        dispatchOnTrustManagedChanged(managed, userId);
        if (mStrongAuthTracker.isTrustAllowedForUser(userId)
                && isTrustUsuallyManagedInternal(userId) != managed) {
            updateTrustUsuallyManaged(userId, managed);
        }
        boolean trusted = aggregateIsTrusted(userId);
        boolean changed;
        synchronized (mUserIsTrusted) {
            changed = mUserIsTrusted.get(userId) != trusted;
            mUserIsTrusted.put(userId, trusted);
        }
        dispatchOnTrustChanged(trusted, userId, flags);
        if (changed) {
            refreshDeviceLockedForUser(userId);
        }
    }
  private void dispatchOnTrustChanged(boolean enabled, int userId, int flags) {
        if (DEBUG) {
            Log.i(TAG, "onTrustChanged(" + enabled + ", " + userId + ", 0x"
                    + Integer.toHexString(flags) + ")");
        }
        if (!enabled) flags = 0;
        for (int i = 0; i < mTrustListeners.size(); i++) {
            try {
                mTrustListeners.get(i).onTrustChanged(enabled, userId, flags);
            } catch (DeadObjectException e) {
                Slog.d(TAG, "Removing dead TrustListener.");
                mTrustListeners.remove(i);
                i--;
            } catch (RemoteException e) {
                Slog.e(TAG, "Exception while notifying TrustListener.", e);
            }
        }
    }
相关文章
|
3月前
|
API 开发工具 Android开发
视觉智能开放平台产品使用合集之人脸活体检测能力是否支持Android端或者iOS端直接调用
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
|
安全 算法 Android开发
Android10.0 人脸解锁(上)
Android10.0 人脸解锁(上)
Android10.0 人脸解锁(上)
|
存储 传感器 安全
Android11.0 增加人脸解锁功能
Android11.0 增加人脸解锁功能
944 0
|
计算机视觉
Android10.0 人脸解锁(下)
Android10.0 人脸解锁
|
安全 数据安全/隐私保护 Android开发
Android 10.0 滑动解锁流程(下)
Android 10.0 滑动解锁流程(下)
|
安全 Android开发 数据安全/隐私保护
Android 10.0 滑动解锁流程(上)
Android 10.0 滑动解锁流程(上)
1045 0
|
算法 数据处理 开发工具
|
算法 Java 生物认证
Android指纹解锁源码分析
Android指纹解锁源码分析
389 0
Android指纹解锁源码分析
|
测试技术 API 数据安全/隐私保护
Android——实现人脸支付
功能实现 人脸支付 API初始化 人脸特征提取 返回支付结果 密码框输入支付 自定义密码输入框控件 初始化控件 密码匹配 尾言 效果展
368 0
|
Android开发
【Android】Pixel 2 解锁 Bootloader
【Android】Pixel 2 解锁 Bootloader
403 0
【Android】Pixel 2 解锁 Bootloader