Android 7.0 Keyguard流程分析
在android 6.0 上Keyguard作为了SystemUI的一个库文件被引用,所以编译的时候不会出现Keyguard.apk这个文件,Keyguard也伴随着SystemUI的启动而启动,其中最重要的一个文件就是KeyguardViewMediator,这个文件负责SystemUI与Keyguard的交互,我们来看一下这个文件的启动。
一.KeyguardViewMediator的启动
KeyguardViewMediator.java作为SystemUIApplication.java中SERVICES[]中的一个元素,我们用一个流程图来说明这个文件的启动过程,这个数组中的其它元素启动顺序与这个类似,只是功能不同而已。
从上面的流程图中可以看到KeyguardViewMediator.java的启动分为两部分。
1.SystemUIApplication.java的onstart()
2.SystemUIApplication的onBootCompleted()
二.SystemUI的启动
三.POWER键灭屏时Keyguard的加载
1.PowerManagerService亮屏流程
2.KeyguardManager.java的说明
3.锁屏的加载绘制过程
需要注意这个过程中的26:updateState(),这个函数会去更新keyguard以及systemUI的一些标志状态,保持系统状态的统一性,27会去设置更新后的这些状态值。
备注:
在这个过程中,使用了几次Handle,Handle的使用使得从log上看流程跟诡异,这是由于handle消息处理机制导致的,这个流程处理下来加了大量的状态判断,所以并不会对结果造成什么影响,只是分析问题查看log的时候可能需要注意一下这个情况。
四.锁屏方式的保存
系统在加载keyguard的时候需要先判断当前系统中是否有锁屏方式,那么锁屏方式又是如何保存的了?需要分析一下:
研究锁屏方式的保存可以从Settings 里的设置锁屏方式作为入口,ChooseLockGeneric.java。在这个文件中我们找到了锁屏的工具了,LockPathernUtils.java,锁屏方式的获取以及锁屏方式的保存都依靠这个类来进行,所以如果需要修改默认锁屏方式或者初始化锁屏方式有什么特殊的需求,可以直接改LockPathernUtils.java中对应的默认方式,本地实验过,都是可行的,副作用最小。
锁屏方式的保存与检测最后都会调用到framework层去,这部分比较复杂,后续会有专门的部分来说明framework中的锁屏方式。
五.锁屏界面解锁分析
1.onInterceptTouchEvent和onTouchEvent调用时序
onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,Android这么设计的想法也很好理解,由于ViewGroup会包含若干childView,因此需要能够统一监控各种touch事件的机会,因此纯粹的不能包含子view的控件是没有这个方法的,如LinearLayout就有,TextView就没有。
onInterceptTouchEvent()使用也很简单,如果在ViewGroup里覆写了该方法,那么就可以对各种touch事件加以拦截。但是如何拦截,是否所有的touch事件都需要拦截则是比较复杂的,touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。并且,针对down事件处理的返回值直接影响到后续move和up事件的接收和传递。
关于返回值的问题,基本规则很清楚,如果return true,那么表示该方法消费了此次事件,如果return false,那么表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。
由于onInterceptTouchEvent()的机制比较复杂,总结一下,基本的规则是:
1.down事件首先会传递到onInterceptTouchEvent()方法
2.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
3.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
4.如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
5.如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。
如果仅仅想让MyTextView来响应触屏事件,让MyTextView的OnTouchEvent返回true,那么事件流就变成如下图,可以看到layoutview1,layoutview2已经不能进入OnTouchEvent:
另外一种情况,就是外围容器想独自处理触屏事件,那么就应该在相应的onInterceptTouchEvent函数中返回true,表示要截获触屏事件,比如layoutview1作截获处理,处理流变成如下图:
2.解锁流程
(1)notification界面的滑动
- 1.alps/frameworks/base/packages/SystemUI/res/values/Dimens.xml
- 2.<dimen name="unlock_falsing_threshold">80dp</dimen>
- PhoneStatusBar.java
- public void onTrackingStarted(){
- Log.d(TAG, "onTrackingStarted begin"); //添加这行
- ...
- }
- public void onTrackingStopped(){
- Log.d(TAG, "onTrackingStopped begin"); //添加这行
- ...
- }
- PanelView.java
- public boolean onTouchEvent(MotionEvent event){
- ...
- case MotionEvent.ACTION_MOVE:
- ...
- Log.d(TAG, "-h="+(-h)+" getFalsingThreshold()="+getFalsingThreshold()); //添加这行
- if(-h >= getFalsingThreshold()){
- mTouchAboveFalsingThreshold = true;
- }
- ...
- ...
- }
onTrackingStarted()的调用流程如下:
- 09-20 09:47:15.896 W/yangjie ( 1276): java.lang.RuntimeException: here
- 09-20 09:47:15.896 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.PanelView.onTrackingStarted(PanelView.java:438)
- 09-20 09:47:15.896 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.NotificationPanelView.onTrackingStarted(NotificationPanelView.java:1868)
- 09-20 09:47:15.896 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.PanelView.onTouchEvent(PanelView.java:311)
- 09-20 09:47:15.896 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.NotificationPanelView.onTouchEvent(NotificationPanelView.java:774)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.View.dispatchTouchEvent(View.java:9415)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2660)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2304)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2666)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2666)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
- 09-20 09:47:15.896 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.StatusBarWindowView.dispatchTouchEvent(StatusBarWindowView.java:208)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.View.dispatchPointerEvent(View.java:9646)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4738)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4596)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4101)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4154)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4120)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4266)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4128)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4323)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4101)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4154)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4120)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4128)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4101)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6555)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6529)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6472)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6727)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:6686)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:6753)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:894)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.Choreographer.doCallbacks(Choreographer.java:696)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.Choreographer.doFrame(Choreographer.java:625)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:880)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.os.Handler.handleCallback(Handler.java:815)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.os.Handler.dispatchMessage(Handler.java:104)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.os.Looper.loop(Looper.java:207)
- 09-20 09:47:15.896 W/yangjie ( 1276): at android.app.ActivityThread.main(ActivityThread.java:5692)
- 09-20 09:47:15.896 W/yangjie ( 1276): at java.lang.reflect.Method.invoke(Native Method)
- 09-20 09:47:15.896 W/yangjie ( 1276): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
- 09-20 09:47:15.896 W/yangjie ( 1276): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:766)
onTrackingStopped()的调用流程如下:
- 09-20 09:47:16.014 W/yangjie ( 1276): java.lang.RuntimeException: here
- 09-20 09:47:16.014 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.PanelView.onTrackingStopped(PanelView.java:426)
- 09-20 09:47:16.014 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.NotificationPanelView.onTrackingStopped(NotificationPanelView.java:1881)
- 09-20 09:47:16.014 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.PanelView.endMotionEvent(PanelView.java:396)
- 09-20 09:47:16.014 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.PanelView.onTouchEvent(PanelView.java:335)
- 09-20 09:47:16.014 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.NotificationPanelView.onTouchEvent(NotificationPanelView.java:774)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.View.dispatchTouchEvent(View.java:9415)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2660)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2304)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2666)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2666)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
- 09-20 09:47:16.014 W/yangjie ( 1276): at com.android.systemui.statusbar.phone.StatusBarWindowView.dispatchTouchEvent(StatusBarWindowView.java:208)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.View.dispatchPointerEvent(View.java:9646)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4738)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4596)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4101)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4154)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4120)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4266)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4128)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4323)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4101)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4154)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4120)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4128)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4101)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6555)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6529)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6472)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6727)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.os.MessageQueue.nativePollOnce(Native Method)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.os.MessageQueue.next(MessageQueue.java:328)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.os.Looper.loop(Looper.java:164)
- 09-20 09:47:16.014 W/yangjie ( 1276): at android.app.ActivityThread.main(ActivityThread.java:5692)
- 09-20 09:47:16.014 W/yangjie ( 1276): at java.lang.reflect.Method.invoke(Native Method)
- 09-20 09:47:16.014 W/yangjie ( 1276): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
- 09-20 09:47:16.014 W/yangjie ( 1276): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:766)
- 09-20 09:47:16.015 D/StatusBarKeyguardViewManager( 1276): dismiss(authenticated = false) is called. mScreenOn = true
- 09-20 09:47:16.015 D/KeyguardBouncer( 1276): show(resetSecuritySelection = false
- 09-20 09:47:16.016 D/KeyguardSecurityView( 1276): showNextSecurityScreenOrFinish(false)
- 09-20 09:47:16.016 D/KeyguardSecurityView( 1276): showNext.. mCurrentSecuritySelection = Pattern
- 09-20 09:47:16.016 D/KeyguardViewMediator( 1276): updateNavbarStatus() is called.
- 09-20 09:47:16.016 D/KeyguardSecurityView( 1276): showNextSecurityScreenOrFinish() - return finish = false
- 09-20 09:47:16.016 D/KeyguardBouncer( 1276): show() - try to dismiss "Bouncer" directly.
(2)锁屏界面的解锁
(3)根据异常栈来定位调用顺序
六.framework层Keyguard 的保存与读取
1.背景资料
(1)Android M 之前锁屏密码的存储
- /data/system # cat password.keyB40C2F6FE4E89F3386D4E689B135304410D64951914FB35770FDAC58B694177B29297A80
而密码的详细信息,存储在 /data/system/device_policies.xml 中,内容类似如下:
- /data/system # cat device_policies.xml
(2)Android M 中锁屏密码的存储
- typedef uint64_t secure_id_t;
- typedef uint64_t salt_t;
- /**
- * structure for easy serialization
- * and deserialization of password handles.
- */
- static const uint8_t HANDLE_VERSION = 2;
- struct __attribute__ ((__packed__))
- password_handle_t {
- // fields included in signature
- uint8_t version;
- secure_id_t user_id;
- uint64_t flags;
- // fields not included in signature
- salt_t salt;
- uint8_t signature[32];
- bool hardware_backed;
- };
2.无法解锁、解锁较慢或者注册锁慢问题
(1) java层分析
- public VerifyCredentialResponse checkPattern(String pattern, int userId) throws RemoteException {
- + Slog.d(TAg, "checkPattern"); //这里是slog,在吐sys log文件中return doVerifyPattern(pattern, false, 0, userId);
- }
- private VerifyCredentialResponse doVerifyPattern(String pattern, boolean hasChallenge,long challenge, int userId) throws RemoteException {
- checkPasswordReadPermission(userId);
- + Slog.d(TAg, "doVerifyPattern start");CredentialHash storedHash = mStorage.readPatternHash(userId);
- + Slog.d(TAg, "read pattern hash");boolean shouldReEnrollBaseZero = storedHash != null && storedHash.isBaseZeroPattern;
- ...
- VerifyCredentialResponse response = verifyCredential(userId, storedHash, patternToVerify,hasChallenge, challenge,new CredentialUtil() {...}
- );
- + Slog.d(TAg, "verifyCredential response code: response.getResponseCode()");if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK
- && shouldReEnrollBaseZero) {
- setLockPattern(pattern, patternToVerify, userId);
- }
- + Slog.d(TAg, "doVerifyPattern end");return response;
- }
- private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
- String credential, boolean hasChallenge, long challenge, CredentialUtil credentialUtil)
- throws RemoteException {
- ...
- + Slog.d(TAG, "hasChallenge: " + hasChallenge);if (hasChallenge) {
- byte[] token = null;
- GateKeeperResponse gateKeeperResponse = getGateKeeperService()
- .verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes());
- ...
- + Slog.d(TAG, "verify response " + response);
- } else {
- GateKeeperResponse gateKeeperResponse = getGateKeeperService().verify(
- userId, storedHash.hash, credential.getBytes());
- ...
- + Slog.d(TAG, "verify response " + response);
- }
- if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
- // credential has matchedunlockKeystore(credential, userId);
- if (shouldReEnroll) {
- credentialUtil.setCredential(credential, credential, userId);
- }
- + Slog.d(TAG, "verify ok");
- } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
- if (response.getTimeout() > 0) {
- requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
- }
- + Slog.d(TAG, "verify fail, retry ");
- }
- return response;
- }
- public void setLockPattern(String pattern, String savedCredential, int userId)
- throws RemoteException {
- checkWritePermission(userId);
- byte[] currentHandle = getCurrentHandle(userId);
- + Slog.d(TAG, "setLockPattern");if (pattern == null) {
- getGateKeeperService().clearSecureUserId(userId);
- mStorage.writePatternHash(null, userId);
- setKeystorePassword(null, userId);
- return;
- }
- ...
- byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, pattern, userId);
- if (enrolledHandle != null) {
- + Slog.d(TAG, "writePatternHash ");mStorage.writePatternHash(enrolledHandle, userId);
- } else {
- Slog.e(TAG, "Failed to enroll pattern");
- }
- + Slog.d(TAG, "setLockPattern done!");
- }
- @Overridepublic void setLockPassword(String password, String savedCredential, int userId)
- throws RemoteException {
- checkWritePermission(userId);
- byte[] currentHandle = getCurrentHandle(userId);
- + Slog.d(TAG, "setLockPassword");if (password == null) {
- getGateKeeperService().clearSecureUserId(userId);
- mStorage.writePasswordHash(null, userId);
- setKeystorePassword(null, userId);
- return;
- }
- ...
- byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, password, userId);
- if (enrolledHandle != null) {
- + Slog.d(TAG, "writePatternHash ");mStorage.writePasswordHash(enrolledHandle, userId);
- } else {
- Slog.e(TAG, "Failed to enroll password");
- }
- + Slog.d(TAG, "setLockPassword done!");
- }
- private byte[] enrollCredential(byte[] enrolledHandle,
- String enrolledCredential, String toEnroll, int userId)
- throws RemoteException {
- ...
- + Slog.d(TAG, "enroll start.");GateKeeperResponse response = getGateKeeperService().enroll(userId, enrolledHandle,
- enrolledCredentialBytes, toEnrollBytes);
- + Slog.d(TAG, "enroll finish.");
- if (response == null) {
- return null;
- }
- byte[] hash = response.getPayload();
- if (hash != null) {
- + Slog.d(TAG, "setKeystorePassword.");setKeystorePassword(toEnroll, userId);
- } else {
- // Should not happenSlog.e(TAG, "Throttled while enrolling a password");
- }
- + Slog.d(TAG, "enrollCredential done.");return hash;
- }
/frameworks/base/core/java/com/android/internal/widget/LockPatternUtils.java
- public void saveLockPattern(List<LockPatternView.Cell> pattern, String savedPattern,
- boolean isFallback, String fallbackFor, int userId) {
- try {
- if (pattern == null || pattern.size() < MIN_LOCK_PATTERN_SIZE) {
- throw new IllegalArgumentException("pattern must not be null and at least "
- + MIN_LOCK_PATTERN_SIZE + " dots long.");
- }
- + Log.d(TAG, "saveLockPattern begin. ");
- getLockSettings().setLockPattern(patternToString(pattern), savedPattern, userId);
- + Log.d(TAG, "saveLockPattern end. ");DevicePolicyManager dpm = getDevicePolicyManager();
- // Update the device encryption password.if (userId == UserHandle.USER_OWNER
- && LockPatternUtils.isDeviceEncryptionEnabled()) {
- if (!shouldEncryptWithCredentials(true)) {
- clearEncryptionPassword();
- } else {
- String stringPattern = patternToString(pattern);
- updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
- }
- }
- + Log.d(TAG, "update encrypt password ");
- setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
- ...
- + Log.d(TAG, set pawword type finish.");onAfterChangingPassword(userId);
- } catch (RemoteException re) {
- Log.e(TAG, "Couldn't save lock pattern " + re);
- }
- + Log.d(TAG, "saveLockPattern end. ");
- }
- public void saveLockPassword(String password, String savedPassword, int quality,
- boolean isFallback, String fallbackFor, int userHandle) {
- try {
- ...
- + Log.d(TAG, "saveLockPassowrd start.");getLockSettings().setLockPassword(password, savedPassword, userHandle);
- + Log.d(TAG, "saveLockPassowrd start.");int computedQuality = computePasswordQuality(password);
- ...
- + Log.d(TAG, "is fallback: " + isFallback);if (!isFallback) {
- ...
- } else {
- ...
- }
- ...
- + Log.d(TAG, "saveLockPassword done.");
- } catch (RemoteException re) {
- // Cant do muchLog.e(TAG, "Unable to save lock password " + re);
- }
- }
(2)native层分析
- LOCAL_CFLAGS = -Wall -Werror -g LOCAL_MODULE_TAGS := optional
- LOCAL_SHARED_LIBRARIES := liblog
/system/gatekeeper/gatekeeper.cpp
- + #define LOG_TAG "gatekeeperd"+ #include <cutils/log.h>+ #include <utils/Log.h>
void GateKeeper::Verify(const VerifyRequest &request, VerifyResponse *response) {
- if (response == NULL) return;
- ...
- + ALOGI("Verify: version %d", password_handle->version);if (password_handle->version > HANDLE_VERSION) {
- response->error = ERROR_INVALID;
- return;
- }
- secure_id_t user_id = password_handle->user_id;
- secure_id_t authenticator_id = 0;
- uint32_t uid = request.user_id;
- uint64_t timestamp = GetMillisecondsSinceBoot();
- uint32_t timeout = 0;
- bool throttle = (password_handle->version >= HANDLE_VERSION_THROTTLE);
- bool throttle_secure = password_handle->flags & HANDLE_FLAG_THROTTLE_SECURE;
- + ALOGI("throttle: %d, throttle_secure: %d", (throttle? 1:0), (throttle_secure? 1:0));if (throttle) {
- failure_record_t record;
- + ALOGI("GetFailureRecord"); //GetFailtureRecord具体有soft或hard的gatekeeper实现if (!GetFailureRecord(uid, user_id, &record, throttle_secure)) {
- response->error = ERROR_UNKNOWN;
- return;
- }
- + ALOGI("ThrottleRequest");if (ThrottleRequest(uid, timestamp, &record, throttle_secure, response)) return;
- + ALOGI("IncrementFailureRecord");if (!IncrementFailureRecord(uid, user_id, timestamp, &record, throttle_secure)) {
- response->error = ERROR_UNKNOWN;
- return;
- }
- timeout = ComputeRetryTimeout(&record);
- + ALOGI("ComputeRetryTimeout %d", timeout);
- } else {
- response->request_reenroll = true;
- + ALOGI("reenroll");
- }
- if (DoVerify(password_handle, request.provided_password)) {//校验函数
- // Signature matchesUniquePtr<uint8_t> auth_token_buffer;
- uint32_t auth_token_len;
- MintAuthToken(&auth_token_buffer, &auth_token_len, timestamp,
- user_id, authenticator_id, request.challenge);
- SizedBuffer auth_token(auth_token_len);
- memcpy(auth_token.buffer.get(), auth_token_buffer.get(), auth_token_len);
- response->SetVerificationToken(&auth_token);
- if (throttle) ClearFailureRecord(uid, user_id, throttle_secure);
- } else {
- // compute the new timeout given the incremented recordif (throttle && timeout > 0) {
- response->SetRetryTimeout(timeout);
- } else {
- response->error = ERROR_INVALID;
- }
- }
- + ALOGI("Verify: error is %d", response->error); //校验结束
- }
- bool GateKeeper::CreatePasswordHandle(SizedBuffer *password_handle_buffer, salt_t salt,
- secure_id_t user_id, uint64_t flags, uint8_t handle_version, const uint8_t *password,
- uint32_t password_length) {
- ...
- + ALOGI("CreatePasswordHandle");const uint8_t *password_key = NULL;
- uint32_t password_key_length = 0;
- GetPasswordKey(&password_key, &password_key_length);
- + ALOGI("password lenght: %d", password_key_length);if (!password_key || password_key_length == 0) {
- return false;
- }
- ComputePasswordSignature(password_handle->signature, sizeof(password_handle->signature), //ComputePasswordSignature由具体的soft或者hard gatekeeper实现。
- password_key, password_key_length, to_sign, sizeof(to_sign), salt);
- + ALOGI("CreatePasswordHandle end");return true;
- }
/system/core/gatekeeperd/gatekeeperd.cpp
- virtual int enroll(uint32_t uid,
- const uint8_t *current_password_handle, uint32_t current_password_handle_length,
- const uint8_t *current_password, uint32_t current_password_length,
- const uint8_t *desired_password, uint32_t desired_password_length,
- uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
- ...
- + ALOGI("enroll");
- if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
- return PERMISSION_DENIED;
- }
- // need a desired password to enrollif (desired_password_length == 0) return -EINVAL;
- int ret;
- if (device) {
- ...
- + ALOGI("hardware gatekeeper enroll begin.");ret = device->enroll(device, uid, current_password_handle, current_password_handle_length,
- current_password, current_password_length,
- desired_password, desired_password_length,
- enrolled_password_handle, enrolled_password_handle_length);
- } else {
- + ALOGI("soft gatekeeper enroll begin.");ret = soft_device->enroll(uid,
- current_password_handle, current_password_handle_length,
- current_password, current_password_length,
- desired_password, desired_password_length,
- enrolled_password_handle, enrolled_password_handle_length);
- }
- + ALOGI("enroll end. ret: %d", ret);
- if (ret == 0) {
- gatekeeper::password_handle_t *handle =
- reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle);
- store_sid(uid, handle->user_id);
- bool rr;
- + ALOGI("internal verify begin. ");// immediately verify this password so we don't ask the user to enter it again// if they just created it.verify(uid, *enrolled_password_handle, sizeof(password_handle_t), desired_password,
- desired_password_length, &rr);
- + ALOGI("internal verify end. ");
- }
- return ret;
- }
- virtual int verifyChallenge(uint32_t uid, uint64_t challenge,
- const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
- const uint8_t *provided_password, uint32_t provided_password_length,
- uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) {
- IPCThreadState* ipc = IPCThreadState::self();
- ...
- + ALOGI("verifyChallenge start. ");if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
- return PERMISSION_DENIED;
- }
- // can't verify if we're missing either paramif ((enrolled_password_handle_length | provided_password_length) == 0)
- return -EINVAL;
- int ret;
- if (device) {
- const gatekeeper::password_handle_t *handle =
- reinterpret_cast<const gatekeeper::password_handle_t *>(enrolled_password_handle);
- // handle version 0 does not have hardware backed flag, and thus cannot be upgraded to// a HAL if there was none beforeif (handle->version == 0 || handle->hardware_backed) {
- + ALOGI("hardware gatekeeper verify begin. ");ret = device->verify(device, uid, challenge,
- enrolled_password_handle, enrolled_password_handle_length,
- provided_password, provided_password_length, auth_token, auth_token_length,
- request_reenroll);
- } else {
- // upgrade scenario, a HAL has been added to this device where there was none beforeSoftGateKeeperDevice soft_dev;
- + ALOGI("software gatekeeper verify begin. ");ret = soft_dev.verify(uid, challenge,
- enrolled_password_handle, enrolled_password_handle_length,
- provided_password, provided_password_length, auth_token, auth_token_length,
- request_reenroll);
- if (ret == 0) {
- // success! re-enroll with HAL
- *request_reenroll = true;
- }
- }
- } else {
- + ALOGI("software gatekeeper verify begin. ");ret = soft_device->verify(uid, challenge,
- enrolled_password_handle, enrolled_password_handle_length,
- provided_password, provided_password_length, auth_token, auth_token_length,
- request_reenroll);
- }
- + ALOGI("gatekeeper verify end. ret: %d", ret);
- ...
- return ret;
- }
(3)如何通过log知道创建的是software还是hardware gatekeeper?
答: 在开机时候创建gatekeeper daemon的时候通过/system/core/gatekeeperd/gatekeeperd.cpp中的main函数启动daemon,
会创建GateKeeperProxy实例, 在GateKeeperProxy的构造函数,会决定创建的是software还是hardware gatekeeper:
- GateKeeperProxy() {
- int ret = hw_get_module_by_class(GATEKEEPER_HARDWARE_MODULE_ID, NULL, &module);//尝试获取HW gatekpper
- device = NULL;
- if (ret < 0) {
- ALOGW("falling back to software GateKeeper"); //如果有这条log出来,就表示用的是sw。否则就是hwsoft_device.reset(new SoftGateKeeperDevice());//使用sw gatekeeper
- } else {
- ret = gatekeeper_open(module, &device); //尝试打开hw gatekeeper
- if (ret < 0)
- LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to open GateKeeper HAL");
- }
- if (mark_cold_boot()) {
- ALOGI("cold boot: clearing state");
- if (device != NULL && device->delete_all_users != NULL) {
- device->delete_all_users(device);
- }
- }
- }
Android 7.0 Keyguard流程分析相关推荐
- Android8.0(34)----Android 8.0 Settings流程分析与变动
Android 8.0 Settings流程分析与变动 一,相比Android Settings 7.0 如下图,在7.0的基础上,去掉了7.0新加的侧滑菜单(可能是觉得有点鸡肋吧).多加了一级页面, ...
- Android 7.0系统启动流程分析
随着Android版本的升级,aosp项目中的代码也有了些变化,本文基于Android 7.0分析Android系统启动流程.当我们按下电源键后,整个Android设备大体经过了一下过程: 今天我们 ...
- Android 8.0 recovery 流程分析
这里主要分析non A/B模式下的recovery流程 A/B模式下的recovery在boot中 后续会不断补充,如果有疏漏或者错误的地方,请指出,共同学习,谢谢! 一.流程分析 首先列出recov ...
- AOSP Android 8.0 冷启动流程分析(二)
前奏: Android系统虽然基于Linux系统的,但是由于Android属于嵌入式设备,并没有像PC那样的BISO程序,取而代之的是Bootloader----系统启动加载器. /boot : 存放 ...
- Android 9.0 Vold 流程分析(-)
Vold 介绍 Vold(volume Daemon),即Volume守护进程,用来管理Android中存储类的热拔插事件,处于Kernel和Framework之间,是两个层级连接的桥梁.vold 代 ...
- Android 手机灭屏流程分析详解
参考地址:https://www.jianshu.com/p/9241f3a91095 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 1.前言 2.Pow ...
- c++builder启动了怎么停止_App 竟然是这样跑起来的 —— Android App/Activity 启动流程分析...
在我的上一篇文章: AJie:按下电源键后竟然发生了这一幕 -- Android 系统启动流程分析zhuanlan.zhihu.com 我们分析了系统在开机以后的一系列行为,其中最后一阶段 AMS( ...
- android 屏幕旋转流程,android自动屏幕旋转流程分析.doc
android自动屏幕旋转流程分析.doc android自动屏幕旋转流程分析 在android设置(Settings)中我们可以看到显示(display)下有一个自动屏幕旋转的checkbox, 如 ...
- android加载efi分区,高通Android UEFI XBL 代码流程分析
高通Android UEFI XBL 代码流程分析 背景 之前学习的lk阶段点亮LCD的流程算是比较经典,但是高通已经推出了很多种基于UEFI方案的启动架构. 所以需要对这块比较新的技术进行学习.在学 ...
最新文章
- python中根据URL获得数据库的名称及IP
- C语言中的scanf()函数介绍
- Unity制作游戏中的场景
- 计算机编程ebcdic码,EBCDIC 与 ASCII 编码相互转换
- linux命令:watch 、lsmod、mdadm 创建软RAID
- Webrtc服务器搭建转
- 每日冲刺报告——Day2(Java-Team)
- mysql怎么实现的主从复制_【mysql】mysql实现主从复制
- HIVE数据导入MYSQL实现方式
- matlab画直方图_直方图规定化+暗通道去雾 python
- 软工文档-项目开发计划
- 域名使用https访问配置
- 怎样自学python_怎样自学Python?
- 文件分配方式-索引分配
- 国土档案管理信息系统【档案查借阅登记】
- 学习pathon工具安装
- 哲理故事300篇(上)
- 计算机体系结构:不同改进方案的性价比计算(1.4)
- 组件Element的入门学习
- 图形性能测试软件,3DMark05 Build 1.2.0『最为普及的3D图形卡性能测试工具』