android 4.2以上系统锁屏框架
主要类:
工作路径: frameworks/base/packages/keyguard
--> KeyguardViewModiator.java
在上述中有给出一系列的判断是否锁屏,比如在用户按下PowerOff的时候,会给出一定缓冲时间来避免用户执行后悔动作。处理了闹钟事件下的动作。
调用视图显示:
--> KeyguardViewManager.java
主要类:
工作路径: frameworks/base/packages/keyguard
--> KeyguardViewModiator.java
调度器中开始执行锁屏动作
doKeyguardLocked(Bundle options)--> showLocked(options)
-->
/**
* Send message to keyguard telling it to show itself
* @see #handleShow()
*/
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);
}
查找Handler消息处理中心调用,handleShow((Bundle) msg.obj);
/**
* Handle message sent by {@link #showLocked}.
* @see #SHOW
*/
private void handleShow(Bundle options) {
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");
}
mKeyguardViewManager.show(options);
if (DEBUG) KeyguardUtils.xlogD(TAG, "handleShow mKeyguardViewManager Show done");
mShowing = true;
mKeyguardDonePending = false;
updateActivityLockScreenState();
adjustStatusBarLocked();
userActivity();
///M: [ALPS01268903] delay to finish to avoid flashing the below activity
mHandler.postDelayed(new Runnable() {
public void run() {
try {
ActivityManagerNative.getDefault().closeSystemDialogs("lock");
} catch (RemoteException e) {
}
}
}, 500);
// Do this at the end to not slow down display of the keyguard.
/// M: power off alarm
if (!PowerOffAlarmManager.isAlarmBoot()) {
playSounds(true);
} else {
mPowerOffAlarmManager.startAlarm();
}
mShowKeyguardWakeLock.release();
if (DEBUG) KeyguardUtils.xlogD(TAG, "handleShow exit");
}
if (mKeyguardDisplayManager != null) {
mKeyguardDisplayManager.show();
}
}
在上述中有给出一系列的判断是否锁屏,比如在用户按下PowerOff的时候,会给出一定缓冲时间来避免用户执行后悔动作。处理了闹钟事件下的动作。
调用视图显示:
mKeyguardViewManager.show(options);
--> KeyguardViewManager.java
/**
* Show the keyguard. Will handle creating and attaching to the view manager
* lazily.
*/
public synchronized void show(Bundle options) {
if (DEBUG) Log.d(TAG, "show(); mKeyguardView=" + mKeyguardView);
boolean enableScreenRotation = KeyguardUtils.shouldEnableScreenRotation(mContext);
if (DEBUG) Log.d(TAG, "show() query screen rotation after");
/// M: Incoming Indicator for Keyguard Rotation @{
KeyguardUpdateMonitor.getInstance(mContext).setQueryBaseTime();
/// @}
maybeCreateKeyguardLocked(enableScreenRotation, false, options);
if (DEBUG) Log.d(TAG, "show() maybeCreateKeyguardLocked finish");
maybeEnableScreenRotation(enableScreenRotation);
// Disable common aspects of the system/status/navigation bars that are not appropriate or
// useful on any keyguard screen but can be re-shown by dialogs or SHOW_WHEN_LOCKED
// activities. Other disabled bits are handled by the KeyguardViewMediator talking
// directly to the status bar service.
int visFlags = View.STATUS_BAR_DISABLE_HOME;
if (shouldEnableTranslucentDecor()) {
mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
}
if (DEBUG) Log.d(TAG, "show:setSystemUiVisibility(" + Integer.toHexString(visFlags)+")");
mKeyguardHost.setSystemUiVisibility(visFlags);
mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
mKeyguardHost.setVisibility(View.VISIBLE);
mKeyguardView.show();
mKeyguardView.requestFocus();
if (DEBUG) Log.d(TAG, "show() exit; mKeyguardView=" + mKeyguardView);
}
这个方法就是将锁屏视图显示出来了,并抢占焦点。初始化时在maybeCreateKeyguardLocked时完成的
private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
Bundle options) {
if (mKeyguardHost != null) {
mKeyguardHost.saveHierarchyState(mStateContainer);
}
if (mKeyguardHost == null) {
if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
mKeyguardHost = new ViewManagerHost(mContext);
int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
| WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
| WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
if (!mNeedsInput) {
flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
final int type = WindowManager.LayoutParams.TYPE_KEYGUARD;
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
lp.windowAnimations = R.style.Animation_LockScreen;
lp.screenOrientation = enableScreenRotation ?
ActivityInfo.SCREEN_ORIENTATION_USER : ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
lp.privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
}
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
/// M: Poke user activity when operating Keyguard
//lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
lp.setTitle("Keyguard");
mWindowLayoutParams = lp;
///M: skip add KeyguardHost into viewManager in AT case
if (!KeyguardViewMediator.isKeyguardInActivity) {
mViewManager.addView(mKeyguardHost, lp);
} else {
if (DEBUG) Log.d(TAG, "skip add mKeyguardHost into mViewManager for testing");
}
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mBackgroundChanger);
}
/// M: If force and keyguardView is not null, we should relase memory hold by old keyguardview
if (force && mKeyguardView != null) {
mKeyguardView.cleanUp();
}
if (force || mKeyguardView == null) {
mKeyguardHost.setCustomBackground(null);
mKeyguardHost.removeAllViews();
inflateKeyguardView(options);
mKeyguardView.requestFocus();
}
updateUserActivityTimeoutInWindowLayoutParams();
mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
mKeyguardHost.restoreHierarchyState(mStateContainer);
}
上述中可以看到,其实系统锁屏也是通过全屏的悬浮视图贴在窗口视图的最顶层,实现方式类似于我们开发工具类应用悬浮窗的方式, 锁屏视图类型由一下方法决定:
private void inflateKeyguardView(Bundle options) {
/// M: add for power-off alarm @{
int resId = R.id.keyguard_host_view;
int layoutId = R.layout.keyguard_host_view;
if(PowerOffAlarmManager.isAlarmBoot()){
resId = R.id.power_off_alarm_host_view;
layoutId = R.layout.mtk_power_off_alarm_host_view;
}
/// @}
View v = mKeyguardHost.findViewById(resId);
if (v != null) {
mKeyguardHost.removeView(v);
}
/// M: Save new orientation
mCreateOrientation = mContext.getResources().getConfiguration().orientation;
mCreateScreenWidthDp = mContext.getResources().getConfiguration().screenWidthDp;
mCreateScreenHeightDp = mContext.getResources().getConfiguration().screenHeightDp;
final LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(layoutId, mKeyguardHost, true);
mKeyguardView = (KeyguardHostView) view.findViewById(resId);
mKeyguardView.setLockPatternUtils(mLockPatternUtils);
mKeyguardView.setViewMediatorCallback(mViewMediatorCallback);
mKeyguardView.initializeSwitchingUserState(options != null &&
options.getBoolean(IS_SWITCHING_USER));
// HACK
// The keyguard view will have set up window flags in onFinishInflate before we set
// the view mediator callback. Make sure it knows the correct IME state.
if (mViewMediatorCallback != null) {
KeyguardPasswordView kpv = (KeyguardPasswordView) mKeyguardView.findViewById(
R.id.keyguard_password_view);
if (kpv != null) {
mViewMediatorCallback.setNeedsInput(kpv.needsInput());
}
}
if (options != null) {
int widgetToShow = options.getInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET,
AppWidgetManager.INVALID_APPWIDGET_ID);
if (widgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
mKeyguardView.goToWidget(widgetToShow);
}
}
}
然後在不同的视图类来实现解锁动作。