android锁屏流程_2018-01-14Android 6.0 SystemUI 锁屏流程解析

Android 6.0 SystemUI 锁屏流程解析

谈到锁屏我们先来简单看下systemUI的启动流程

SystemUI常驻于系统,通过Service实现,关键service:SystemUIService是在SystemServer.java中启动。

Android的启动分为内核启动,android启动,Launcher启动,我们的SystemServer就处于Android启动中,SystemUI的启动以下是大致流程:init->ServiceManager->Zygote->SystemServer->SystemUIService-->SystemUIApplication-->SystemUI.start(KeyguardViewMeditor,Recents等SytsemUI子类开始各司其职的正常工作起来)

SystemUI具体的启动流程代码可以参考博客。

设计代码

frameworks/base/packages/Keyguard

frameworks/base/packages/SystemUI

frameworks/base/policy/src/com/android/internal/policy/impl/keyguard/ KeyguardServiceWrapper.java KeyguardServiceDelegate.java frameworks/base/core/java/android/app/keyguardManager.java packages/apps/Settings/src/com/android/settings/ChooseLockGeneric.java SecuritySettings.java

锁屏分类

那么锁屏界面是怎样加载到widnow显示出来的呢?首先需要明确的是6.0分为两类锁屏(非安全锁屏和安全锁屏)

1.非安全锁屏,称之为notification keyguard,这个类型的keyguard 已经和statusbar融为一体,可以通过PhoneStatusBar.java对象直接进行控制;

2.安全锁屏,比如密码,图案,PIN码,PUK码等锁屏的锁屏界面,通过keyguardBouncer.java进行控制

锁屏加载流程

非安全锁屏加载流程

首先非安全锁屏界面,是NotificationPanelView的一部分,在SystemUI启动SystemUI.start就已经加载,看下SystemUI开机启动流程图

因为这里重点是锁屏,所以我们从PhoneStatusBar.start()开启看。

PhoneStatusBar.start会调用父类BaseStatusBar的start(),继续调用PhoneStatusBar的createAndAddWindow(),然后继续调用addStatusBarWindow来创建通知锁屏等StatusBarWindowView并加到window上。

非安全锁屏是NotificationPanelView的一部分,而NotificationPanelView又是StatusBarWindowView的一部分,所以这样就已经将非安全模式加载好了,至于显示还是隐藏就只是NotificationPanelView界面调整的问题了,具体的View层级和控制代码量太多,暂不做深入分析

private void addStatusBarWindow() { makeStatusBarView(); mStatusBarWindowManager = new StatusBarWindowManager(mContext); mRemoteInputController = new RemoteInputController(mStatusBarWindowManager, mHeadsUpManager); mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); }

安全锁屏加载流程

安全锁屏SystemUI启动时准备

上面还只是加载了非安全锁屏界面,那安全锁屏界面呢?实际上安全锁屏界面也会加载到StatusBarWindowView,只不过是动态加载和移除,并不是直接放在布局里初始化加载,我们简单看下锁屏UI层级

在PhoneStatusBar.start()方法里加载完StatusBarWindowView后,还会调用startKeyGuard()来安全锁屏的一些初始化准备工作,这里关注的是将StatusBarWindowView作为属性赋值给安全锁屏的操控类KeyguardBoncerpublic class PhoneStatusBar extends BaseStatusBar implements DemoMode,

DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,

HeadsUpManager.OnHeadsUpChangedListener {

@Override

public void start() {

super.start(); // calls createAndAddWindows()

startKeyguard();

}

private void startKeyguard() {

KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);

//-----这里的mStatusBarWindow就是StatusBarWindowView

mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,

mStatusBarWindow, mStatusBarWindowManager, mScrimController);

mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();

}

}

public class KeyguardViewMediator extends SystemUI {

public StatusBarKeyguardViewManager registerStatusBar(PhoneStatusBar phoneStatusBar,

ViewGroup container, StatusBarWindowManager statusBarWindowManager,

ScrimController scrimController) {

//-----这里的container就是StatusBarWindowView

mStatusBarKeyguardViewManager.registerStatusBar(phoneStatusBar, container,

statusBarWindowManager, scrimController);

return mStatusBarKeyguardViewManager;

}

}

public class StatusBarKeyguardViewManager {

public void registerStatusBar(PhoneStatusBar phoneStatusBar,

ViewGroup container, StatusBarWindowManager statusBarWindowManager,

ScrimController scrimController) {

mPhoneStatusBar = phoneStatusBar;

mContainer = container;

mStatusBarWindowManager = statusBarWindowManager;

mScrimController = scrimController;

mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,

mStatusBarWindowManager, container);

mKeyguardMusicManager = KeyguardMusicManager.getInstance(mContext, this);

}

}

