锁屏界面之Keyguard和SystemUI

本文详细介绍了Android系统中Keyguard与SystemUI的关系,它们在同一进程中运行。Keyguard由SystemUI管理,核心类如KeyguardViewMediator作为中介,连接Keyguard与SystemUI,处理锁屏的显示和隐藏。锁屏流程涉及SystemServer、PhoneWindowManager、KeyguardServiceDelegate等多个组件,通过IKeyguardService接口进行跨进程通信。当系统准备好后,调用KeyguardService的onSystemReady方法,进而显示锁屏界面。

Keyguard 与 SystemUI

PATH: /frameworks/base/packages/SystemUI/src/com/android/

Keyguard 与 SystemUI 进程

Keyguard 与 SystemUI 运行在同一进程中,即com.android.systemui进程。这点可以从manifest.xml文件就可以看出。

Keyguard

    <application android:label="@string/app_name"
        android:process="com.android.systemui"
        android:persistent="true"
        android:supportsRtl="true"
        android:defaultToDeviceProtectedStorage="true"
        android:directBootAware="true">

SystemUI

<application
        android:name=".SystemUIApplication"
        android:persistent="true"
        android:allowClearUserData="false"
        android:allowBackup="false"
        android:hardwareAccelerated="true"
        android:label="@string/app_label"
        android:icon="@drawable/icon"
        android:process="com.android.systemui"
        android:supportsRtl="true"
        android:theme="@style/systemui_theme"
        android:defaultToDeviceProtectedStorage="true"
        android:directBootAware="true">

通过Android.mk可知:在编译过程中,keyguard被打包成静态Java库. Keygaurd实际是由SystemUI来管理的.

# Keyguard Android.mk
include $(BUILD_STATIC_JAVA_LIBRARY)

# SystemUI: 
LOCAL_STATIC_JAVA_LIBRARIES := \
    com.mediatek.systemui.ext \
    Keyguard \

类的简单含义

Android锁屏流程分析,主要用到的核心类如下:

keyguardUpdateMonitor是状态回调的管理类, 类似于一个监视器, 用于监听keyguard的更新变化.

keyguardBouncer 是锁屏view的通信交互类。

KeyguardServiceDelegate.java 继承了接口IKeyguardService; 同时KeyguardService完成了IKeyguardService的远程实现. 即这两个类通过底层aidl进行远程通信. 进入系统可以控制Keyguard服务的启动.

KeyguardServiceDelegate.java 是一个局部类,保存keyguard在崩溃之前的状态,用来恢复。同时它也可以运行时选择本地或远程的keyguard实例.

KeyguardViewMediator.java 作为一个中介类, 连接Keyguard与Systemui.其职能包括查询keyguard的状态, Keyguard在开关键的事件的动作,如显示或重置等。(KeyguardViewMediator 继承SystemUI, 是锁屏的核心类, 是交互的中转类,其它对象都通过KeyguardViewMediator对象相互交互。)

KeyguardSecurityContainer.java 这个类主要用于装载Pattern, password, pin等解锁视图的容器.

StatusBarKeyguardViewManger.java 在status bar中, 管理创建, 显示, 隐藏, 重置 状态栏中的 Keyguard.

锁屏流程概述

  1. SystemServer这个系统服务线程由底层开启, 该系统服务将开启一系列的服务, 其中Keyguard的流程会流到WindowManagerPolicy进行处理。
  1. WindowManagerPolicy的实现类是PhoneWindowManager。其将 keyguard 事件分发到 KeyguardServiceDelegate 进行处理.
  1. KeyguardServiceDelegate里绑定 KeyguardService 服务。 并调用onSystemReady方法。此时进入到SystemUI, 并调用KeyguardViewMediator决定是否显示视图。
    (IkeyguardService 由KeyguardServiceWrapper包装类继承, 由KeyguardService远程实现. 实现底层与Systemui的通信,保证两者之间数据共享)。
  1. keyguard事件传递到了SystemUI, 并由KeyguardViewMediator进行事件的分派. 如部分视图由SystemUI显示, 即如StatusBarKeyguardViewManager来处理,并进入到KeyguardBouncer。 部分视图将传递到Keyguard, 由Keyguard来绘制, 如 KeyguardSecurityContainer来处理。

