Android 人脸解锁源码剖析,安卓开发不得不会

case MSG_STARTED_GOING_TO_SLEEP:

/重点关注/

handleStartedGoingToSleep(msg.arg1);

break;

handleStartedGoingToSleep(msg.arg1);

protected void handleStartedGoingToSleep(int arg1) {

clearBiometricRecognized();

final int count = mCallbacks.size();

for (int i = 0; i < count; i++) {

KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();

if (cb != null) {

cb.onStartedGoingToSleep(arg1);

}

}

mGoingToSleep = true;

/重点关注/

updateBiometricListeningState();//更新生物识别状态

}

updateBiometricListeningState()

//在这个方法中我们可以看到同时更新了指纹和人脸的状态

private void updateBiometricListeningState() {

updateFingerprintListeningState();

/重点关注/

updateFaceListeningState();

}

updateFaceListeningState()

private void updateFaceListeningState() {

// If this message exists, we should not authenticate again until this message is

// consumed by the handler

if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {

return;

}

mHandler.removeCallbacks(mRetryFaceAuthentication);

boolean shouldListenForFace = shouldListenForFace();

if (mFaceRunningState == BIOMETRIC_STATE_RUNNING && !shouldListenForFace) {

stopListeningForFace();

} else if (mFaceRunningState != BIOMETRIC_STATE_RUNNING

&& shouldListenForFace) {

/重点关注/

startListeningForFace();

}

}

startListeningForFace()

private void startListeningForFace() {

if (mFaceRunningState == BIOMETRIC_STATE_CANCELLING) {

setFaceRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);

return;

}

if (DEBUG) Log.v(TAG, “startListeningForFace()”);

int userId = getCurrentUser();

if (isUnlockWithFacePossible(userId)) {

if (mFaceCancelSignal != null) {

mFaceCancelSignal.cancel();

}

mFaceCancelSignal = new CancellationSignal();

/重点关注/

mFaceManager.authenticate(null, mFaceCancelSignal, 0,

mFaceAuthenticationCallback, null, userId);

setFaceRunningState(BIOMETRIC_STATE_RUNNING);

}

}

frameworks/base/core/java/android/hardware/face/FaceManager.java

public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,

int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler,

int userId) {

if (callback == null) {

throw new IllegalArgumentException(“Must supply an authentication callback”);

}

if (cancel != null) {

if (cancel.isCanceled()) {

Log.w(TAG, “authentication already canceled”);

return;

} else {

cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));

}

}

if (mService != null) {

try {

useHandler(handler);

mAuthenticationCallback = callback;

mCryptoObject = crypto;

long sessionId = crypto != null ? crypto.getOpId() : 0;

Trace.beginSection(“FaceManager#authenticate”);

/重点关注/

mService.authenticate(mToken, sessionId, userId, mServiceReceiver,

flags, mContext.getOpPackageName());

} catch (RemoteException e) {

Log.w(TAG, "Remote exception while authenticating: ", e);

if (callback != null) {

// Though this may not be a hardware issue, it will cause apps to give up or

// try again later.

callback.onAuthenticationError(FACE_ERROR_HW_UNAVAILABLE,

getErrorString(mContext, FACE_ERROR_HW_UNAVAILABLE,

0 /* vendorCode */));

}

} finally {

Trace.endSection();

}

}

}

frameworks/base/services/core/java/com/android/server/biometrics/face/FaceService.java

@Override // Binder call

public void authenticate(final IBinder token, final long opId, int userId,

final IFaceServiceReceiver receiver, final int flags,

final String opPackageName) {

checkPermission(USE_BIOMETRIC_INTERNAL);

updateActiveGroup(userId, opPackageName);

final boolean restricted = isRestricted();

final AuthenticationClientImpl client = new FaceAuthClient(getContext(),

mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),

mCurrentUserId, 0 /* groupId */, opId, restricted, opPackageName,

0 /* cookie /, false / requireConfirmation */);

/重点关注/

authenticateInternal(client, opId, opPackageName);

}

frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java

protected void authenticateInternal(AuthenticationClientImpl client, long opId,

String opPackageName) {

final int callingUid = Binder.getCallingUid();

final int callingPid = Binder.getCallingPid();

final int callingUserId = UserHandle.getCallingUserId();

authenticateInternal(client, opId, opPackageName, callingUid, callingPid, callingUserId);

}

frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java

protected void authenticateInternal(AuthenticationClientImpl client, long opId,

String opPackageName, int callingUid, int callingPid, int callingUserId) {

if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid,

callingUserId)) {

if (DEBUG) Slog.v(getTag(), "authenticate(): reject " + opPackageName);

return;

}

mHandler.post(() -> {

mMetricsLogger.histogram(getConstants().tagAuthToken(), opId != 0L ? 1 : 0);

// Get performance stats object for this user.

HashMap<Integer, PerformanceStats> pmap

= (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap;

PerformanceStats stats = pmap.get(mCurrentUserId);

if (stats == null) {

stats = new PerformanceStats();

pmap.put(mCurrentUserId, stats);

}

mPerformanceStats = stats;

mIsCrypto = (opId != 0);

/重点关注/

startAuthentication(client, opPackageName);

});

}

startAuthentication(client, opPackageName);

private void startAuthentication(AuthenticationClientImpl client, String opPackageName) {

if (DEBUG) Slog.v(getTag(), “startAuthentication(” + opPackageName + “)”);

int lockoutMode = getLockoutMode();

if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {

Slog.v(getTag(), “In lockout mode(” + lockoutMode + “) ; disallowing authentication”);

int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?

BiometricConstants.BIOMETRIC_ERROR_LOCKOUT :

BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;

if (!client.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */)) {

Slog.w(getTag(), “Cannot send permanent lockout message to client”);

}

return;

}

/重点关注/

startClient(client, true /* initiatedByClient */);

//这里将AuthenticationClient传递进去

}

startClient(client, true /* initiatedByClient */);

private void startClient(ClientMonitor newClient, boolean initiatedByClient) {

ClientMonitor currentClient = mCurrentClient;

if (currentClient != null) {

if (DEBUG) Slog.v(getTag(), "request stop current client " +

currentClient.getOwnerString());

// This check only matters for FingerprintService, since enumerate may call back

// multiple times.

if (currentClient instanceof InternalEnumerateClient

|| currentClient instanceof InternalRemovalClient) {

// This condition means we’re currently running internal diagnostics to

// remove extra templates in the hardware and/or the software

// TODO: design an escape hatch in case client never finishes

if (newClient != null) {

Slog.w(getTag(), "Internal cleanup in progress but trying to start client "

  • newClient.getClass().getSuperclass().getSimpleName()

  • “(” + newClient.getOwnerString() + “)”

  • ", initiatedByClient = " + initiatedByClient);

}

} else {

currentClient.stop(initiatedByClient);

// Only post the reset runnable for non-cleanup clients. Cleanup clients should

// never be forcibly stopped since they ensure synchronization between HAL and

// framework. Thus, we should instead just start the pending client once cleanup

// finishes instead of using the reset runnable.

mHandler.removeCallbacks(mResetClientState);

mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);

}

mPendingClient = newClient;

} else if (newClient != null) {

// For BiometricPrompt clients, do not start until

// Service#startPreparedClient is called. BiometricService waits until all

// modalities are ready before initiating authentication.

if (newClient instanceof AuthenticationClient) {

AuthenticationClient client = (AuthenticationClient) newClient;

if (client.isBiometricPrompt()) {

if (DEBUG) Slog.v(getTag(), "Returning cookie: " + client.getCookie());

mCurrentClient = newClient;

if (mBiometricService == null) {

mBiometricService = IBiometricService.Stub.asInterface(

ServiceManager.getService(Context.BIOMETRIC_SERVICE));

}

try {

mBiometricService.onReadyForAuthentication(client.getCookie(),

client.getRequireConfirmation(), client.getTargetUserId());

} catch (RemoteException e) {

Slog.e(getTag(), “Remote exception”, e);

}

return;

}

}

// We are not a BiometricPrompt client, start the client immediately

mCurrentClient = newClient;

/重点关注/

startCurrentClient(mCurrentClient.getCookie());

//这里继续将AuthenticationClient传递进去

}

}

startCurrentClient(mCurrentClient.getCookie());

