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
During the GMS update process, the number of options in Smart Lock may appear between 0-3, which is unstable
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.
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) ;
}
}
} ;
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
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 ) ;
}
}
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
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) ;
}
}
}