锁屏流程详述

  1. Zygote进程启动后会首先创建一个SystemServer进程;

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer ...
  1. SystemServer进程在调用startOtherServices时,同时也会调用WindowManagerService的systemReady()方法;

/frameworks/base/services/java/com/android/server/SystemServer.java

    private void startOtherServices() {
        ...
        wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore);
        ...
        try {
            wm.systemReady();  //WindowManagerService的systemReady()方法
        } catch (Throwable e) {
            reportWtf("making Window Manager Service ready", e);
        }
    }
  1. 在WindowManagerService服务中,直接调用了WindowManagerPolicy.java的systemReady()方法,而具体方法的实现在PhoneWindowManager.java中。
    注: 窗口管理服务WindowManagerService的职责是对系统中的所有窗口进行管理

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

    @VisibleForTesting
    WindowManagerPolicy mPolicy;

    public void systemReady() {
        mSystemReady = true;
        mPolicy.systemReady();
        ...
    }
  1. 在PhoneWindowManager的systemReady()中,会依据一个Boolean值bindKeyguardNow来决定是否绑定keyguard service

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    public void systemReady() {
        mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
        mKeyguardDelegate.onSystemReady(); //分派到KeyguardDelegate进行处理,开机时不做任何处理.
        ...
        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) {//如果已经绑定KeyguardService,进行处理.
            mKeyguardDelegate.bindService(mContext);
            mKeyguardDelegate.onBootCompleted();
        }
        ...
    }
  1. 看到这里,假设 bindKeyguardNow 为false就会不绑定,后面通过继续跟踪发现PhoneWindowManager的systemBooted()里也会去绑定keyguard service。假设在systemBooted里绑定,就不在systemReady里再去绑定(某大佬描述:是在systemBooted绑定)。

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    /** {@inheritDoc} */
    @Override
    public void systemBooted() {
        bindKeyguard();
        synchronized (mLock) {
            mSystemBooted = true;
            if (mSystemReady) {
                mKeyguardDelegate.onBootCompleted();
            }
        }
        mSideFpsEventHandler.onFingerprintSensorReady();
        startedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
        finishedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);

        int defaultDisplayState = mDisplayManager.getDisplay(DEFAULT_DISPLAY).getState();          boolean defaultDisplayOn = defaultDisplayState == Display.STATE_ON;
        boolean defaultScreenTurningOn = mDefaultDisplayPolicy.getScreenOnListener() != null;
        if (defaultDisplayOn || defaultScreenTurningOn) {
            // Now that system is booted, wait for keyguard and windows to be drawn before
            // updating the orientation listener, stopping the boot animation and enabling screen.
            screenTurningOn(DEFAULT_DISPLAY, mDefaultDisplayPolicy.getScreenOnListener());
            screenTurnedOn(DEFAULT_DISPLAY);
        } else {
            // We're not turning the screen on, so don't wait for keyguard to be drawn
              // to dismiss the boot animation and finish booting
              mBootAnimationDismissable = true;
              enableScreen(null, false /* report */);
        }
    }

    private void bindKeyguard() {
        synchronized (mLock) {
            if (mKeyguardBound) {
                return;
            }
            mKeyguardBound = true;
        }
        mKeyguardDelegate.bindService(mContext);
    }
  
  1. 通过时序图看看是如何调用到systemBooted的
    在这里插入图片描述
  2. 不管是在systemReady或systemBooted,都调用了KeyguardServiceDelegate对象的bindService方法

显示锁屏界面

锁屏界面是怎么显示出来的,先看看以下的时序图
在这里插入图片描述

  1. 进入KeyguardServiceDelegate.java中, 将绑定keyguardService服务.

frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java

    public void bindService(Context context) {
        Intent intent = new Intent();
        final Resources resources = context.getApplicationContext().getResources();

        final ComponentName keyguardComponent = ComponentName.unflattenFromString(
                resources.getString(com.android.internal.R.string.config_keyguardComponent));
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        intent.setComponent(keyguardComponent);

        /* notice */
        if (!context.bindServiceAsUser(intent, mKeyguardConnection,
                Context.BIND_AUTO_CREATE, mHandler, UserHandle.SYSTEM)) {
            Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent);
            mKeyguardState.showing = false;
            mKeyguardState.showingAndNotOccluded = false;
            mKeyguardState.secure = false;
            synchronized (mKeyguardState) {
                // TODO: Fix synchronisation model in this class. The other state in this class
                // is at least self-healing but a race condition here can lead to the scrim being
                // stuck on keyguard-less devices.
                mKeyguardState.deviceHasKeyguard = false;
            }
        } else {
            if (DEBUG) Log.v(TAG, "*** Keyguard started");
        }
    }
  1. 在 bindService 中调用了 bindServiceAsUser, 绑定指定intent的service。

frameworks/base/core/res/res/values/config.xml
config_keyguardComponent的定义, 例如

    <!-- Keyguard component -->
    <string name="config_keyguardComponent" translatable="false">com.android.systemui/com.android.systemui.keyguard.KeyguardService</string>
  1. 当绑定成功后会调用mKeyguardConnection里的onServiceConnected方法。mKeyguardDelegate.onServiceConnected()进入到了KeyguardServiceWrapper。并将任务分派到KeyguardService, 启动Keyguard服务。

frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java

private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
                ...
                mKeyguardService = new KeyguardServiceWrapper(mContext,
                IKeyguardService.Stub.asInterface(service), mCallback);
                if (mKeyguardState.systemIsReady) {
                    // If the system is ready, it means keyguard crashed and restarted.
                    mKeyguardService.onSystemReady();
                    ...
                ...
        }
    ...
    };
  1. 当mKeyguardState.systemIsReady为true时,就会通过KeyguardServiceWrapper的实例mKeyguardService,调用onSystemReady方法。在KeyguardServiceWrapper的onSystemReady里, 调用了上面刚刚绑定成功的KeyguardService的onSystemReady方法。

frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java

public class KeyguardServiceWrapper implements IKeyguardService {
    ...
    @Override // Binder interface
    public void onSystemReady() {
        try {
            mService.onSystemReady();
        } catch (RemoteException e) {
            Slog.w(TAG , "Remote Exception", e);
        }
    }
    ...
}
  1. 在KeyguardService的onSystemReady里调用了KeyguardViewMediator里的onSystemReady。

/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java

    private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {   
        public void onSystemReady() {
            checkPermission(); //权限的检查
            mKeyguardViewMediator.onSystemReady();
        }
    }

可以看出,其实这两个类就是跨进程通信.通过IKeyguardService这个接口来进行framework与Systemui之间的跨进程通信.此时,流程就进入到了SystemUI.

进入SystemUI这个应用后, 将进入Keyguard的一个重要的类KeyguardViewMediator。该方法主要是进行广播:标志这系统在启动后已经准备好了.接着,doKeyguardLocked()方法收到了null参数。可以看到这个方法主要是针对不同的keyguard模式进行判别.

  1. KeyguardViewMediator.onSystemReady

frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java

public class KeyguardViewMediator extends SystemUI {
    ...
    public void onSystemReady() {
        mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            doKeyguardLocked(null); //锁屏路径
            mUpdateMonitor.registerCallback(mUpdateCallback); // 注冊了KeyguardUpdateMonitorCallback
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }
    ...
}
  1. 通过调用doKeyguardLocked显示锁屏界面

frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java

