在android 6.0 上Keyguard作为了SystemUI的一个库文件被引用,所以编译的时候不会出现Keyguard.apk这个文件,Keyguard也伴随着SystemUI的启动而启动,其中最重要的一个文件就是KeyguardViewMediator,这个文件负责SystemUI与Keyguard的交互,我们来看一下这个文件的启动。
KeyguardViewMediator.java作为SystemUIApplication.java中SERVICES[]中的一个元素,我们用一个流程图来说明这个文件的启动过程,这个数组中的其它元素启动顺序与这个类似,只是功能不同而已。
从上面的流程图中可以看到KeyguardViewMediator.java的启动分为两部分。
需要注意这个过程中的26:updateState(),这个函数会去更新keyguard以及systemUI的一些标志状态,保持系统状态的统一性,27会去设置更新后的这些状态值。
备注:
在这个过程中,使用了几次Handle,Handle的使用使得从log上看流程跟诡异,这是由于handle消息处理机制导致的,这个流程处理下来加了大量的状态判断,所以并不会对结果造成什么影响,只是分析问题查看log的时候可能需要注意一下这个情况。
系统在加载keyguard的时候需要先判断当前系统中是否有锁屏方式,那么锁屏方式又是如何保存的了?需要分析一下:
研究锁屏方式的保存可以从Settings 里的设置锁屏方式作为入口,ChooseLockGeneric.java。在这个文件中我们找到了锁屏的工具了,LockPathernUtils.java,锁屏方式的获取以及锁屏方式的保存都依靠这个类来进行,所以如果需要修改默认锁屏方式或者初始化锁屏方式有什么特殊的需求,可以直接改LockPathernUtils.java中对应的默认方式,本地实验过,都是可行的,副作用最小。
锁屏方式的保存与检测最后都会调用到framework层去,这部分比较复杂,后续会有专门的部分来说明framework中的锁屏方式。
如果仅仅想让MyTextView来响应触屏事件,让MyTextView的OnTouchEvent返回true,那么事件流就变成如下图,可以看到layoutview1,layoutview2已经不能进入OnTouchEvent:
另外一种情况,就是外围容器想独自处理触屏事件,那么就应该在相应的onInterceptTouchEvent函数中返回true,表示要截获触屏事件,比如layoutview1作截获处理,处理流变成如下图:
1.alps/frameworks/base/packages/SystemUI/res/values/Dimens.xml
2.80dp
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;
}
...
...
}
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)
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.
/data/system # cat password.keyB40C2F6FE4E89F3386D4E689B135304410D64951914FB35770FDAC58B694177B29297A80
/data/system # cat device_policies.xml
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;
};
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;
}
public void saveLockPattern(List 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);
}
}
LOCAL_CFLAGS = -Wall -Werror -g LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := liblog
+ #define LOG_TAG "gatekeeperd"+ #include + #include
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 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;
}
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(*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(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);
}
}
}