基于android 8.0 原生锁屏流程源码分析
1.首先从phoneWindowManager 中开始往下走:
frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs) {
mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
new StateCallback() {
@Override
public void onTrustedChanged() {
mWindowManagerFuncs.notifyKeyguardTrustedChanged();
}
});
}
}
@Override
public void systemReady() {
// So it is better not to bind keyguard here.
mKeyguardDelegate.onSystemReady();
}
2. KeyguardServiceDelegate
frameworks\base\services\core\java\com\android\server\policy\keyguard\KeyguardServiceDelegate.java
protected KeyguardServiceWrapper mKeyguardService;
public void onSystemReady() {
if (mKeyguardService != null) {
mKeyguardService.onSystemReady();
} else {
mKeyguardState.systemIsReady = true;
}
}
//接下来看一下 mKeyguardService 的是如何初始化的。
public void bindService(Context context) {
Intent intent = new Intent();
final Resources resources = context.getApplicationContext().getResources();
final ComponentName keyguardComponent = ComponentName.unflattenFromString(
resources.getString(com.android.internal.R.string.config_keyguardComponent));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
intent.setComponent(keyguardComponent);
// 这里可以看到 bind的服务为 com.android.systemui/com.android.systemui.keyguard.KeyguardService,这里实现了跨进程
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
Context.BIND_AUTO_CREATE, mHandler, UserHandle.SYSTEM)) {
Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent);
mKeyguardState.showing = false;
mKeyguardState.showingAndNotOccluded = false;
mKeyguardState.secure = false;
synchronized (mKeyguardState) {
// TODO: Fix synchronisation model in this class. The other state in this class
// is at least self-healing but a race condition here can lead to the scrim being
// stuck on keyguard-less devices.
mKeyguardState.deviceHasKeyguard = false;
}
} else {
if (DEBUG) Log.v(TAG, "*** Keyguard started");
}
}
private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
mKeyguardService = new KeyguardServiceWrapper(mContext,
IKeyguardService.Stub.asInterface(service), mCallback);
// 这里的mKeyguardService实际上还是KeyguardServiceWrapper对象,
if (mKeyguardState.systemIsReady) {
// If the system is ready, it means keyguard crashed and restarted.
mKeyguardService.onSystemReady();
if (mKeyguardState.currentUser != UserHandle.USER_NULL) {
// There has been a user switch earlier
mKeyguardService.setCurrentUser(mKeyguardState.currentUser);
}
// This is used to hide the scrim once keyguard displays.
if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
mKeyguardService.onStartedWakingUp();
}
if (mKeyguardState.screenState == SCREEN_STATE_ON
|| mKeyguardState.screenState == SCREEN_STATE_TURNING_ON) {
mKeyguardService.onScreenTurningOn(
new KeyguardShowDelegate(mDrawnListenerWhenConnect));
}
if (mKeyguardState.screenState == SCREEN_STATE_ON) {
mKeyguardService.onScreenTurnedOn();
}
mDrawnListenerWhenConnect = null;
}
if (mKeyguardState.bootCompleted) {
mKeyguardService.onBootCompleted();
}
if (mKeyguardState.occluded) {
mKeyguardService.setOccluded(mKeyguardState.occluded, false /* animate */);
}
if (!mKeyguardState.enabled) {
mKeyguardService.setKeyguardEnabled(mKeyguardState.enabled);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
mKeyguardService = null;
mKeyguardState.reset();
mHandler.post(() -> {
try {
ActivityManager.getService().setLockScreenShown(true);
} catch (RemoteException e) {
// Local call.
}
});
}
};
3.KeyguardServiceWrapper.java
frameworks\base\services\core\java\com\android\server\policy\keyguard\KeyguardServiceWrapper.java
//可以看到构造函数中上面new的是这个,这个service实际上才是bind过来的service
public KeyguardServiceWrapper(Context context, IKeyguardService service,
KeyguardStateMonitor.StateCallback callback) {
mService = service;
mKeyguardStateMonitor = new KeyguardStateMonitor(context, service, callback);
}
@Override // Binder interface
public void onSystemReady() {
try {
mService.onSystemReady();
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
4. 接下来看一下跨进程的aidl文件,当然如果你想要在systemUI里面封装一个方法给framework 调用,别往了也要在这里加上
frameworks\base\core\java\com\android\internal\policy\IKeyguardService.aidl
oneway interface IKeyguardService {
/**
* Sets the Keyguard as occluded when a window dismisses the Keyguard with flag
* FLAG_SHOW_ON_LOCK_SCREEN.
*
* @param isOccluded Whether the Keyguard is occluded by another window.
* @param animate Whether to play an animation for the state change.
*/
void setOccluded(boolean isOccluded, boolean animate);
void addStateMonitorCallback(IKeyguardStateCallback callback);
void verifyUnlock(IKeyguardExitCallback callback);
void dismiss(IKeyguardDismissCallback callback);
void onDreamingStarted();
void onDreamingStopped();
/**
* Called when the device has started going to sleep.
*
* @param why {@link #OFF_BECAUSE_OF_USER}, {@link #OFF_BECAUSE_OF_ADMIN},
* or {@link #OFF_BECAUSE_OF_TIMEOUT}.
*/
void onStartedGoingToSleep(int reason);
/**
* Called when the device has finished going to sleep.
*
* @param why {@link #OFF_BECAUSE_OF_USER}, {@link #OFF_BECAUSE_OF_ADMIN},
* or {@link #OFF_BECAUSE_OF_TIMEOUT}.
* @param cameraGestureTriggered whether the camera gesture was triggered between
* {@link #onStartedGoingToSleep} and this method; if it's been
* triggered, we shouldn't lock the device.
*/
void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered);
/**
* Called when the device has started waking up.
*/
void onStartedWakingUp();
/**
* Called when the device screen is turning on.
*/
void onScreenTurningOn(IKeyguardDrawnCallback callback);
/**
* Called when the screen has actually turned on.
*/
void onScreenTurnedOn();
/**
* Called when the screen has turned off.
*/
void onScreenTurnedOff();
void setKeyguardEnabled(boolean enabled);
void onSystemReady();
void doKeyguardTimeout(in Bundle options);
void setSwitchingUser(boolean switching);
void setCurrentUser(int userId);
void onBootCompleted();
/**
* Notifies that the activity behind has now been drawn and it's safe to remove the wallpaper
* and keyguard flag.
*
* @param startTime the start time of the animation in uptime milliseconds
* @param fadeoutDuration the duration of the exit animation, in milliseconds
*/
void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
/**
* Notifies the Keyguard that the power key was pressed while locked and launched Home rather
* than putting the device to sleep or waking up.
*/
void onShortPowerPressedGoHome();
}
5. 终于跨进程到了 SystemUI 中
frameworks\base\packages\SystemUI\src\com\android\systemui\keyguard\KeyguardService.java
@Override // Binder interface
public void onSystemReady() {
Trace.beginSection("KeyguardService.mBinder#onSystemReady");
checkPermission();
mKeyguardViewMediator.onSystemReady();
Trace.endSection();
}
这里还要单独说明一下,看一下SystemUI 中AndroidManifest 文件中KeyguardService 的定义,可以看到如果想要开启android 原生的keyguard 锁屏,则必须在config 中打开config_enableKeyguardService
<service
android:name=".keyguard.KeyguardService"
android:exported="true"
android:enabled="@bool/config_enableKeyguardService" />
6.KeyguardViewMediator.java 锁屏的核心调用类
frameworks\base\packages\SystemUI\src\com\android\systemui\keyguard\KeyguardViewMediator.java
/**
* Let us know that the system is ready after startup.
*/
public void onSystemReady() {
synchronized (this) {
if (DEBUG) Log.d(TAG, "onSystemReady");
mSystemReady = true;
doKeyguardLocked(null); // 调用此方法
mUpdateMonitor.registerCallback(mUpdateCallback);
}
// Most services aren't available until the system reaches the ready state, so we
// send it here when the device first boots.
maybeSendUserPresentBroadcast();
}
/**
* Enable the keyguard if the settings are appropriate.
这个方法里面主要都是用来判断是否显示锁屏的一些条件
*/
private void doKeyguardLocked(Bundle options) {
// if another app is disabling us, don't show
if (!mExternallyEnabled) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
//其他第三方应用如果禁止了锁屏,则直接返回不显示
// note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
// for an occasional ugly flicker in this situation:
// 1) receive a call with the screen on (no keyguard) or make a call
// 2) screen times out
// 3) user hits key to turn screen back on
// instead, we reenable the keyguard when we know the screen is off and the call
// ends (see the broadcast receiver below)
// TODO: clean this up when we have better support at the window manager level
// for apps that wish to be on top of the keyguard
return;
}
// 如果锁屏正在显示
// if the keyguard is already showing, don't bother
if (mStatusBarKeyguardViewManager.isShowing()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
resetStateLocked();
return;
}
// In split system user mode, we never unlock system user.
if (!mustNotUnlockCurrentUser()
|| !mUpdateMonitor.isDeviceProvisioned()) {
// if the setup wizard hasn't run yet, don't show
final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false); //获取sim卡状态
final boolean absent = SubscriptionManager.isValidSubscriptionId(
mUpdateMonitor.getNextSubIdForState(ABSENT));
final boolean disabled = SubscriptionManager.isValidSubscriptionId(
mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.PERM_DISABLED));
final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()
|| ((absent || disabled) && requireSim);
if (!lockedOrMissing && shouldWaitForProvisioning()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
+ " and the sim is not locked or missing");
return;
}
// settings 中是否有启用锁屏
boolean forceShow = options != null && options.getBoolean(OPTION_FORCE_SHOW, false);
if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
&& !lockedOrMissing && !forceShow) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
return;
}
if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
// Without this, settings is not enabled until the lock screen first appears
setShowingLocked(false);
hideLocked();
mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();
return;
}
}
if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
showLocked(options); // 接下来调用这个
}
/**
* Send message to keyguard telling it to show itself
* @see #handleShow
*/
private void showLocked(Bundle options) {
Trace.beginSection("KeyguardViewMediator#showLocked aqcuiring mShowKeyguardWakeLock");
if (DEBUG) Log.d(TAG, "showLocked");
// ensure we stay awake until we are finished displaying the keyguard
mShowKeyguardWakeLock.acquire();
Message msg = mHandler.obtainMessage(SHOW, options); //发消息去show
mHandler.sendMessage(msg);
Trace.endSection();
}
*/
private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW:
handleShow((Bundle) msg.obj);
break;
// show的方法。
/**
* Handle message sent by {@link #showLocked}.
* @see #SHOW
*/
private void handleShow(Bundle options) {
Trace.beginSection("KeyguardViewMediator#handleShow");
final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
if (mLockPatternUtils.isSecure(currentUser)) {
mLockPatternUtils.getDevicePolicyManager().reportKeyguardSecured(currentUser);
}
synchronized (KeyguardViewMediator.this) {
if (!mSystemReady) {
if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready.");
return;
} else {
if (DEBUG) Log.d(TAG, "handleShow");
}
setShowingLocked(true);
mStatusBarKeyguardViewManager.show(options); // 这个方法
mHiding = false;
mWakeAndUnlocking = false;
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
adjustStatusBarLocked();
userActivity();
mShowKeyguardWakeLock.release();
}
mKeyguardDisplayManager.show();
Trace.endSection();
}
/**
* Show the keyguard. Will handle creating and attaching to the view manager
* lazily.
*/
public void show(Bundle options) {
mShowing = true;
mStatusBarWindowManager.setKeyguardShowing(true);
mScrimController.abortKeyguardFadingOut();
reset(true /* hideBouncerWhenShowing */);
}
/**
* Reset the state of the view.
*/
public void reset(boolean hideBouncerWhenShowing) {
if (mShowing) {
if (mOccluded) {
mStatusBar.hideKeyguard();
mStatusBar.stopWaitingForKeyguardExit();
mBouncer.hide(false /* destroyView */);
} else {
判断是调用安全锁屏还是调用滑动锁屏
showBouncerOrKeyguard(hideBouncerWhenShowing);
}
KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
updateStates();
}
}