public class KeyguardBouncer {

public KeyguardBouncer(Context context, ViewMediatorCallback callback,

LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,

ViewGroup container) {

mContext = context;

mCallback = callback;

mLockPatternUtils = lockPatternUtils;

mContainer = container;//-----这样就将StatusBarWindowView作为属性赋值给安全锁屏的操控类

mWindowManager = windowManager;

}

}

安全锁屏开机展示流程

时序图

到现在为止还只是StatusBarWindowView与KeyguardBouncer关联,那安全锁屏界面到底是什么时候加载到StatusBarWindowView从而显示给我们呢?实际上我们前面也说了,安全锁屏界面其实是动态的加载和移除的,从未上锁到上锁就会addView,完成全部解锁就会removeView,比如开机完成后就会上锁,下面我们来分析下开机展示安全锁屏流程,首先看下时序图:

代码流程

开机启动流程其实也很复杂,但是本文重点在于KeyGuard锁屏的展示,所以我们从开机启动调用到PhoneWindowManager的SystemReady()和SystemReady()和SystemBooted()方法开始分析。

systemReady()调用systemBooted()之前,至于具体的调用流程这里不做分析,大致也是SystemServer.java中main函数会调用startOtherService()方法跟下去:

那么现在看下去PhoneWindowManager的systemReady()和systemBooted()这两个方法

public class PhoneWindowManager implements WindowManagerPolicy {

@Override

public void systemReady() {

mKeyguardDelegate = new KeyguardServiceDelegate(mContext);

mKeyguardDelegate.onSystemReady();

boolean bindKeyguardNow;

synchronized (mLock) {

bindKeyguardNow = mDeferBindKeyguard;

if (bindKeyguardNow) {

// systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.

mDeferBindKeyguard = false;

}

}

if (bindKeyguardNow) {

mKeyguardDelegate.bindService(mContext);

mKeyguardDelegate.onBootCompleted();

}

}

@Override

public void systemBooted() {

boolean bindKeyguardNow = false;

synchronized (mLock) {

// Time to bind Keyguard; take care to only bind it once, either here if ready or

// in systemReady if not.

if (mKeyguardDelegate != null) {

bindKeyguardNow = true;

} else {

// Because mKeyguardDelegate is null, we know that the synchronized block in

// systemReady didn't run yet and setting this will actually have an effect.

mDeferBindKeyguard = true;

}

}

if (bindKeyguardNow) {

mKeyguardDelegate.bindService(mContext);

mKeyguardDelegate.onBootCompleted();

}

}

看代码可知,systemReady()方法里初始化KeyguardServiceDeleGate,但还不能bindService,等到systemBooted()时才能bindService,下面bindService做了些什么

public class KeyguardServiceDelegate {

protected KeyguardServiceWrapper mKeyguardService;

public void bindService(Context context) {

Intent intent = new Intent();

//-----config_keyguardComponent就是com.android.systemui/com.android.systemui.keyguard.KeyguardService

final ComponentName keyguardComponent = ComponentName.unflattenFromString(

resources.getString(com.android.internal.R.string.config_keyguardComponent));

intent.setComponent(keyguardComponent);

if (!context.bindServiceAsUser(intent, mKeyguardConnection,

Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {}

}

private final ServiceConnection mKeyguardConnection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

mKeyguardService = new KeyguardServiceWrapper(mContext,

IKeyguardService.Stub.asInterface(service));

if (mKeyguardState.systemIsReady) {

// If the system is ready, it means keyguard crashed and restarted.

mKeyguardService.onSystemReady();//-----前面调用systemReady,所以这里成立

// This is used to hide the scrim once keyguard displays.

mKeyguardService.onStartedWakingUp()

mKeyguardService.onScreenTurningOn(

new KeyguardShowDelegate(mDrawnListenerWhenConnect));

mKeyguardService.onScreenTurnedOn();

mDrawnListenerWhenConnect = null;

}

if (mKeyguardState.bootCompleted) {

mKeyguardService.onBootCompleted();

}

if (mKeyguardState.occluded) {

mKeyguardService.setOccluded(mKeyguardState.occluded);

}

}

@Override

public void onServiceDisconnected(ComponentName name) {

if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");

mKeyguardService = null;

}

};

}

因为config_keyguardComponent就是com.android.systemui/com.andoid.systemui.keyguard.KeyguardService,所以IKeyguardService.Stub.asInterface(service)就是KeyguardService里的private final IKeyguardService.Stub mBinder,也就是KeyguardServiceWrapper里的private IKeyguardService mService,所以接着调用onSystemReady()

public class KeyguardServiceWrapper implements IKeyguardService {

private IKeyguardService mService;

public KeyguardServiceWrapper(Context context, IKeyguardService service) {

mService = service;

}

@Override // Binder interface

public void onSystemReady() {

try {

mService.onSystemReady();

} catch (RemoteException e) {

Slog.w(TAG , "Remote Exception", e);

}

}

}

于是再走到KeyguardService.mBinder.onSystemReady()

public class KeyguardService extends Service {

private KeyguardViewMediator mKeyguardViewMediator;

private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {

@Override // Binder interface

public void onSystemReady() {

checkPermission();

mKeyguardViewMediator.onSystemReady();

}

}

}

终于走到我们锁屏模块最关键的调度类KeyguardViewMediator,功能上负责处理keyguard试图的事件,锁屏事件的入口,下面继续KeyguardViewMediator的doKeyguardLocked()

public class KeyguardViewMediator extends SystemUI {

public void onSystemReady() {

doKeyguardLocked(null);

}

private void doKeyguardLocked(Bundle options) {

showLocked(options);

}

private void showLocked(Bundle options) {

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);

mHandler.sendMessage(msg);

}

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;

}

}

};