protected void startCurrentClient(int cookie) {

if (mCurrentClient == null) {

Slog.e(getTag(), “Trying to start null client!”);

return;

}

if (DEBUG) Slog.v(getTag(), "starting client "

  • mCurrentClient.getClass().getSuperclass().getSimpleName()

  • “(” + mCurrentClient.getOwnerString() + “)”

  • " cookie: " + cookie + “/” + mCurrentClient.getCookie());

if (cookie != mCurrentClient.getCookie()) {

Slog.e(getTag(), “Mismatched cookie”);

return;

}

notifyClientActiveCallbacks(true);

/重点关注/

mCurrentClient.start();

//这里调用的是AuthenticationClient的start方法

}

frameworks/base/services/core/java/com/android/server/biometrics/AuthenticationClient.java

public int start() {

mStarted = true;

onStart();

try {

/重点关注/

final int result = getDaemonWrapper().authenticate(mOpId, getGroupId());

if (result != 0) {

Slog.w(getLogTag(), “startAuthentication failed, result=” + result);

mMetricsLogger.histogram(mConstants.tagAuthStartError(), result);

onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,

0 /* vendorCode */);

return result;

}

if (DEBUG) Slog.w(getLogTag(), “client " + getOwnerString() + " is authenticating…”);

} catch (RemoteException e) {

Slog.e(getLogTag(), “startAuthentication failed”, e);

return ERROR_ESRCH;

}

return 0; // success

}

start方法会调用faced,调用底层的人脸库,底层库返回结果后会调用onAuthenticated来反馈结果给receiver,在往上层反馈

五、人脸解锁屏幕


frameworks/base/services/core/java/com/android/server/biometrics/AuthenticationClient.java

public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,

boolean authenticated, ArrayList token) {

super.logOnAuthenticated(getContext(), authenticated, mRequireConfirmation,

getTargetUserId(), isBiometricPrompt());

final BiometricServiceBase.ServiceListener listener = getListener();

mMetricsLogger.action(mConstants.actionBiometricAuth(), authenticated);

boolean result = false;

try {

if (DEBUG) Slog.v(getLogTag(), “onAuthenticated(” + authenticated + “)”

  • “, ID:” + identifier.getBiometricId()

  • ", Owner: " + getOwnerString()

  • ", isBP: " + isBiometricPrompt()

  • ", listener: " + listener

  • ", requireConfirmation: " + mRequireConfirmation

  • ", user: " + getTargetUserId());

if (authenticated) {

mAlreadyDone = true;

if (listener != null) {

vibrateSuccess();

}

result = true;

if (shouldFrameworkHandleLockout()) {

resetFailedAttempts();

}

onStop();

final byte[] byteToken = new byte[token.size()];

for (int i = 0; i < token.size(); i++) {

byteToken[i] = token.get(i);

}

if (isBiometricPrompt() && listener != null) {

// BiometricService will add the token to keystore

listener.onAuthenticationSucceededInternal(mRequireConfirmation, byteToken);

} else if (!isBiometricPrompt() && listener != null) {

KeyStore.getInstance().addAuthToken(byteToken);

try {

// Explicitly have if/else here to make it super obvious in case the code is

// touched in the future.

if (!getIsRestricted()) {

/重点关注/

listener.onAuthenticationSucceeded(

getHalDeviceId(), identifier, getTargetUserId());

} else {

listener.onAuthenticationSucceeded(

getHalDeviceId(), null, getTargetUserId());

}

} catch (RemoteException e) {

Slog.e(getLogTag(), “Remote exception”, e);

}

} else {

// Client not listening

Slog.w(getLogTag(), “Client not listening”);

result = true;

}

} else {

if (listener != null) {

vibrateError();

}

// Allow system-defined limit of number of attempts before giving up

final int lockoutMode = handleFailedAttempt();

if (lockoutMode != LOCKOUT_NONE && shouldFrameworkHandleLockout()) {

Slog.w(getLogTag(), “Forcing lockout (driver code should do this!), mode(”

  • lockoutMode + “)”);

stop(false);

final int errorCode = lockoutMode == LOCKOUT_TIMED

? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;

onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);

} else {

// Don’t send onAuthenticationFailed if we’re in lockout, it causes a

// janky UI on Keyguard/BiometricPrompt since “authentication failed”

// will show briefly and be replaced by “device locked out” message.

if (listener != null) {

if (isBiometricPrompt()) {

listener.onAuthenticationFailedInternal(getCookie(),

getRequireConfirmation());

} else {

listener.onAuthenticationFailed(getHalDeviceId());

}

}

}

result = lockoutMode != LOCKOUT_NONE; // in a lockout mode

}

} catch (RemoteException e) {

Slog.e(getLogTag(), “Remote exception”, e);

result = true;

}

