启动指纹监听: 用户打开指纹识别开关时,开机初始化,唤醒,睡眠,都回调到 updateFingerprintListeningState更新是否打开指纹监听。
private void updateFingerprintListeningState() {
boolean shouldListenForFingerprint = shouldListenForFingerprint();
if (mFingerprintDetectionRunning && !shouldListenForFingerprint){
stopListeningForFingerprint();
} else if (!mFingerprintDetectionRunning && shouldListenForFingerprint){
startListeningForFingerprint();
}
}
startListeningForFingerprint 中调用mFpm.authenticate(null,mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);实现指纹监听扫描。
FingerprintManager 通过跨进程调用实现:它实际就调到了FingerprintService内部类 FingerprintServiceWrapper中的方法。如下:(关于mService为什么是FingerprintService后面有说明)
mService.authenticate(mToken, sessionId, userId, mServiceReceiver,flags,
mContext.getOpPackageName());
FingerprintService.java 内部类FingerprintServiceWrapper的方法:
@Override // Binder call
public void authenticate(final IBinder token, final long opId, final intgroupId,
finalIFingerprintServiceReceiver receiver, final int flags,
final String opPackageName) {
if (!isCurrentUserOrProfile(UserHandle.getCallingUserId())) {
Slog.w(TAG, "Can'tauthenticate non-current user");
return;
}
if (!canUseFingerprint(opPackageName)) {
Slog.w(TAG, "Calling notgranted permission to use fingerprint");
return;
}
// Group ID is arbitrarily set to parent profile user ID. It justrepresents
// the default fingerprints for the user.
final int effectiveGroupId = getEffectiveUserId(groupId);
final boolean restricted = isRestricted();
mHandler.post(new Runnable() {
@Override
public void run() {
startAuthentication(token, opId,effectiveGroupId, receiver, flags, restricted);
}
});
}
关于mService为什么是FingerprintService后面有说明如下:
FingerprintService.java在其中注册了FINGERPRINT_SERVICE服务,方便系统直接通过
SystemServer中调用FingerprintService的start方法最后调到publishBinderService来绑定服务
mSystemServiceManager.startService(FingerprintService.class);—》publishBinderService
ServiceManager.getService进行获取:
publishBinderService(Context.FINGERPRINT_SERVICE, newFingerprintServiceWrapper());
(publishBinderService 的实际实现systemService.java的ServiceManager.addService(name, service, allowIsolated);)
注册初始化:FingerprintManager,这样fingerprintManager就可以以代理的方式调用FingprintService
SystemServiceRegistry.java中:
registerService(Context.FINGERPRINT_SERVICE, FingerprintManager.class,
newCachedServiceFetcher<FingerprintManager>() {
@Override
public FingerprintManager createService(ContextImpl ctx) {
IBinder binder =ServiceManager.getService(Context.FINGERPRINT_SERVICE);
IFingerprintService service =IFingerprintService.Stub.asInterface(binder);
return newFingerprintManager(ctx.getOuterContext(), service);
}});
mService.authenticate最后调到了: final int result = daemon.authenticate(opId,groupId);
这个也同样是跨进程调用,被调用的进程是fingerd (C++书写的守护进程)。
fingerd进程分析:
入口为fingerprintd.cpp文件中的main函数:
android::sp<android::FingerprintDaemonProxy>proxy =
android::FingerprintDaemonProxy::getInstance();
android::status_t ret = serviceManager->addService(
android::FingerprintDaemonProxy::descriptor, proxy);
添加服务到serviceManager中这样framework代码就可以跨进程拿到这个服务也是aidl原理。不过这个是实现了c++层aidl.
那我们就开始看它核心(FingerprintDaemonProxy)proxy 到底做了些什么?
其中包括:
FingerprintDaemonProxy::authenticate 指纹认证实际调用的地方:daemon.authenticate就调用fingerd这个函数;
FingerprintDaemonProxy::init初始化:如进行初始化一个回调等
在FingerprintService就有用到:(注册一个回调给fingerd)
public IFingerprintDaemongetFingerprintDaemon() {
if (mDaemon == null) {
mDaemon =IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(FINGERPRINTD));
if (mDaemon != null) {
try {
mDaemon.asBinder().linkToDeath(this, 0);
mDaemon.init(mDaemonCallback);
mHalDeviceId =mDaemon.openHal();
FingerprintDaemonProxy::hal_notify_callback 注册到device驱动中:如FingerprintDaemonProxy::openHal() —》err =mDevice->set_notify(mDevice, hal_notify_callback); 如:驱动进行指纹的识别动作,根据不同的返回码调用hal_notify_callback这个回调,这个回调最后回调到mDaemon.init(mDaemonCallback);初始化进去的mDaemonCallback(即框架上层的回调)
如authenticate 操作经过指纹汇顶驱动进行匹配后,会回调执行到以下函数。 最后通过callback->onAuthenticated回调反馈给上层处理。
caseFINGERPRINT_AUTHENTICATED:
ALOGD("onAuthenticated(fid=%d, gid=%d)",
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid);
if (msg->data.authenticated.finger.fid!= 0) {
const uint8_t* hat = reinterpret_cast<const uint8_t*>(&msg->data.authenticated.hat);
instance->notifyKeystore(hat,sizeof(msg->data.authenticated.hat));
}
callback->onAuthenticated(device,
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid);
break;
那么上层的callback->onAuthenticated是怎么处理的呢?
callback实际上是FingerprintService.java中的IFingerprintDaemonCallbackmDaemonCallback = new IFingerprintDaemonCallback.Stub(){
@Override
public void onAuthenticated(long deviceId, int fingerId, int groupId) {
dispatchAuthenticated(deviceId, fingerId, groupId);
}
}
———>最后调到:receiver.onAuthenticationSucceeded(mHalDeviceId,fp);
receiver实际是:KeyguardUpdateMonitor.java
privateFingerprintManager.AuthenticationCallback mAuthenticationCallback
= new AuthenticationCallback() {
@Override
public void onAuthenticationSucceeded(AuthenticationResult result) {
handleFingerprintAuthenticated();
}
};
handleFingerprintAuthenticated 会调到KeyguardUpdateMonitorCallback,而其中的一个KeyguardUpdateMonitorCallback实际就是KeyguardViewMediator.onFingerprintAuthenticated这个函数就实现了解锁功能:
KeyguardUpdateMonitorCallback cb =mCallbacks.get(i).get();
cb.onFingerprintAuthenticated(userId,wakeAndUnlocking);
**************
public void onFingerprintAuthenticated(int userId, booleanwakeAndUnlocking) {
if (wakeAndUnlocking &&mShowing && unlockingWithFingerprintAllowed) {
mWakeAndUnlocking = true;
mStatusBarKeyguardViewManager.setWakeAndUnlocking();
keyguardDone(true, true);
} else if (mShowing &&mDeviceInteractive) {
if (wakeAndUnlocking) {
mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
}
mStatusBarKeyguardViewManager.animateCollapsePanels(
FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
}
}
};
***************
KeyguardViewMediator.onFingerprintAuthenticated这个函数就实现了解锁功能:
黑屏指纹解锁调用:keyguardDone(true,true);
亮屏指纹解锁调用:mStatusBarKeyguardViewManager.animateCollapsePanels(
FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
先讲解:亮屏指纹解锁调用的过程:
1:状态栏的一些处理 :如: PanelView
2:执行mBar.makeExpandedInvisible(); 实现解锁
1)添加mHideExpandedRunnable到sPendingRunnables中
2)postAnimationCallback调用执行sPendingRunnables
private Runnable mHideExpandedRunnable = new Runnable() {
@Override
public void run() {
mBar.makeExpandedInvisible();
}
};
上面的mHideExpandedRunnable是由下面函数进行调用的。
private staticvoid postAnimationCallback() {
sChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,sAnimationCallbackRunnable,
null);
}
其中有对于调用的控制最后又doFrame 做每一帧的时候根据条件调用doCallbacks函数,这里会调用到上列的mHideExpandedRunnable。
执行mBar.makeExpandedInvisible();实现解锁的解锁过程:
1)最终它也是调用mViewMediatorCallback.keyguardDone(true);实现的解锁
通过:
makeExpandedInvisible –》StatusBarKeyguarViewManager.dismiss(booleanauthenticated)–> showBouncer—>KeyguardBouncer.show(..)—>mKeyguardView.dismiss(authenticated)
mKeyguardView.dismiss(authenticated)就是实现解锁的关键方法:
KeyguardHostView.dismiss() –>KeyguardSecurityContainer. showNextSecurityScreenOrFinish(….)
showNextSecurityScreenOrFinish最终会调到mSecurityCallback.finish();
而mSecurityCallback是KeyguardHostView.即最终调了KeyguardHostView. finish()
if (mViewMediatorCallback != null) {
if (deferKeyguardDone) {
mViewMediatorCallback.keyguardDonePending();
} else {
mViewMediatorCallback.keyguardDone(true);
}
}
***************************************************************************
mViewMediatorCallback实际是定义在KeyguardViewMediator.java中
ViewMediatorCallback mViewMediatorCallback= new ViewMediatorCallback() {
public void userActivity() {
KeyguardViewMediator.this.userActivity();
}
public void keyguardDone(boolean authenticated) {
if (!mKeyguardDonePending) {
KeyguardViewMediator.this.keyguardDone(authenticated,true);
}
}
这里终于调到了KeyguardViewMediator.keyguardDone.
那我们从现在开始论述KeyguardViewMediator.keyguardDone.的解锁过程:
keyguardDone 实际调用解锁handleHide
最终它会跑到如下的代码进入框架进行解锁流程:
private final RunnablemKeyguardGoingAwayRunnable = new Runnable() {
@Override
public void run() {
try {
mStatusBarKeyguardViewManager.keyguardGoingAway();
// Don't actually hide theKeyguard at the moment, wait for window
// manager until it tells usit's safe to do so with
// startKeyguardExitAnimation.
ActivityManagerNative.getDefault().keyguardGoingAway(
mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
||mWakeAndUnlocking,
mStatusBarKeyguardViewManager.isGoingToNotificationShade());
} catch (RemoteException e) {
Log.e(TAG, "Error whilecalling WindowManager", e);
}
}
};
其中mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
||mWakeAndUnlocking,
可以控制解锁进桌面是否播放动画。keyguardGoingAway先是通过ActivityManagerService调到WindowManagerService的keyguardGoingAway
设置了mAnimator属性后直接进入requestTraversalLocked();进行窗口的变化。
performLayoutAndPlaceSurfacesLocked–》performLayoutAndPlaceSurfacesLockedLoop–》performLayoutAndPlaceSurfacesLockedInner—》
这个过程有很多窗口的layout 等最后跑到scheduleAnimationLocked();函数中。最后进入WindowAnimator的窗口动画中。
scheduleAnimationLocked到animateLocked 的过程:
mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback);其实它是通过Choreographer机制最后调用mAnimationFrameCallback——Choreographer通过利用Vsync机制执行执行Choreographer.dnFrame从而通过doCallbacks(Choreographer.CALLBACK_ANIMATION,frameTimeNanos);调用到了mAnimationFrameCallback
下面说一下animateLocked主要干了些什么?
window动画分为两种:窗口中的动画,Activity切换个动画。
1)updateWindowsLocked
这里需要指出的变量是:
// Currentlyrunning animation.
boolean mAnimating;
if (mAnimating) {
mService.scheduleAnimationLocked();
}
它是判断当前是否在有动画在执行:判断规则比较严格,如果窗口还有更多动画,或有Activity动画它都会反复调用scheduleAnimationLocked进行多次执行,这是为了保证窗口的画面的正确性。有时我们能通过判断这个变量拿到窗口动画执行的总时间。
下面通过代码分析认证这个:
updateWindowsLocked(displayId);
就是通过这个进行条件判断:winAnimator.stepAnimationLocked(mCurrentTime);里面就是通过判断
窗口是否还有更多动画需要执行,或有Activity动画来返回true或false来赋值mAnimating
updateWallpaperLocked(displayId)
updateWallpaperLocked同样也会进行判断:winAnimator.mAnimating来赋值mAnimating
如果最终mAnimating是True它会再次执行scheduleAnimationLocked
if (mAnimating) {
mService.scheduleAnimationLocked();
}
最终这个过程通过mPolicy.startKeyguardExitAnimation(mCurrentTime, 0 /*duration */);跑出框架。mPolicy实际是PhoneWindowManager对象。即最终调用了
public void startKeyguardExitAnimation(longstartTime, long fadeoutDuration) {
mKeyguardDelegate.startKeyguardExitAnimation(startTime,fadeoutDuration);
}
}
然后调到mKeyguardService.startKeyguardExitAnimation(startTime,fadeoutDuration);
即调到了KeyguardViewMediator的handleStartKeyguardExitAnimation
很多时候我们可以认为如果调到handleStartKeyguardExitAnimation那么解锁就完成了,但严格上也不能说它完成了(因为这时候其实窗口还是在变化中,我们无法确定窗口时候已经全部绘画完成),所以这个函数很多时候用来处理解锁完成后的一些事情。
2)updateWallpaperLocked
3:窗口动画的呈现:WinAnimator.prepareSurfaceLocked
1) computeShownFrameLocked(); 计算需要呈现的动画
2)赋值动画变化矩阵,透明度,Z轴到mSurfaceControl中
mSurfaceAlpha = mShownAlpha;
mSurfaceControl.setAlpha(mShownAlpha);
mSurfaceLayer = mAnimLayer;
mSurfaceControl.setLayer(mAnimLayer);
mSurfaceControl.setMatrix(
mDsDx * w.mHScale,mDtDx * w.mVScale,
mDsDy * w.mHScale,mDtDy * w.mVScale);
3)通过surfacefinger绘制surface画布纹理从而实现动画。
showSurfaceRobustlyLocked.mSurfaceControl.show();
再说一下Choreographer机制:
最后会执行到 调用输入窗口,其他窗口,窗口动画的回调函数
mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT,frameTimeNanos);
如下面所列都用到这个机制:
1:窗口动画:mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback);
2:View的添加然后窗口创建:
如:应用通过addView来添加布局View
- //3 选定了窗口修饰布局文件 ,添加至DecorView对象里,并且指定mcontentParent值
- View in = mLayoutInflater.inflate(layoutResource, null);
- decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
它的工作原理是:
ViewRootImp是用户与WMS沟通的桥梁,通过DectorView .addView
ViewRootImp.setView—-> ViewRootImp. requestLayout–>ViewRootImp. scheduleTraversals最后会执行到:
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
最后执行到mTraversalRunnable这个回调函数:
mTraversalRunnable做了些什么呢?
1) performMeasure View进行大小计算
2) performLayout View进行布局
2) performDraw(); 进行绘画
代码过程如下:
doTraversal()–>performTraversals —》performMeasure
—》performLayout
—》performDraw
performDraw的过程比较有意思:
performDraw –》draw(fullRedrawNeeded);
draw(fullRedrawNeeded);主要作用
1: surface = mSurface;拿到计算后的刚才通过performMeasure ,performLayout 过程后的surface纹理画布
2:drawSoftware(surface, mAttachInfo, xOffset,yOffset, scalingRequired, dirty)通过mView.draw(canvas)遍历绘制DectorView, surface.unlockCanvasAndPost(canvas);sufaceFinger绘制这个suface.
3:判断是否有动画,如果有,走动画的过程。
if(animating) {
mFullRedrawNeeded = true;
scheduleTraversals();
}