今天開(kāi)始梳理SystemUI Keyguard源碼
話不多說(shuō)首先從啟動(dòng)流程開(kāi)始:
起點(diǎn)是在 SystemUI/src/com/android/systemui/SystemUIService.java
onCreate() -> ((SystemUIApplication) getApplication()).startServicesIfNeeded();
啟動(dòng)SystemUI各個(gè)模塊
SystemUI/src/com/android/systemui/SystemUIApplication.java
public void startServicesIfNeeded() {
startServicesIfNeeded(SERVICES);
}
private void startServicesIfNeeded(Class<?>[] services) {
..
startServicesIfNeeded()-> Object newService = SystemUIFactory.getInstance().createInstance(cl);
..
mServices[i].start();
..
if (mBootCompleted) {
mServices[i].onBootCompleted();
}
}
我們這里主要關(guān)注KeyguardViewMediator:
SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@Override
public void start() {
synchronized (this) {
setupLocked();
}
putComponent(KeyguardViewMediator.class, this);
}
private void setupLocked() {
// 獲取PowerManager
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
// 獲取TrustManager
mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
// 創(chuàng)建PARTIAL_WAKE_LOCK
mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
// 設(shè)置WakeLock為不計(jì)數(shù)機(jī)制
mShowKeyguardWakeLock.setReferenceCounted(false);
// 注冊(cè)廣播監(jiān)聽(tīng)
IntentFilter filter = new IntentFilter();
filter.addAction(DELAYED_KEYGUARD_ACTION);
filter.addAction(DELAYED_LOCK_PROFILE_ACTION);
filter.addAction(Intent.ACTION_SHUTDOWN);
mContext.registerReceiver(mBroadcastReceiver, filter);
mKeyguardDisplayManager = new KeyguardDisplayManager(mContext, mViewMediatorCallback);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
// KeyguardUpdateMontitor注冊(cè)一堆廣播監(jiān)聽(tīng)和Listener
mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
mLockPatternUtils = new LockPatternUtils(mContext);
KeyguardUpdateMonitor.setCurrentUser(ActivityManager.getCurrentUser());
// Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
// is disabled.
if (mContext.getResources().getBoolean(
com.android.keyguard.R.bool.config_enableKeyguardService)) {
setShowingLocked(!shouldWaitForProvisioning()
&& !mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser()),
mSecondaryDisplayShowing, true /* forceCallbacks */);
}
// 把statusbar和keyguard關(guān)聯(lián)起來(lái)步做,將mViewMediatorCallback傳給mStatusBarKeyguardViewManager
mStatusBarKeyguardViewManager =
SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
mViewMediatorCallback, mLockPatternUtils);
final ContentResolver cr = mContext.getContentResolver();
/* 獲取設(shè)備可交互狀態(tài)
true : 包括dreaming
false: dozing或asleep
* The system will send a {@link android.content.Intent#ACTION_SCREEN_ON screen on}
* or {@link android.content.Intent#ACTION_SCREEN_OFF screen off} broadcast
* whenever the interactive state of the device changes. For historical reasons,
* the names of these broadcasts refer to the power state of the screen
* but they are actually sent in response to changes in the overall interactive
* state of the device, as described by this method.*/
mDeviceInteractive = mPM.isInteractive();
// 加載鎖屏解鎖音頻和音量
mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);
if (soundPath != null) {
mLockSoundId = mLockSounds.load(soundPath, 1);
}
..
..
int lockSoundDefaultAttenuation = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lockSoundVolumeDb);
mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
// 加載動(dòng)畫 (僅用于獲得動(dòng)畫時(shí)間偏移量)
mHideAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.lock_screen_behind_enter);
mWorkLockController = new WorkLockActivityController(mContext);
}
關(guān)于WakeLock:
WakeLock計(jì)數(shù)機(jī)制(setReferenceCounted):
在創(chuàng)建了PowerManager.WakeLock 后眉撵,有兩種機(jī)制,第一種是不計(jì)數(shù)鎖機(jī)制蒲肋,另一種是計(jì)數(shù)鎖機(jī)制乒省。這可以通過(guò)setReferenceCounted( boolean value) 來(lái)指定巧颈,默認(rèn)為計(jì)數(shù)機(jī)制。這兩種機(jī)制的區(qū)別在于袖扛,前者無(wú)論acquire() 了多少次砸泛,只要通過(guò)一次release() 即可解鎖。而后者正真解鎖是在(--count == 0 )的時(shí)候,同樣當(dāng)(count == 0) 的時(shí)候才會(huì)去申請(qǐng)加鎖晾嘶,其他情況下isHeld 狀態(tài)是不會(huì)改變的妓雾。所以PowerManager.WakeLock 的計(jì)數(shù)機(jī)制并不是正真意義上的對(duì)每次請(qǐng)求進(jìn)行申請(qǐng)/釋放每一把鎖,它只是對(duì)同一把鎖被申請(qǐng)/釋放的次數(shù)進(jìn)行了統(tǒng)計(jì)垒迂。
KeyguardService的啟動(dòng):
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
@Override
/**
* Called when the system is done booting to the point where the
* user can start interacting with it.
*/
public void systemBooted() {
bindKeyguard();
..
}
frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
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);
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
Context.BIND_AUTO_CREATE, mHandler, UserHandle.SYSTEM)) {
..
}
private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
// KeyguardServiceWrapper包裝類調(diào)用KeyguardService的Binder實(shí)例
mKeyguardService = new KeyguardServiceWrapper(mContext,
IKeyguardService.Stub.asInterface(service), mCallback);
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);
}
// 調(diào)用KeyguardService的IPC接口
..
..
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
mKeyguardService = null;
mKeyguardState.reset();
..
}
};
在綁定以后械姻,PhoneWindowManager可以調(diào)用代理類KeyguardServiceDelegate間接調(diào)用KeyguardService的binder接口進(jìn)行各種鎖屏相關(guān)狀態(tài)回調(diào)。
初次開(kāi)機(jī)Keyguard showLock流程:
系統(tǒng)啟動(dòng)完成-->PhoneWindowManager.systemReady()-->mKeyguardDelegate.onSystemReady()
-->mKeyguardService.onSystemReady()-->KeyguardService.onSystemReady()
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();
}
frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
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) {
// 判斷是不是安全啟動(dòng)
if (KeyguardUpdateMonitor.CORE_APPS_ONLY) {
// Don't show keyguard during half-booted cryptkeeper stage.
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because booting to cryptkeeper");
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;
}
..
..
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) {
// 持有mShowKeyguardWakeLock
// ensure we stay awake until we are finished displaying the keyguard
mShowKeyguardWakeLock.acquire();
Message msg = mHandler.obtainMessage(SHOW, options);
mHandler.sendMessage(msg);
Trace.endSection();
}
/**
* Handle message sent by {@link #showLocked}.
* @see #SHOW
*/
private void handleShow(Bundle options) {
..
synchronized (KeyguardViewMediator.this) {
..
setShowingLocked(true);
// 顯示keyguard
mStatusBarKeyguardViewManager.show(options);
..
// 釋放mShowKeyguardWakeLock
mShowKeyguardWakeLock.release();
}
mKeyguardDisplayManager.show();
Trace.endSection();
}
接下來(lái)就要處理Keyguard繪制的邏輯了机断,這部分主要是在StatusBarKeyguardViewManager中
調(diào)用showBouncerOrKeyguard()方法去顯示notification keyguard還是bouncer,在滅屏的情況下楷拳,再次亮屏看到的一般是notification keyguard,就是有消息通知吏奸、時(shí)間之類的那個(gè)view欢揖,上滑才會(huì)顯示密碼解鎖界面,也就是bouncer奋蔚。接著就會(huì)調(diào)用showKeyguard()她混,當(dāng)然由于還沒(méi)有繪制內(nèi)容,所以會(huì)進(jìn)行keyguard的繪制。這里會(huì)調(diào)用hideBouncer()去隱藏已有的bouncer泊碑,因?yàn)橄麓瘟疗恋臅r(shí)候可能不是原來(lái)的鎖屏方式坤按。例如原來(lái)是PIN解鎖,而我們?cè)趕ettings去重置了鎖屏為pattern馒过,那下次亮屏就應(yīng)該顯示pattern的view臭脓。
/**
* 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 */);
}
/**
* Shows the notification keyguard or the bouncer depending on
* {@link KeyguardBouncer#needsFullscreenBouncer()}.
*/
protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
if (mBouncer.needsFullscreenBouncer() && !mDozing) {
// The keyguard might be showing (already). So we need to hide it.
mStatusBar.hideKeyguard();
mBouncer.show(true /* resetSecuritySelection */);
} else {
mStatusBar.showKeyguard();
if (hideBouncerWhenShowing) {
hideBouncer(false /* destroyView */);
mBouncer.prepare();
}
}
updateStates();
}
參考文檔:
https://developer.android.google.cn/reference/android/os/PowerManager
https://blog.csdn.net/zhandoushi1982/article/details/8513203
https://blog.csdn.net/qq_28147169/article/details/79467159