return result;

}

frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java

protected interface ServiceListener {

default void onEnrollResult(BiometricAuthenticator.Identifier identifier,

int remaining) throws RemoteException {};

void onAcquired(long deviceId, int acquiredInfo, int vendorCode) throws RemoteException;

/重点关注/

default void onAuthenticationSucceeded(long deviceId,

BiometricAuthenticator.Identifier biometric, int userId) throws RemoteException {

throw new UnsupportedOperationException(“Stub!”);

}

default void onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] token)

throws RemoteException {

throw new UnsupportedOperationException(“Stub!”);

}

default void onAuthenticationFailed(long deviceId) throws RemoteException {

throw new UnsupportedOperationException(“Stub!”);

}

default void onAuthenticationFailedInternal(int cookie, boolean requireConfirmation)

throws RemoteException {

throw new UnsupportedOperationException(“Stub!”);

}

void onError(long deviceId, int error, int vendorCode, int cookie) throws RemoteException;

default void onRemoved(BiometricAuthenticator.Identifier identifier,

int remaining) throws RemoteException {};

default void onEnumerated(BiometricAuthenticator.Identifier identifier,

int remaining) throws RemoteException {};

}

onAuthenticationSucceeded

/**

  • Wraps the callback interface from Service -> BiometricPrompt

*/

protected abstract class BiometricServiceListener implements ServiceListener {

private IBiometricServiceReceiverInternal mWrapperReceiver;

public BiometricServiceListener(IBiometricServiceReceiverInternal wrapperReceiver) {

mWrapperReceiver = wrapperReceiver;

}

public IBiometricServiceReceiverInternal getWrapperReceiver() {

return mWrapperReceiver;

}

@Override

public void onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] token)

throws RemoteException {

if (getWrapperReceiver() != null) {

/重点关注/

getWrapperReceiver().onAuthenticationSucceeded(requireConfirmation, token);

}

}

@Override

public void onAuthenticationFailedInternal(int cookie, boolean requireConfirmation)

throws RemoteException {

if (getWrapperReceiver() != null) {

getWrapperReceiver().onAuthenticationFailed(cookie, requireConfirmation);

}

}

}

frameworks/base/core/java/android/hardware/face/FaceManager.java

private IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {

@Override // binder call

public void onAuthenticationSucceeded(long deviceId, Face face, int userId) {

/重点关注/

mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, face).sendToTarget();

}

MSG_AUTHENTICATION_SUCCEEDED

case MSG_AUTHENTICATION_SUCCEEDED:

/重点关注/

sendAuthenticatedSucceeded((Face) msg.obj, msg.arg1 /* userId */);

break;

sendAuthenticatedSucceeded

private void sendAuthenticatedSucceeded(Face face, int userId) {

if (mAuthenticationCallback != null) {

final AuthenticationResult result =

new AuthenticationResult(mCryptoObject, face, userId);

/重点关注/

mAuthenticationCallback.onAuthenticationSucceeded(result);

}

}

AuthenticationCallback是Fm的一个内部回调接口

public abstract static class AuthenticationCallback

extends BiometricAuthenticator.AuthenticationCallback {

/**

  • Called when an unrecoverable error has been encountered and the operation is complete.

  • No further callbacks will be made on this object.

  • @param errorCode An integer identifying the error message

  • @param errString A human-readable error string that can be shown in UI

*/

public void onAuthenticationError(int errorCode, CharSequence errString) {

}

/**

  • Called when a recoverable error has been encountered during authentication. The help

  • string is provided to give the user guidance for what went wrong, such as

  • “Sensor dirty, please clean it.”

  • @param helpCode An integer identifying the error message

  • @param helpString A human-readable string that can be shown in UI

*/

public void onAuthenticationHelp(int helpCode, CharSequence helpString) {

}

/**

  • Called when a face is recognized.

  • @param result An object containing authentication-related data

*/

/重点关注/

public void onAuthenticationSucceeded(AuthenticationResult result) {

}

/**

  • Called when a face is detected but not recognized.

*/

public void onAuthenticationFailed() {

}

/**

  • Called when a face image has been acquired, but wasn’t processed yet.

  • @param acquireInfo one of FACE_ACQUIRED_* constants

  • @hide

*/

public void onAuthenticationAcquired(int acquireInfo) {

}

}

frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java

AuthenticationCallback接口在KeyguardUpdateMonitor.java中实现,用于监听FaceService中人脸的解锁状态

@VisibleForTesting

FaceManager.AuthenticationCallback mFaceAuthenticationCallback

= new FaceManager.AuthenticationCallback() {

@Override

public void onAuthenticationFailed() {

handleFaceAuthFailed();

}

@Override

public void onAuthenticationSucceeded(FaceManager.AuthenticationResult result) {

Trace.beginSection(“KeyguardUpdateMonitor#onAuthenticationSucceeded”);

/重点关注/

handleFaceAuthenticated(result.getUserId());

Trace.endSection();

}

@Override

public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {

handleFaceHelp(helpMsgId, helpString.toString());

}

@Override

public void onAuthenticationError(int errMsgId, CharSequence errString) {

handleFaceError(errMsgId, errString.toString());

}

@Override

public void onAuthenticationAcquired(int acquireInfo) {

handleFaceAcquired(acquireInfo);

}

};

handleFaceAuthenticated

private void handleFaceAuthenticated(int authUserId) {

Trace.beginSection(“KeyGuardUpdateMonitor#handlerFaceAuthenticated”);

try {

final int userId;

try {

userId = ActivityManager.getService().getCurrentUser().id;

} catch (RemoteException e) {

Log.e(TAG, "Failed to get current user id: ", e);

return;

}

if (userId != authUserId) {

Log.d(TAG, "Face authenticated for wrong user: " + authUserId);

return;

}

if (isFaceDisabled(userId)) {

Log.d(TAG, "Face authentication disabled by DPM for userId: " + userId);

return;

}

/重点关注/

onFaceAuthenticated(userId);

} finally {

setFaceRunningState(BIOMETRIC_STATE_STOPPED);

}

Trace.endSection();

}

onFaceAuthenticated(userId)

protected void onFaceAuthenticated(int userId) {

Trace.beginSection(“KeyGuardUpdateMonitor#onFaceAuthenticated”);

mUserFaceAuthenticated.put(userId, true);

// Update/refresh trust state only if user can skip bouncer

if (getUserCanSkipBouncer(userId)) {

mTrustManager.unlockedByBiometricForUser(userId, BiometricSourceType.FACE);

}

// Don’t send cancel if authentication succeeds

mFaceCancelSignal = null;

for (int i = 0; i < mCallbacks.size(); i++) {

/重点关注/

KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();

if (cb != null) {

/重点关注/

cb.onBiometricAuthenticated(userId,

BiometricSourceType.FACE);

}

}

mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE),

BIOMETRIC_CONTINUE_DELAY_MS);

// Only authenticate face once when assistant is visible

mAssistantVisible = false;

Trace.endSection();

}

这里开始调用接口将解锁成功消息层层传递直至keyguard解锁,与指纹解锁逻辑一致

可以看到在onFaceAuthenticated(userId)方法中调用了KeyguardUpdateMonitorCallback这个抽象类的onBiometricAuthenticated()抽象方法,而BiometricUnlockController extends KeyguardUpdateMonitorCallback,并注册了回调mUpdateMonitor.registerCallback(this)

frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java

/**

  • Called when a biometric is recognized.

  • @param userId the user id for which the biometric sample was authenticated

  • @param biometricSourceType

*/

/重点关注/

public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) { }

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java

@Override

public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {

Trace.beginSection(“BiometricUnlockController#onBiometricAuthenticated”);

if (mUpdateMonitor.isGoingToSleep()) {

mPendingAuthenticatedUserId = userId;

mPendingAuthenticatedBioSourceType = biometricSourceType;

Trace.endSection();

return;

}

mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)

.setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));

/重点关注/

startWakeAndUnlock(calculateMode(biometricSourceType));

}

startWakeAndUnlock(calculateMode(biometricSourceType));

