adroid 5.1锁屏研究总结


           Android 5.1 和6.0的锁屏和以往的版本相比发生了很大变化,同时增加了新的特性:锁屏上显示通知。另一方面,Keyguard  不在是独立的apk和systemUI 合并,做成了systemUI的一个lib ,如下Android.mk可以说明

Android 4.4 --SystemUI--Android.mk

LOCAL_JAVA_LIBRARIES := telephony-common
LOCAL_PACKAGE_NAME := SystemUI
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))


Android5.1 systemUI 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 telephony-common2
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
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))

Adroid6.0 systemUI 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 显示锁屏大致流程图:
adroid 5.1锁屏研究总结_第1张图片
screen off 显示大致流程:
adroid 5.1锁屏研究总结_第2张图片


从流程上看,在决定显示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还没有仔细研究,以后补充。。。

你可能感兴趣的:(Android)