Android supports Smart Lock face unlock

platform

RK3288 + Android 7.1

demand

支持人脸解锁

plan description

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

Implementation steps

  • Built-in GMS (If PUSH goes in, please reset)
    GMS package content is as follows:
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

  • Confirm if FaceLock is installed
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@[email protected]@classes.dex [compilation_filter=interpret-onl
      y, status=kOatUpToDate]


Compiler stats:
  [com.android.facelock]
     FaceLock.apk - 252

  • The
    built-in GMS package version of the VPN connection is older, and you need to connect to GOOGLE updates and support libraries.
  • Set the screen lock method
    Settings>Security>Screen lock
    To use smart lock, you need to set the screen lock method to pattern/PIN code/password
  • Open Trusted Faces
    Settings>Security>Smart Lock> Trusted Faces, just press operation

Miscellaneous

some problems
  1. During the GMS update process, the number of options in Smart Lock may appear between 0-3, which is unstable
  2. The face unlock of Smart Lock does not skip the lock screen directly. In actual use, the user wakes up the device with the power supply, and the device starts to recognize the face. After the recognition is successful, there will be an unlock animation at the bottom of the screen, indicating that it has been successfully unlocked, but It does not directly enter the system, and requires the user to perform the upward sliding picture to complete the unlocking action.
  3. Starting from Android Q(10), GOOGLE deleted trusted faces for security reasons
Lock screen related codes
锁屏程序接收面部识别广播
|--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);
            }
        }
    }

Guess you like

Origin blog.csdn.net/ansondroider/article/details/102592602