public void startWakeAndUnlock(int mode) {

// TODO(b/62444020): remove when this bug is fixed

Log.v(TAG, “startWakeAndUnlock(” + mode + “)”);

boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();

mMode = mode;

mHasScreenTurnedOnSinceAuthenticating = false;

if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {

// If we are waking the device up while we are pulsing the clock and the

// notifications would light up first, creating an unpleasant animation.

// Defer changing the screen brightness by forcing doze brightness on our window

// until the clock and the notifications are faded out.

mStatusBarWindowController.setForceDozeBrightness(true);

}

// During wake and unlock, we need to draw black before waking up to avoid abrupt

// brightness changes due to display state transitions.

boolean alwaysOnEnabled = DozeParameters.getInstance(mContext).getAlwaysOn();

boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;

Runnable wakeUp = ()-> {

if (!wasDeviceInteractive) {

if (DEBUG_BIO_WAKELOCK) {

Log.i(TAG, “bio wakelock: Authenticated, waking up…”);

}

mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,

“android.policy:BIOMETRIC”);

}

if (delayWakeUp) {

/重点关注/

mKeyguardViewMediator.onWakeAndUnlocking();

}

Trace.beginSection(“release wake-and-unlock”);

releaseBiometricWakeLock();

Trace.endSection();

};

if (!delayWakeUp) {

wakeUp.run();

}

switch (mMode) {

case MODE_DISMISS_BOUNCER:

Trace.beginSection(“MODE_DISMISS”);

mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(

false /* strongAuth */);

Trace.endSection();

break;

case MODE_UNLOCK:

case MODE_SHOW_BOUNCER:

Trace.beginSection(“MODE_UNLOCK or MODE_SHOW_BOUNCER”);

if (!wasDeviceInteractive) {

mPendingShowBouncer = true;

} else {

showBouncer();

}

Trace.endSection();

break;

case MODE_WAKE_AND_UNLOCK_FROM_DREAM:

case MODE_WAKE_AND_UNLOCK_PULSING:

case MODE_WAKE_AND_UNLOCK:

if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {

Trace.beginSection(“MODE_WAKE_AND_UNLOCK_PULSING”);

mMediaManager.updateMediaMetaData(false /* metaDataChanged */,

true /* allowEnterAnimation */);

} else if (mMode == MODE_WAKE_AND_UNLOCK){

Trace.beginSection(“MODE_WAKE_AND_UNLOCK”);

} else {

Trace.beginSection(“MODE_WAKE_AND_UNLOCK_FROM_DREAM”);

mUpdateMonitor.awakenFromDream();

}

mStatusBarWindowController.setStatusBarFocusable(false);

if (delayWakeUp) {

mHandler.postDelayed(wakeUp, mWakeUpDelay);

} else {

mKeyguardViewMediator.onWakeAndUnlocking();

}

if (mStatusBar.getNavigationBarView() != null) {

mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);

}

Trace.endSection();

break;

case MODE_ONLY_WAKE:

case MODE_NONE:

break;

}

mStatusBar.notifyBiometricAuthModeChanged();

Trace.endSection();

}

frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java