private void handleShow(Bundle options) {

mStatusBarKeyguardViewManager.show(options);

}

}

通过代码可知,最后将show动作交给StatusBarkeyguardViewManager来处理,实际上这类直接锁屏相关动作最后都会交给StatusbarKeyguardViewManager处理,StatusBarKeyguardViewManager就是keyguard的视图管理者,包括非安全锁屏和安全锁屏,接着往下看

public class StatusBarKeyguardViewManager {

private PhoneStatusBar mPhoneStatusBar;

private KeyguardBouncer mBouncer;

/**

* 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();//-----show和reset动作都会调用reset

mKeyguardMusicManager.start();

}

/**

* Reset the state of the view.

*/

public void reset() {

if (mShowing) {

if (mOccluded) {

mPhoneStatusBar.hideKeyguard();

mPhoneStatusBar.stopWaitingForKeyguardExit();

mBouncer.hide(false /* destroyView */);

} else {

showBouncerOrKeyguard();//-----显示安全锁屏界面还是先显示非安全锁屏界面

}

KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();

updateStates();

}

}

/**

* Shows the notification keyguard or the bouncer depending on

* {@link KeyguardBouncer#needsFullscreenBouncer()}.

*/

private void showBouncerOrKeyguard() {

if (mBouncer.needsFullscreenBouncer()) {

// The keyguard might be showing (already). So we need to hide it.

mPhoneStatusBar.hideKeyguard();

mBouncer.show(true /* resetSecuritySelection */);

} else {

mPhoneStatusBar.showKeyguard();

mBouncer.hide(false /* destroyView */);

mBouncer.prepare();

}

}

}

在showBouncerOrKeyguard方法里mPhoneStatusBar.hideKeyguard()和mPhoneStatusBar.showKeyguard;控制的是非安全锁,而mBoncer.show(true)和mBoncer.hide(false)控制的是安全锁屏,也就是说非安全锁屏和安全锁屏在这里开始分别由PhoneStatusBar和KeyguardBouncer管理,前面说了非安全锁屏这里不做升入分析,下面重点看安全锁屏,安全锁屏界面KeyguardHostView作为KeyguardBouncer的属性直接被操控,而要不要先显示非安全锁屏是根据锁屏模式来的,由于锁屏情况太多现在假设是图案解锁,具体在往下来,根据目前场景来看是会走到

/**

* A class which manages the bouncer on the lockscreen.

*/