这段代码主要是在是否要显示锁屏之前做了5个推断:
1. 当前正在解密界面不显示。
2. 假设启用第三方锁屏界面, 不显示原生界面;
3. 锁屏界面已经显示了话,又一次更新下状态;
4. 假设第一次开机引导界面setup wizard 还没有执行,也先不显示;
5. 屏幕没有亮不显示;
假设这几个条件都不满足, 则调用showLocked显示锁屏界面。
   /**
     * Enable the keyguard if the settings are appropriate.
     */
    private void doKeyguardLocked(Bundle options) {
        if (KeyguardUpdateMonitor.CORE_APPS_ONLY) {
            // Don't show keyguard during half-booted cryptkeeper stage.
            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because booting to cryptkeeper");
            return;
        }

        // if another app is disabling us, don't show
        // 外置apk的keyguard等
        if (!mExternallyEnabled) {
            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");

            mNeedToReshowWhenReenabled = true;
            return;
        }

        // if the keyguard is already showing, don't bother. check flags in both files
        // to account for the hiding animation which results in a delay and discrepancy
        // between flags
        if (mShowing && mKeyguardViewControllerLazy.get().isShowing()) {
            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
            resetStateLocked();
            return;
        }

        // In split system user mode, we never unlock system user.
        if (!mustNotUnlockCurrentUser()
                || !mUpdateMonitor.isDeviceProvisioned()) {

            // if the setup wizard hasn't run yet, don't show
            final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false);
            final boolean absent = SubscriptionManager.isValidSubscriptionId(
                    mUpdateMonitor.getNextSubIdForState(TelephonyManager.SIM_STATE_ABSENT));
            final boolean disabled = SubscriptionManager.isValidSubscriptionId(
                    mUpdateMonitor.getNextSubIdForState(TelephonyManager.SIM_STATE_PERM_DISABLED));
            final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()
                    || ((absent || disabled) && requireSim);

            if (!lockedOrMissing && shouldWaitForProvisioning()) {
                if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
                        + " and the sim is not locked or missing");
                return;
            }

            boolean forceShow = options != null && options.getBoolean(OPTION_FORCE_SHOW, false);
            if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
                    && !lockedOrMissing && !forceShow) {
                if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
                return;
            }
        }

        if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
        showLocked(options);
    }
  1. 在showLocked通过mHandler发送Message。在handleMessage里“case SHOW:”时调用 handleShow

frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java

    private void showLocked(Bundle options) {
        setReadyToShow(true); //设置参数.
        updateActivityLockScreenState(); //更新锁屏状态,使用进程间通信技术
        // ensure we stay awake until we are finished displaying the keyguard
        mShowKeyguardWakeLock.acquire(); //获取唤醒锁.不受电源影响,不让cpu进入休眠状态.
        Message msg = mHandler.obtainMessage(SHOW, options);
        mHandler.sendMessage(msg); //使用handler子线程来处理显示
    }
  1. 在 handleShow 里设置一些锁屏状态和显示锁屏界面