public void onWakeAndUnlocking() {

Trace.beginSection(“KeyguardViewMediator#onWakeAndUnlocking”);

mWakeAndUnlocking = true;

/重点关注/

keyguardDone();

Trace.endSection();

}

keyguardDone();

public void keyguardDone() {

Trace.beginSection(“KeyguardViewMediator#keyguardDone”);

if (DEBUG) Log.d(TAG, “keyguardDone()”);

userActivity();

EventLog.writeEvent(70000, 2);

/重点关注/

Message msg = mHandler.obtainMessage(KEYGUARD_DONE);

mHandler.sendMessage(msg);

Trace.endSection();

}

KEYGUARD_DONE

case KEYGUARD_DONE:

Trace.beginSection(“KeyguardViewMediator#handleMessage KEYGUARD_DONE”);

/重点关注/

handleKeyguardDone();

Trace.endSection();

break;

handleKeyguardDone();

private void handleKeyguardDone() {

Trace.beginSection(“KeyguardViewMediator#handleKeyguardDone”);

final int currentUser = KeyguardUpdateMonitor.getCurrentUser();

mUiOffloadThread.submit(() -> {

if (mLockPatternUtils.isSecure(currentUser)) {

mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);

}

});

if (DEBUG) Log.d(TAG, “handleKeyguardDone”);

synchronized (this) {

resetKeyguardDonePendingLocked();

}

mUpdateMonitor.clearBiometricRecognized();

if (mGoingToSleep) {

Log.i(TAG, “Device is going to sleep, aborting keyguardDone”);

return;

}

if (mExitSecureCallback != null) {

try {

mExitSecureCallback.onKeyguardExitResult(true /* authenciated */);

} catch (RemoteException e) {

Slog.w(TAG, “Failed to call onKeyguardExitResult()”, e);

}

mExitSecureCallback = null;

// after succesfully exiting securely, no need to reshow

// the keyguard when they’ve released the lock

mExternallyEnabled = true;

mNeedToReshowWhenReenabled = false;

updateInputRestricted();

}

/重点关注/

handleHide();

Trace.endSection();

}

handleHide();

private void handleHide() {

Trace.beginSection(“KeyguardViewMediator#handleHide”);

// It’s possible that the device was unlocked in a dream state. It’s time to wake up.

if (mAodShowing) {

PowerManager pm = mContext.getSystemService(PowerManager.class);

pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,

“com.android.systemui:BOUNCER_DOZING”);

}

synchronized (KeyguardViewMediator.this) {

if (DEBUG) Log.d(TAG, “handleHide”);

if (mustNotUnlockCurrentUser()) {

// In split system user mode, we never unlock system user. The end user has to

// switch to another user.

// TODO: We should stop it early by disabling the swipe up flow. Right now swipe up

// still completes and makes the screen blank.

if (DEBUG) Log.d(TAG, “Split system user, quit unlocking.”);

return;

}

mHiding = true;

if (mShowing && !mOccluded) {

mKeyguardGoingAwayRunnable.run();

} else {

/重点关注/

handleStartKeyguardExitAnimation(

SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),

mHideAnimation.getDuration());

}

}

Trace.endSection();

}

handleHide();

private void handleHide() {

Trace.beginSection(“KeyguardViewMediator#handleHide”);

// It’s possible that the device was unlocked in a dream state. It’s time to wake up.

if (mAodShowing) {

PowerManager pm = mContext.getSystemService(PowerManager.class);

pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,

“com.android.systemui:BOUNCER_DOZING”);

}

synchronized (KeyguardViewMediator.this) {

if (DEBUG) Log.d(TAG, “handleHide”);

if (mustNotUnlockCurrentUser()) {

// In split system user mode, we never unlock system user. The end user has to

// switch to another user.

// TODO: We should stop it early by disabling the swipe up flow. Right now swipe up

// still completes and makes the screen blank.

if (DEBUG) Log.d(TAG, “Split system user, quit unlocking.”);

return;

}

mHiding = true;

if (mShowing && !mOccluded) {

mKeyguardGoingAwayRunnable.run();

} else {

/重点关注/

handleStartKeyguardExitAnimation(

SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),

mHideAnimation.getDuration());

}

}

Trace.endSection();

}

handleStartKeyguardExitAnimation

private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDuration) {

Trace.beginSection(“KeyguardViewMediator#handleStartKeyguardExitAnimation”);

if (DEBUG) Log.d(TAG, “handleStartKeyguardExitAnimation startTime=” + startTime

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

更多Android高级工程师进阶学习资料

进阶学习视频

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

urn;

}

mHiding = true;

if (mShowing && !mOccluded) {

mKeyguardGoingAwayRunnable.run();

} else {

/重点关注/

handleStartKeyguardExitAnimation(

SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),

mHideAnimation.getDuration());

}

}

Trace.endSection();

}

handleStartKeyguardExitAnimation

private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDuration) {

Trace.beginSection(“KeyguardViewMediator#handleStartKeyguardExitAnimation”);

if (DEBUG) Log.d(TAG, “handleStartKeyguardExitAnimation startTime=” + startTime

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Ilhc4vyU-1712146053864)]
[外链图片转存中…(img-vywDtDd2-1712146053865)]
[外链图片转存中…(img-sUPzN0cX-1712146053865)]
[外链图片转存中…(img-UVcXd6Ru-1712146053866)]
[外链图片转存中…(img-GE2wCztk-1712146053866)]
[外链图片转存中…(img-jAYCOWgR-1712146053866)]
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-LjS7MEQm-1712146053867)]

更多Android高级工程师进阶学习资料

进阶学习视频
[外链图片转存中…(img-kLuQPpgA-1712146053867)]

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-YPnoD8y6-1712146053867)]

里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 14
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值