public class KeyguardBouncer {

private KeyguardHostView mKeyguardView;

/**

* @return True if and only if the security method should be shown before showing the

* notifications on Keyguard, like SIM PIN/PUK.

*/

public boolean needsFullscreenBouncer() {

ensureView();//-----a

if (mKeyguardView != null) {

SecurityMode mode = mKeyguardView.getSecurityMode();

return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;//-----c

}

return false;

}

public void show(boolean resetSecuritySelection) {//-----实际上显示、重置、移除动作都会调用到

ensureView();//----确保安全锁屏界面有创建并添加到StatusBarWindowView上,并且安全界面初始化时是不可见的INVISIBLE

if (resetSecuritySelection) {//-----是否需要重置安全界面

// showPrimarySecurityScreen() updates the current security method. This is needed in

// case we are already showing and the current security method changed.

mKeyguardView.showPrimarySecurityScreen();//-----d

}

if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {//-----mRoot是安全锁屏界面,当已是可见是return,比如重置

return;

}

// Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole

// Keyguard. If we need to authenticate, show the bouncer.

if (!mKeyguardView.dismiss()) {//-----试图移除锁屏界面,比如刚上锁,安全界面还不可见//-----e

mShowingSoon = true; // Split up the work over multiple frames.

DejankUtils.postAfterTraversal(mShowRunnable);//-----安全界面设置成可见VISIBLE//-----f

}

}

private final Runnable mShowRunnable = new Runnable() {

@Override

public void run() {

mRoot.setVisibility(View.VISIBLE);

mKeyguardView.onResume();

showPromptReason(mBouncerPromptReason);

mKeyguardView.startAppearAnimation();

mShowingSoon = false;

mKeyguardView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);

}

};

private void ensureView() {

if (mRoot == null) {//-----安全界面跟布局,一般无锁到有锁初始化,完全完成解锁时置空

inflateView();//-----b

}

}

private void inflateView() {

removeView();

mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);

mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view);

mKeyguardView.setLockPatternUtils(mLockPatternUtils);

mKeyguardView.setViewMediatorCallback(mCallback);

mContainer.addView(mRoot, mContainer.getChildCount());

mRoot.setVisibility(View.INVISIBLE);

mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);

}

}

接着看mKeyguardView.showPrimarySecurityScreen(),KeyguardHostView是安全锁屏主界面,实现了SecrityCallBack接口,其他地方用到的SeurityCakkback其实就是KeyguardHostview

public class KeyguardHostView extends FrameLayout implements SecurityCallback {

private KeyguardSecurityContainer mSecurityContainer;

/**

* Called when the view needs to be shown.

*/

public void showPrimarySecurityScreen() {

if (DEBUG) Log.d(TAG, "show()");

mSecurityContainer.showPrimarySecurityScreen(false);

}

}

KeyguardSecurityContainer,安全锁屏View的容,会具体根据安全模式展示不同的View,继续往下面

public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {

private KeyguardSecurityViewFlipper mSecurityViewFlipper;//安全view的父布局

/**

* Shows the primary security screen for the user. This will be either the multi-selector

* or the user's security method.

* @param turningOff true if the device is being turned off

*/

void showPrimarySecurityScreen(boolean turningOff) {

SecurityMode securityMode = mSecurityModel.getSecurityMode();//----获取安全模式

if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");

showSecurityScreen(securityMode);

}

private void showSecurityScreen(SecurityMode securityMode) {

if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");

if (securityMode == mCurrentSecuritySelection) return;

KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);

KeyguardSecurityView newView = getSecurityView(securityMode);

// Emulate Activity life cycle

if (oldView != null) {

oldView.onPause();

oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view

}

if (securityMode != SecurityMode.None) {

newView.onResume(KeyguardSecurityView.VIEW_REVEALED);

newView.setKeyguardCallback(mCallback);

}

// Find and show this child.

final int childCount = mSecurityViewFlipper.getChildCount();

final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);

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

if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {

mSecurityViewFlipper.setDisplayedChild(i);

break;

}

}

mCurrentSecuritySelection = securityMode;

mSecurityCallback.onSecurityModeChanged(securityMode,

securityMode != SecurityMode.None && newView.needsInput());

}

private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {

final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);

KeyguardSecurityView view = null;

final int children = mSecurityViewFlipper.getChildCount();

for (int child = 0; child < children; child++) {

if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {

view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));

break;

}

}

int layoutId = getLayoutIdFor(securityMode);

if (view == null && layoutId != 0) {

final LayoutInflater inflater = LayoutInflater.from(mContext);

if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);

View v = inflater.inflate(layoutId, mSecurityViewFlipper, false);

mSecurityViewFlipper.addView(v);//----将安全view添加到父布局KeyguardSecurityViewFlipper从而到KeyguardSecurityContainer上

updateSecurityView(v);

view = (KeyguardSecurityView)v;

}

return view;

}

}

到目前位置通过mSercutityViewFliper.addView(v);最终将安全view添加到StatusBarWindowView,但是安全锁屏跟布局还是不可见的,所以代码走到KeyguardBouncer的处,那么mKeyguardView.dismiss()又做了什么呢,继续往下跟

public class KeyguardHostView extends FrameLayout implements SecurityCallback {

/**

*  Dismisses the keyguard by going to the next screen or making it gone.

*

*  @return True if the keyguard is done.

*/

public boolean dismiss() {

return dismiss(false);

}

@Override

public boolean dismiss(boolean authenticated) {

return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated);

}

}