/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java

    // 注意链接前面的 mHandler
    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;
    /**
     * Handle message sent by {@link #showLocked}.
     * @see #SHOW
     */
    private void handleShow(Bundle options) {
        Trace.beginSection("KeyguardViewMediator#handleShow");
        final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
        if (mLockPatternUtils.isSecure(currentUser)) {
            mLockPatternUtils.getDevicePolicyManager().reportKeyguardSecured(currentUser);
        }
        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");
            }

            mHiding = false;
            mKeyguardExitAnimationRunner = null;
            mWakeAndUnlocking = false;
            setPendingLock(false);
            setShowingLocked(true);
            mKeyguardViewControllerLazy.get().show(options); // 跳转到StatusBarKeyguardViewManager中的show()方法
            resetKeyguardDonePendingLocked();
            mHideAnimationRun = false;
            adjustStatusBarLocked();
            userActivity();
            mUpdateMonitor.setKeyguardGoingAway(false);
            mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(false);
            mShowKeyguardWakeLock.release();
        }
        mKeyguardDisplayManager.show(); 

        // schedule 4hr idle timeout after which non-strong biometrics (i.e. weak or convenience
        // biometric) can't be used to unlock device until unlocking with strong biometric or
        // primary auth (i.e. PIN/pattern/password)
        mLockPatternUtils.scheduleNonStrongBiometricIdleTimeout(
                KeyguardUpdateMonitor.getCurrentUser());

        Trace.endSection();
    }
  1. 通过调用 StatusBarKeyguardViewManager 的show()方法重置当前状态, 显示keyguard

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java

    /**
    * Show the keyguard.  Will handle creating and attaching to the view manager
    * lazily.
    */
    @Override
    public void show(Bundle options) {
        Trace.beginSection("StatusBarKeyguardViewManager#show");
        mShowing = true;
        mNotificationShadeWindowController.setKeyguardShowing(true);
        mKeyguardStateController.notifyKeyguardState(mShowing,
                mKeyguardStateController.isOccluded());
        reset(true /* hideBouncerWhenShowing */);
        SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
                SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
        Trace.endSection();
    }
  1. 在reset()方法里调用本类的 showBouncerOrKeyguard。

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java

    @Override
    public void reset(boolean hideBouncerWhenShowing) {
        if (mShowing) {
            // Hide quick settings.
            mNotificationPanelViewController.resetViews(/* animate= */ true);
            // Hide bouncer and quick-quick settings.
            if (mOccluded && !mDozing) { // mOccluded代表是否被其他窗口中断
                // 参数为true, 表示隐藏安全锁界面
                mCentralSurfaces.hideKeyguard();
                if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) {
                    hideBouncer(false /* destroyView */);
                }
            } else {
                showBouncerOrKeyguard(hideBouncerWhenShowing); // 滑动锁或Keyguard锁
            }
            resetAlternateAuth(false);
            mKeyguardUpdateManager.sendKeyguardReset();
            updateStates();
        }
    }
  1. showBouncerOrKeyguard()方法使用 KeyguardBouncer.java 的needsFullscreenBouncer()方法判断显示常规锁屏还是Bouncer安全锁屏。

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java

    protected 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();
        }
    }
  1. 当前获取的Bouncer的类型是SimPin或者SimPuk时,通过mKeyguardView.getSecurityMode()获取当前Bouncer的类型时最终是调到KeyguardSecurityModel的getSecurityMode方法,通过KeyguardUpdateMonitor 这个类获取当前SIM卡的状态来判断的,当状态是PIN_REQUIRED或者PUK_REQUIRED, 则说明应该直接显示类型为SecurityMode.SimPin或者SecurityMode.SimPuk的密码锁屏(这类直接在systemui中处理了),所以当我们插入一张带密码的SIM卡时会立即显示sim pin界面

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java

    public boolean needsFullscreenBouncer() {
        SecurityMode mode = mKeyguardSecurityModel.getSecurityMode(
                KeyguardUpdateMonitor.getCurrentUser());
        return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
    }
  1. 其他则为一般解锁, 其将进入到Keyguard中去进行处理, 称为:notification keyguard, 包括pattern, password, PIN。这种 keyguard 视图的父视图为 KeyguardSecurityContainer。SecurityMode定义如下:

/frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java

    public enum SecurityMode {
        Invalid, // NULL state
        None, // No security enabled
        Pattern, // Unlock by drawing a pattern.
        Password, // Unlock by entering an alphanumeric password
        PIN, // Strictly numeric password
        SimPin, // Unlock by entering a sim pin.
        SimPuk // Unlock by entering a sim puk
    }
  1. 在mBouncer.prepare()方法中,调用 showPrimarySecurityScreen。

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java

    public void prepare() {
        boolean wasInitialized = mInitialized;
        ensureView();
        if (wasInitialized) {
            showPrimarySecurityScreen();
        }
        mBouncerPromptReason = mCallback.getBouncerPromptReason();
    }
}
  1. 通过 KeyguardHostViewController的showPrimarySecurityScreen 再调用 KeyguardSecurityContainer 的showPrimarySecurityScreen() 方法。

/frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java

    public void showPrimarySecurityScreen() {
        if (DEBUG) Log.d(TAG, "show()");
        mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
    }
  1. 最后根据不同的keyguard模式来进行界面的重绘。利用mSecurityModel.getSecurityMode()获取当前的securityMode,传入showSecurityScreen来显示不同锁屏界面。

frameworks/base/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java

    public void showPrimarySecurityScreen(boolean turningOff) {
        SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode(
                KeyguardUpdateMonitor.getCurrentUser()));
        if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
        showSecurityScreen(securityMode);
    }

参考链接

http://t.zoukankan.com/blfbuaa-p-7288867.html
https://developer.aliyun.com/article/1124660

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多维不语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值