adroid 5.1鎖屏研究總結


           Android 5.1 和6.0的鎖屏和以往的版本相比發生了很大變化,同時增加了新的特性:鎖屏上顯示通知。另一方面,Keyguard  不在是獨立的apk和systemUI 合併,做成了systemUI的一個lib ,如下Android.mk可以說明

Android 4.4 --SystemUI--Android.mk

<span style="font-size:14px;font-weight: normal;">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))</span>


Android5.1 systemUI Android.mk
<span style="font-weight: normal;">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))</span>

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 顯示鎖屏大致流程圖:

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還沒有仔細研究,以後補充。。。

發佈了34 篇原創文章 · 獲贊 33 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章