好吧,又是KeyguardSecurityContainer,当前场景下参数未false,继续往下看:

/**

* Shows the next security screen if there is one.

* @param authenticated true if the user entered the correct authentication

* @return true if keyguard is done

*/

//-----显示下一个安全锁屏界面,参数很重要,参数表示是否经过验证

boolean showNextSecurityScreenOrFinish(boolean authenticated) {

if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");

boolean finish = false;

if (mUpdateMonitor.getUserCanSkipBouncer(

KeyguardUpdateMonitor.getCurrentUser())) {

//-----可以跳过安全锁屏,直接完全所有锁屏

finish = true;

} else if (SecurityMode.None == mCurrentSecuritySelection) {

//当前是非安全锁屏(滑动),获取下一个锁屏模式,如果还是非安全锁屏(滑动),直接完全所有锁屏,否则显示下一个安全锁屏界面

SecurityMode securityMode = mSecurityModel.getSecurityMode();

if (SecurityMode.None == securityMode) {

finish = true; // no security required

} else {

showSecurityScreen(securityMode); // switch to the alternate security view

}

} else if (authenticated) {

//-----如果是经过验证的,当前的是普通的安全模式,那么完成全部解锁,如果是pin\puk之类的第三类动态的就继续检查下一个锁屏,

//-----下一个是安全锁屏就继续显示下一个安全锁屏界面,否则完成全部解锁

switch (mCurrentSecuritySelection) {

case Pattern:

case Password:

case PIN:

finish = true;

break;

case SimPin:

case SimPuk:

// Shortcut for SIM PIN/PUK to go to directly to user's security screen or home

SecurityMode securityMode = mSecurityModel.getSecurityMode();

if (securityMode != SecurityMode.None

|| !mLockPatternUtils.isLockScreenDisabled(

KeyguardUpdateMonitor.getCurrentUser())) {

showSecurityScreen(securityMode);

/* SPRD:add PIN verify success prompt @{ */

KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);

if (oldView != null) {

oldView.onPause();

}

/* @} */

} else {

finish = true;

}

break;

default:

Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");

showPrimarySecurityScreen(false);

break;

}

}

if (finish) {

//-----完成了全部解锁,下面要开始rm安全界面等一些操作,mSecurityCallback就是KeyguardHostView

mSecurityCallback.finish();

}

return finish;

}

当前场景下都不满足,直接返回false,那么代码继续走到KeyguardBouncer的处,也就是把安全锁屏根布局设置为可见mRoot.setVisibility(View.VISIBLE);最终锁屏控件都已加载到StatusBarWindowView上且可见

锁屏调用入口

其他场景,如解锁,灭屏等按照上面的思路结构都很容易分析就不再赘述,调用入口目前如下几种情况;

1KeyguardSecurityCallBack.dismiss(true)-->KeyguardSecurityContainer.SecurityCallback.dismiss(true)-->实际上对象就是KeyguardHostView.dismiss(true)-->......这中一般是解锁了安全锁屏onClick里

2ViewMeditorCallback-->实际对象就是KeyguardViewMeditor.mViewMeditorCallback

这种一般是应用内直接调用,比如添加手机防盗解锁,受到上锁广播时直接调用showLocked(null)或resetStatLocked()

3、KeyguardServiceDelegate-->绑定KeyguardService

signature:这种权限级别,只有当发请求的应用和接收此请求的应用使用同一签名文件,并且声明了该权限才会授权,并且是默认授权,不会提示用户授权       这种一般是frameworks通过binder服务调用,如开机上锁,灭屏上锁等

4、通过属性android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUAR                       android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKE

第三方应用一般因为权限问题通过属性来控制消除非安全锁屏或界面显示在锁之上

总结

最后关于锁屏再总结一下:

ui层级图

UI时序图

1、锁屏分两类:非安全锁屏(如滑动锁屏)和安全锁屏(滑动锁屏)

2、他们都会加载到StatusBarWindowView上,而StatusBarWindowView在又会加载到window上从而显示出来

3、不同的是: 非安全锁屏在PanelHolder上,是StatusBarWindowView布局的一部分,所以随着开机加载systemui时就会加载上去,通过展开折叠等布局控制来显示与否 而安全锁屏是KeyguardHostView,它并不是StatusBarWindowView原有布局的一部分,而是根据上锁和解锁实际情况来动态加载和移除以及设置可见与不可见来显示与否,第一次加载是在完成开机动画触屏可显示时

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值