Android 5.1 和6.0的锁屏和以往的版本相比发生了很大变化,同时增加了新的特性:锁屏上显示通知。另一方面,Keyguard 不在是独立的apk和systemUI 合并,做成了systemUI的一个lib ,如下Android.mk可以说明
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
src/com/android/systemui/EventLogTags.logtags
LOCAL_STATIC_JAVA_LIBRARIES := Keyguard
LOCAL_JAVA_LIBRARIES := telephony-common ims-common
LOCAL_PACKAGE_NAME := SystemUI
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_RESOURCE_DIR := \
frameworks/base/packages/Keyguard/res \
$(LOCAL_PATH)/res
LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages com.android.keyguard
ifneq ($(SYSTEM_UI_INCREMENTAL_BUILDS),)
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_JACK_ENABLED := incremental
endif
include frameworks/base/packages/SettingsLib/common.mk
include $(BUILD_PACKAGE)
ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)
include $(call all-makefiles-under,$(LOCAL_PATH))
endif
对比上面既可以发现,
差别显而易见,其中
LOCAL_STATIC_JAVA_LIBRARIES := Keyguard #表示Keyguard是一个static lib。
LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages com.android.keyguard #表示Keyguard 和 SystemUI被整合到一起,这样修改源码代码以后,只要mm SystemUI。
Android4.4上,show Keyguard,KeyguardViewManager.java和KeyguardHostView.java比较重要,而在Android5.1上,这两者直接被弃用了,Android5.1 Keyguard的root
view是SystemUI下的StatusBarWindowView,KeyguardViewManager也被StatusBarKeyguardViewManager所取代,StatusBarKeyguardViewManager现在负责管理keyguard 在status bar中
创建、显示、隐藏、重置。show keyguard 有两个触发点,一个是systemReady,意思是系统启动完成以后show keyguard。另一个是screenOff,表示灭屏,手机要灭屏进入休眠状态有两
个原因:手动按Power键灭屏(WindowManagerPolicy.OFF_BECAUSE_OF_USER)和 系统自动灭屏(WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT)。
SystemReady 显示锁屏大致流程图:
screen off 显示大致流程:
从流程上看,在决定显示keygurad的时,还会判断显示 Bouncer 还是Keygurad:(StatusBarKeyguardViewManager.java)
/**
* 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();
}
}
Bouncer是用来显示安全锁屏,比如图案锁屏、密码锁屏、PIN码锁屏等,
从代码中可以看出,show Bouncer的时候才会调用到Keygurad那边的KeyguardViewBase来show Security Screen,(eyguardBouncer.java)
public void show(boolean resetSecuritySelection) {
ensureView();
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();
}
if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
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()) {
mShowingSoon = true;
// Split up the work over multiple frames.
mChoreographer.postCallbackDelayed(Choreographer.CALLBACK_ANIMATION, mShowRunnable,
null, 16);
}
}
下面安全锁屏跟以前基本相同,而普通的锁屏和StatusBar 融合到了一块(PhoneStatusBar.java)
public void showKeyguard() {
if (mLaunchTransitionFadingAway) {
mNotificationPanel.animate().cancel();
mNotificationPanel.setAlpha(1f);
runLaunchTransitionEndRunnable();
mLaunchTransitionFadingAway = false;
}
mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
setBarState(StatusBarState.KEYGUARD);
updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */);
if (!mScreenOnFromKeyguard) {
// If the screen is off already, we need to disable touch events because these might
// collapse the panel after we expanded it, and thus we would end up with a blank
// Keyguard.
mNotificationPanel.setTouchDisabled(true);
}
instantExpandNotificationsPanel();
mLeaveOpenOnKeyguardHide = false;
if (mDraggedDownRow != null) {
mDraggedDownRow.setUserLocked(false);
mDraggedDownRow.notifyHeightChanged();
mDraggedDownRow = null;
}
}
从showKeyguard()方法中可以看到,并没有addView() 和 TYPE_KEYGUARD。而只是setBarState(StatusBarState.KEYGUARD)。
/**
* Class to encapsulate all possible status bar states regarding Keyguard.
*/
public class StatusBarState {
/**
* The status bar is in the "normal" shade mode.
*/
public static final int SHADE = 0;
/**
* Status bar is currently the Keyguard.
*/
public static final int KEYGUARD = 1;
/**
* Status bar is in the special mode, where it is fully interactive but still locked. So
* dismissing the shade will still show the bouncer.
*/
public static final int SHADE_LOCKED = 2;
}
说到TYPE_KEYGUARD,在Android5.1版本中并没有使用这个window type来show keyguard,而是使用PRIVATE_FLAG_KEYGUARD。
private void applyKeyguardFlags(State state) {
if (state.keyguardShowing) {
mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
} else {
mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
}
}
锁屏上增加了Notification,在锁屏是否显示Notification,这个在设置中可以设置。
SystemUI通过监听设置决定是否显示Notification,这部分逻辑在BaseStatusBar.java中。
public void start() {
...
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
mSettingsObserver,
UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
true,
mLockscreenSettingsObserver,
UserHandle.USER_ALL);
...
}
protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
final boolean provisioned = 0 != Settings.Global.getInt(
mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
if (provisioned != mDeviceProvisioned) {
mDeviceProvisioned = provisioned;
updateNotifications();
}
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
setZenMode(mode);
updateLockscreenNotificationSetting();
}
};
private final ContentObserver mLockscreenSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
// We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
// so we just dump our cache ...
mUsersAllowingPrivateNotifications.clear();
// ... and refresh all the notifications
updateNotifications();
}
};
Android 6.0还没有仔细研究,以后补充。。。