问题布景

近期在处理一个开机解锁问题,刺进双SIM卡,并且翻开SIM卡锁,将锁屏办法设为NONE,重启模块,解锁SIM卡后依然显现锁屏页,现象见下图

动画

由于restart后adb断开连接,所以分开录屏了,下图是重启后的操作

动画2

能够看到,在Settings->Security中,Screen lock设为None,SIM card lock均开启,正常状况下,重启后输入完PIN码应该直接进入Launcher,但是竟然出现了锁屏页,最奇怪的是,这个bug还不是必现的,所以这个录屏我操作了好多次才成功的。为了处理这个问题,首要必须要梳理一下开机解锁的履行流程,然后再埋日志,定位问题的要害点。

Android的发动流程

这个就不必多说了,直接先上图

image2022-12-8_14-53-33

首要是Boot Loader发动Kernel进程,然后再由Kernel进程发动init进程,init进程会发动许许多多的子进程(如最常见的Zygote进程)和System Server

KeyguardService

先贴上整个源码流程的时序图,以便在阅览源码的时候知道自己当时在剖析哪一块

keyguard

System Server中包含许多Service,其中包含WindowManagerService,核心源码如下

public final class SystemServer {
    /**
     * The main entry point from zygote.
     * 此办法由Zygote进程调用
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
    //省掉部分代码
    private void run() {
        //省掉部分代码
        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            //发动引导服务,如watchdog,powermanager,installer
            startBootstrapServices();
            //发动核心服务,如battery,bugreport
            startCoreServices();
            //发动其他的服务,咱们经过context.getSystemService()获取到的服务根本都在这儿边
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
		//省掉部分代码
    }
    //省掉部分代码
    private void startOtherServices(){
        //省掉部分代码
        traceBeginAndSlog("StartWindowManagerService");
        // WMS needs sensor service ready
        ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
        mSensorServiceStart = null;
        //创立WindowManagerService
        wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
        ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
        ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
        traceEnd();
        traceBeginAndSlog("SetWindowManagerService");
        mActivityManagerService.setWindowManager(wm);
        traceEnd();
        traceBeginAndSlog("WindowManagerServiceOnInitReady");
        //对WindowManagerService进行初始化
        wm.onInitReady();
        traceEnd();
        //省掉部分代码
        try {
            //WindowManagerService已准备就绪
            wm.systemReady();
        } catch (Throwable e) {
            reportWtf("making Window Manager Service ready", e);
        }
        traceEnd();
        //省掉部分代码
    }
}
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    //省掉部分代码
    @VisibleForTesting
    WindowManagerPolicy mPolicy;
    //省掉部分代码 
    private void initPolicy() {
        UiThread.getHandler().runWithScissors(new Runnable() {
            @Override
            public void run() {
                WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
                mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
            }
        }, 0);
    }
    //省掉部分代码
    /**
     * Called after all entities (such as the {@link ActivityManagerService}) have been set up and
     * associated with the {@link WindowManagerService}.
     */
    public void onInitReady() {
        //初始化署理目标
        initPolicy();
        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);
        openSurfaceTransaction();
        try {
            createWatermarkInTransaction();
        } finally {
            closeSurfaceTransaction("createWatermarkInTransaction");
        }
        showEmulatorDisplayOverlayIfNeeded();
    }
    //省掉部分代码
    public void systemReady() {
        mSystemReady = true;
        //履行mPolicy的systemReady()
        mPolicy.systemReady();
        mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
        mTaskSnapshotController.systemReady();
        mHasWideColorGamutSupport = queryWideColorGamutSupport();
        mHasHdrSupport = queryHdrSupport();
        UiThread.getHandler().post(mSettingsObserver::updateSystemUiSettings);
        UiThread.getHandler().post(mSettingsObserver::updatePointerLocation);
        IVrManager vrManager = IVrManager.Stub.asInterface(
                ServiceManager.getService(Context.VR_SERVICE));
        if (vrManager != null) {
            try {
                final boolean vrModeEnabled = vrManager.getVrModeState();
                synchronized (mGlobalLock) {
                    vrManager.registerListener(mVrStateCallbacks);
                    if (vrModeEnabled) {
                        mVrModeEnabled = vrModeEnabled;
                        mVrStateCallbacks.onVrStateChanged(vrModeEnabled);
                    }
                }
            } catch (RemoteException e) {
                // Ignore, we cannot do anything if we failed to register VR mode listener
            }
        }
    }
    //省掉部分代码
}

上述源码主要是WindowManagerService的发动流程,首要创立WindowManagerService,然后履行它的onInitReady()办法和systemReady()办法。在onInitReady()办法中,履行了initPolicy()办法,initPolicy()办法里边履行了mPolicy的init()办法,而mPolicy是WindowManagerPolicy接口目标,WindowManagerPolicy接口有唯一的完结类PhoneWindowManager,所以mPolicy.init()实践上便是履行PhoneWindowManager的init()办法

public class PhoneWindowManager implements WindowManagerPolicy {
    //省掉部分代码
    /** {@inheritDoc} */
    @Override
    public void init(Context context, IWindowManager windowManager,
            WindowManagerFuncs windowManagerFuncs) {
        //省掉部分代码
        //此处创立了KeyguardServiceDelegate
        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
                new StateCallback() {
                    @Override
                    public void onTrustedChanged() {
                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
                    }
                    @Override
                    public void onShowingChanged() {
                        mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
                    }
                });
    }
    //省掉部分代码
    /** {@inheritDoc} */
    @Override
    public void systemReady() {
        // In normal flow, systemReady is called before other system services are ready.
        // So it is better not to bind keyguard here.
        //履行KeyguardDelegate的onSystemReady()
        mKeyguardDelegate.onSystemReady();
        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
        if (mVrManagerInternal != null) {
            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
        }
        readCameraLensCoverState();
        updateUiMode();
        mDefaultDisplayRotation.updateOrientationListener();
        synchronized (mLock) {
            mSystemReady = true;
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    updateSettings();
                }
            });
            // If this happens, for whatever reason, systemReady came later than systemBooted.
            // And keyguard should be already bound from systemBooted
            if (mSystemBooted) {
                //履行KeyguardDelegate的onBootCompleted()
                mKeyguardDelegate.onBootCompleted();
            }
        }
        mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
    }
    //省掉部分代码
}

PhoneWindowManager的init()办法中创立了keyguardServiceDelegate目标,此目标跟锁屏相关。在WindowManagerService履行完onInitReady()之后,紧接着履行systemReady(),在systemReady()办法中会履行mPolicy的systemReady()办法,正如上述剖析,履行mPolicy.systemReady()其实便是履行的PhoneWindowManager的systemReady()办法,源码见上。

PhoneWindowManager的systemReady()办法里边履行了mKeyguardDelegate的onSystemReady()办法和onBootCompleted()办法

public class KeyguardServiceDelegate {
    //省掉部分代码
    public KeyguardServiceDelegate(Context context, KeyguardStateMonitor.StateCallback callback) {
        mContext = context;
        mHandler = UiThread.getHandler();
        mCallback = callback;
    }
    //省掉部分代码
    public void onSystemReady() {
        if (mKeyguardService != null) {
            mKeyguardService.onSystemReady();
        } else {
            mKeyguardState.systemIsReady = true;
        }
    }
    //省掉部分代码
    public void onBootCompleted() {
        if (mKeyguardService != null) {
            mKeyguardService.onBootCompleted();
        }
        mKeyguardState.bootCompleted = true;
    }    
}

第一次履行KeyguardServiceDelegate的onSystemReady()办法时,mKeyguardService还没有创立,所以这儿会履行else逻辑,将systemIsReady标识方位为true,那mKeyguardService什么时候被创立呢,咱们在KeyguardServiceDelegate的源码中能够看到,mKeyguardService的创立在ServiceConnection傍边,而这个ServiceConnection是在bindService()的时候才会用到,源码如下

public class KeyguardServiceDelegate {
    //省掉部分代码
    //绑定KeyguardService
    public void bindService(Context context) {
        Intent intent = new Intent();
        final Resources resources = context.getApplicationContext().getResources();
        //从resource中获取keyguardservice的全途径,然后创立KeyguardService组件
        //resource途径:frameworks/base/core/res/res/values/config.xml
        //resource界说
        //<!-- Keyguard component -->
        //<string name="config_keyguardComponent" translatable="false">com.android.systemui/com.android.systemui.keyguard.KeyguardService</string>
        final ComponentName keyguardComponent = ComponentName.unflattenFromString(
                resources.getString(com.android.internal.R.string.config_keyguardComponent));
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        intent.setComponent(keyguardComponent);
        //绑定KeyguardService,传入界说的mKeyguardConnection
        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");
        }
    }
    private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
            //创立mkeyguardService
            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()
                mKeyguardService.onSystemReady();
                if (mKeyguardState.currentUser != UserHandle.USER_NULL) {
                    // There has been a user switch earlier
                    mKeyguardService.setCurrentUser(mKeyguardState.currentUser);
                }
                // This is used to hide the scrim once keyguard displays.
                if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE
                        || mKeyguardState.interactiveState == INTERACTIVE_STATE_WAKING) {
                    mKeyguardService.onStartedWakingUp();
                }
                if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
                    mKeyguardService.onFinishedWakingUp();
                }
                if (mKeyguardState.screenState == SCREEN_STATE_ON
                        || mKeyguardState.screenState == SCREEN_STATE_TURNING_ON) {
                    mKeyguardService.onScreenTurningOn(
                            new KeyguardShowDelegate(mDrawnListenerWhenConnect));
                }
                if (mKeyguardState.screenState == SCREEN_STATE_ON) {
                    mKeyguardService.onScreenTurnedOn();
                }
                mDrawnListenerWhenConnect = null;
            }
            if (mKeyguardState.bootCompleted) {
                mKeyguardService.onBootCompleted();
            }
            if (mKeyguardState.occluded) {
                mKeyguardService.setOccluded(mKeyguardState.occluded, false /* animate */);
            }
            if (!mKeyguardState.enabled) {
                mKeyguardService.setKeyguardEnabled(mKeyguardState.enabled);
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
            mKeyguardService = null;
            mKeyguardState.reset();
            mHandler.post(() -> {
                try {
                    ActivityTaskManager.getService().setLockScreenShown(true /* keyguardShowing */,
                            false /* aodShowing */);
                } catch (RemoteException e) {
                    // Local call.
                }
            });
        }
    };
    //省掉部分代码
}

而bindService()的调用在PhoneWindowManager的bindKeyguard()办法傍边

public class PhoneWindowManager implements WindowManagerPolicy {
    //省掉部分代码
    private void bindKeyguard() {
        synchronized (mLock) {
            if (mKeyguardBound) {
                return;
            }
            mKeyguardBound = true;
        }
        //绑定KeyguardService
        mKeyguardDelegate.bindService(mContext);
    }
    @Override
    public void onSystemUiStarted() {
        //绑定KeyguardService
        bindKeyguard();
    }
    //省掉部分代码
    /** {@inheritDoc} */
    @Override
    public void systemBooted() {
        //绑定KeyguardService
        bindKeyguard();
        synchronized (mLock) {
            mSystemBooted = true;
            if (mSystemReady) {
                mKeyguardDelegate.onBootCompleted();
            }
        }
        startedWakingUp(ON_BECAUSE_OF_UNKNOWN);
        finishedWakingUp(ON_BECAUSE_OF_UNKNOWN);
        screenTurningOn(null);
        screenTurnedOn();
    }
    //省掉部分代码
}

bindKeyguard()办法有两次被履行,别离在onSystemUiStarted()办法和systemBooted()办法中,依据办法名能够猜测到,在SystemUI发动后和体系发动完结时都会绑定一下KeyguardService,这也很好理解,锁屏页也是归于SystemUI,那必定需求SystemUI发动之后才干绘制锁屏界面。前面说到SystemServer里边会发动很多Service,在WindowManagerService发动之后会接着发动SystemUIService,源码如下

public final class SystemServer {
    //省掉部分代码
    private void startOtherServices() {
        //省掉部分代码
        //这儿也能够看到,在ActivityManagerService发动结束之后才会发动SystemUI
        mActivityManagerService.systemReady(() -> {
            //省掉部分代码
            traceBeginAndSlog("StartSystemUI");
            try {
                //发动SystemUI
                startSystemUi(context, windowManagerF);
            } catch (Throwable e) {
                reportWtf("starting System UI", e);
            }
            traceEnd();
            //省掉部分代码
        }
    }
    private static void startSystemUi(Context context, WindowManagerService windowManager) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui",
                "com.android.systemui.SystemUIService"));
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.SYSTEM);
        //SystemUIService发动之后履行WindowManagerService的onSystemUiStarted()办法
        windowManager.onSystemUiStarted();
    }
}

可见,在SystemUIService发动之后会履行WindowManagerService的onSystemUiStarted()办法,从而履行KeyguardServiceDelegate的bindService()办法发动KeyguardService,当成功连接KeyguardService之后会回调ServiceConnection的onServiceConnected()办法,从而履行KeyguardServiceWrapper的onSystemReady()办法,KeyguardServiceWrapper是KeyguardService的包装类,终究都会履行到KeyguardService里边对应的办法。

public class KeyguardServiceWrapper implements IKeyguardService {
    //省掉部分代码
    private IKeyguardService mService;
    @Override // Binder interface
    public void onSystemReady() {
        try {
            //经过aidl调用KeyguardService的onSystemReady()
            mService.onSystemReady();
        } catch (RemoteException e) {
            Slog.w(TAG , "Remote Exception", e);
        }
    }
    //省掉部分代码
}

在KeyguardServiceWrapper中,mService是一个IKeyguardService接口,该接口是一个aidl接口,用于WindowManagerService与KeyguardService进行通讯,在KeyguardService的onBind()办法回来了IKeyguardService目标,源码如下

public class KeyguardService extends Service {
    //省掉部分代码
    private KeyguardViewMediator mKeyguardViewMediator;
    private KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
    @Override
    public void onCreate() {
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        //创立mKeyguardViewMediator
        mKeyguardViewMediator =
                ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
        mKeyguardLifecyclesDispatcher = new KeyguardLifecyclesDispatcher(
                Dependency.get(ScreenLifecycle.class),
                Dependency.get(WakefulnessLifecycle.class));
        boolean isflag = SystemProperties.get("ro.boot.mode","0").equals("ffbm-02");
        if (isflag) {
            mKeyguardViewMediator.setKeyguardEnabled(false);
            Slog.i(TAG, "ffbm-02 setKeyguardEnabled false");
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        //回来IKeyguardService.Stub
        return mBinder;
    }
    //省掉部分代码
    private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
        //省掉部分代码
        @Override // Binder interface
        public void onSystemReady() {
            Trace.beginSection("KeyguardService.mBinder#onSystemReady");
            checkPermission();
            //履行mKeyguardViewMediator的onSystemReady()办法
            mKeyguardViewMediator.onSystemReady();
            Trace.endSection();
        }
        //省掉部分代码
    };
}

因而,KeyguardServiceWrapper中的办法终究都会经过aidl调用到KeyguardService中对应的办法,所以上述KeyguardServiceWrapper的onSystemReady()办法会调用KeyguardService的onSystemReady()办法,该办法中履行了mKeyguardViewMediator的onSystemReady()办法,当然mKeyguardViewMediator目标在KeyguardService的onCreate()办法中就现已创立了,看下KeyguardViewMediator的onSystemReady()办法的源码

KeyguardViewMediator

KeyguardViewMediator的源码如下

public class KeyguardViewMediator extends SystemUI {
    //省掉部分代码
    /**
     * Let us know that the system is ready after startup.
     */
    public void onSystemReady() {
        //发送标识为SYSTEM_READY的音讯
        mHandler.obtainMessage(SYSTEM_READY).sendToTarget();
    }
    private void handleSystemReady() {
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            Log.d("jason", "doKeyguardLocked5");
            //锁屏页的显现在此办法中操控
            doKeyguardLocked(null);
            //注册键盘锁更新监听
            mUpdateMonitor.registerCallback(mUpdateCallback);
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }
    //省掉部分代码
    /**
     * 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
        //假如有其他app不让显现,则不显现
        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
        //假如锁屏页现已处于显现状况,则不处理
        if (mStatusBarKeyguardViewManager.isShowing()) {
            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
            Log.d("jason", "resetStateLocked10");
            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);
            //是否存在短少的SIM卡,也便是空卡槽
            final boolean absent = SubscriptionManager.isValidSubscriptionId(
                    mUpdateMonitor.getNextSubIdForState(ABSENT));
            //是否存在未授权的SIM卡
            final boolean disabled = SubscriptionManager.isValidSubscriptionId(
                    mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.PERM_DISABLED));
            //是否有任一SIM卡是安全的
            boolean simPinSecure = mUpdateMonitor.isSimPinSecure();
            final boolean lockedOrMissing = simPinSecure
                    || ((absent || disabled) && requireSim);
            Log.d("jason", "simPinSecure:"+simPinSecure);
            Log.d("jason", "requireSim:"+requireSim+", absent:"+absent+", disabled:"+disabled+", lockedOrMissing:"+lockedOrMissing);
            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);
            //用户是否禁用锁屏,假如锁屏办法设为None,则为true,否则为false
            boolean lockScreenDisabled = mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser());
            Log.d("jason", "lockScreenDisabled:"+lockScreenDisabled+", lockedOrMissing:"+lockedOrMissing+", forceShow:"+forceShow);
            if (lockScreenDisabled
                    && !lockedOrMissing && !forceShow) {
                if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
                return;
            }
            if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
                if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
                // Without this, settings is not enabled until the lock screen first appears
                setShowingLocked(false);
                hideLocked();
                return;
            }
        }
        if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
        Log.d("jason", "showing the lock screen");
        //显现锁屏
        showLocked(options);
    }
    //省掉部分代码
    private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                //省掉部分代码
                //处理SYSTEM_READY音讯
                case SYSTEM_READY:
                    handleSystemReady();
                    break;
            }
        }
    };
}

首要能够看到KeyguardViewMediator承继自SystemUI,这也验证了前面说的锁屏页也是归于SystemUI。在KeyguardViewMediator的onSystemReady()办法中,经过Handler发送了一条SYSTEM_READY音讯,处理此音讯时履行了handleSystemReady()办法,handleSystemReady()办法中又履行了doKeyguardLocked()办法,锁屏页的显现/隐藏操控就在这个办法里边。留意,源码中TAG为jason的log是我在调试进程中埋的。

锁屏办法设置

在doKeyguardLocked()办法中有很重要的一个逻辑,便是获取用户设置的锁屏办法,锁屏办法大概有五种:None(无),Swipe(滑动),Pattern(图画),PIN(pin码),Password(暗码)

image-20230111185759862

只有为None时mLockPatternUtils.isLockScreenDisabled()才会回来true,下面是锁屏办法获取和保存的相关源码

public class LockPatternUtils {
    //省掉部分代码
    private ILockSettings mLockSettingsService;
    //省掉部分代码
    @UnsupportedAppUsage
    @VisibleForTesting
    public ILockSettings getLockSettings() {
        if (mLockSettingsService == null) {
            ILockSettings service = ILockSettings.Stub.asInterface(
                    ServiceManager.getService("lock_settings"));
            mLockSettingsService = service;
        }
        return mLockSettingsService;
    }
    //省掉部分代码
    /**
     * Determine if LockScreen is disabled for the current user. This is used to decide whether
     * LockScreen is shown after reboot or after screen timeout / short press on power.
     *
     * @return true if lock screen is disabled
     */
    @UnsupportedAppUsage
    public boolean isLockScreenDisabled(int userId) {
        if (isSecure(userId)) {
            return false;
        }
        boolean disabledByDefault = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_disableLockscreenByDefault);
        boolean isSystemUser = UserManager.isSplitSystemUser() && userId == UserHandle.USER_SYSTEM;
        UserInfo userInfo = getUserManager().getUserInfo(userId);
        boolean isDemoUser = UserManager.isDeviceInDemoMode(mContext) && userInfo != null
                && userInfo.isDemo();
        //获取用户设置的锁屏办法
        return getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId)
                || (disabledByDefault && !isSystemUser)
                || isDemoUser;
    }
    //省掉部分代码
    private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
        try {
            //经过aidl拜访LockSettingsService,获取用户保存的锁屏办法
            return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId);
        } catch (RemoteException re) {
            return defaultValue;
        }
    }
    //省掉部分代码
}

上述源码中获取用户保存的锁屏办法终究是经过aidl拜访LockSettingsService获取用户保存的锁屏办法,查看LockSettingsService的源码

public class LockSettingsService extends ILockSettings.Stub {
    //省掉部分代码
    @Override
    public boolean getBoolean(String key, boolean defaultValue, int userId) {
        checkReadPermission(key, userId);
        String value = getStringUnchecked(key, null, userId);
        return TextUtils.isEmpty(value) ?
                defaultValue : (value.equals("1") || value.equals("true"));
    }
    //省掉部分代码
    public String getStringUnchecked(String key, String defaultValue, int userId) {
        if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
            long ident = Binder.clearCallingIdentity();
            try {
                return mLockPatternUtils.isLockPatternEnabled(userId) ? "1" : "0";
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
        if (userId == USER_FRP) {
            return getFrpStringUnchecked(key);
        }
        if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) {
            key = Settings.Secure.LOCK_PATTERN_ENABLED;
        }
        //调用LockSettingsStorage的readKeyValue()
        return mStorage.readKeyValue(key, defaultValue, userId);
    }
}

终究调用LockSettingsStorage的readKeyValue()办法

class LockSettingsStorage {
    public String readKeyValue(String key, String defaultValue, int userId) {
        //先从缓存中查找
        int version;
        synchronized (mCache) {
            if (mCache.hasKeyValue(key, userId)) {
                return mCache.peekKeyValue(key, defaultValue, userId);
            }
            version = mCache.getVersion();
        }
        Cursor cursor;
        Object result = DEFAULT;
        //从sqlite数据库中查找
        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY,
                COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?",
                new String[] { Integer.toString(userId), key },
                null, null, null)) != null) {
            if (cursor.moveToFirst()) {
                result = cursor.getString(0);
            }
            cursor.close();
        }
        //将数据库中的数据寄存到缓存中
        mCache.putKeyValueIfUnchanged(key, result, userId, version);
        return result == DEFAULT ? defaultValue : (String) result;
    }
}

可见用户设置的锁屏办法终究存在放了sqlite数据库里边,而详细寄存进程在ChooseLockGeneric.ChooseLockGenericFragment类中

public class ChooseLockGeneric extends SettingsActivity {
    //省掉部分代码
    public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
        //省掉部分代码
        //用户挑选锁屏办法回调
        @Override
        public boolean onPreferenceTreeClick(Preference preference) {
            final String key = preference.getKey();
            if (!isUnlockMethodSecure(key) && mLockPatternUtils.isSecure(mUserId)) {
                // Show the disabling FRP warning only when the user is switching from a secure
                // unlock method to an insecure one
                showFactoryResetProtectionWarningDialog(key);
                return true;
            } else if (KEY_SKIP_FINGERPRINT.equals(key) || KEY_SKIP_FACE.equals(key)) {
                Intent chooseLockGenericIntent = new Intent(getActivity(),
                    getInternalActivityClass());
                chooseLockGenericIntent.setAction(getIntent().getAction());
                // Forward the target user id to  ChooseLockGeneric.
                chooseLockGenericIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
                chooseLockGenericIntent.putExtra(CONFIRM_CREDENTIALS, !mPasswordConfirmed);
                chooseLockGenericIntent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY,
                        mRequestedMinComplexity);
                chooseLockGenericIntent.putExtra(EXTRA_KEY_CALLER_APP_NAME, mCallerAppName);
                if (mUserPassword != null) {
                    chooseLockGenericIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
                            mUserPassword);
                }
                startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
                return true;
            } else {
                //保存用户设置的锁屏办法
                return setUnlockMethod(key);
            }
        }
        private void maybeEnableEncryption(int quality, boolean disabled) {
            DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
            if (UserManager.get(getActivity()).isAdminUser()
                    && mUserId == UserHandle.myUserId()
                    && LockPatternUtils.isDeviceEncryptionEnabled()
                    && !LockPatternUtils.isFileEncryptionEnabled()
                    && !dpm.getDoNotAskCredentialsOnBoot()) {
                // Get the intent that the encryption interstitial should start for creating
                // the new unlock method.
                Intent unlockMethodIntent = getIntentForUnlockMethod(quality);
                unlockMethodIntent.putExtra(
                        ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT,
                        mForChangeCredRequiredForBoot);
                final Context context = getActivity();
                // If accessibility is enabled and the user hasn't seen this dialog before, set the
                // default state to agree with that which is compatible with accessibility
                // (password not required).
                final boolean accEn = AccessibilityManager.getInstance(context).isEnabled();
                final boolean required = mLockPatternUtils.isCredentialRequiredToDecrypt(!accEn);
                Intent intent = getEncryptionInterstitialIntent(context, quality, required,
                        unlockMethodIntent);
                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
                        mForFingerprint);
                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE,
                        mForFace);
                startActivityForResult(
                        intent,
                        mIsSetNewPassword && mHasChallenge
                                ? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST
                                : ENABLE_ENCRYPTION_REQUEST);
            } else {
                if (mForChangeCredRequiredForBoot) {
                    // Welp, couldn't change it. Oh well.
                    finish();
                    return;
                }
                //仍是调用updateUnlockMethodAndFinish()
                updateUnlockMethodAndFinish(quality, disabled, false /* chooseLockSkipped */);
            }
        }
        //省掉部分代码
        private boolean setUnlockMethod(String unlockMethod) {
            EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod);
            ScreenLockType lock = ScreenLockType.fromKey(unlockMethod);
            if (lock != null) {
                switch (lock) {
                    case NONE:
                    case SWIPE:
                        //NONE和SWIPE都归于未加密的
                        updateUnlockMethodAndFinish(
                                lock.defaultQuality,
                                lock == ScreenLockType.NONE,
                                false /* chooseLockSkipped */);
                        return true;
                    case PATTERN:
                    case PIN:
                    case PASSWORD:
                    case MANAGED:
                        //PATTERN、PIN、PASSWORD、MANAGED都是归于加密的
                        maybeEnableEncryption(lock.defaultQuality, false);
                        return true;
                }
            }
            Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
            return false;
        }
        //省掉部分代码
        void updateUnlockMethodAndFinish(int quality, boolean disabled, boolean chooseLockSkipped) {
            // Sanity check. We should never get here without confirming user's existing password.
            if (!mPasswordConfirmed) {
                throw new IllegalStateException("Tried to update password without confirming it");
            }
            quality = mController.upgradeQuality(quality);
            Intent intent = getIntentForUnlockMethod(quality);
            if (intent != null) {
                if (getIntent().getBooleanExtra(EXTRA_SHOW_OPTIONS_BUTTON, false)) {
                    intent.putExtra(EXTRA_SHOW_OPTIONS_BUTTON, chooseLockSkipped);
                }
                intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras());
                startActivityForResult(intent,
                        mIsSetNewPassword && mHasChallenge
                                ? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST
                                : CHOOSE_LOCK_REQUEST);
                return;
            }
            if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
                //先清除旧数据
                mChooseLockSettingsHelper.utils().clearLock(mUserPassword, mUserId);
                //保存到数据库,仍是经过LockPatternUtils的setLockScreenDisabled()办法
                mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId);
                getActivity().setResult(Activity.RESULT_OK);
                removeAllBiometricsForUserAndFinish(mUserId);
            } else {
                removeAllBiometricsForUserAndFinish(mUserId);
            }
        }
    }
    //省掉部分代码
}

上述源码中,用户在Settings里边设置了锁屏办法之后,终究都是经过LockPatternUtils.setLockScreenDisabled()来保存

public class LockPatternUtils {
    //省掉部分代码
    /**
     * Disable showing lock screen at all for a given user.
     * This is only meaningful if pattern, pin or password are not set.
     *
     * @param disable Disables lock screen when true
     * @param userId User ID of the user this has effect on
     */
    public void setLockScreenDisabled(boolean disable, int userId) {
        setBoolean(DISABLE_LOCKSCREEN_KEY, disable, userId);
    }
    //省掉部分代码
    private void setBoolean(String secureSettingKey, boolean enabled, int userId) {
        try {
            //经过aidl拜访LockSettingsService,保存用户保存的锁屏办法
            getLockSettings().setBoolean(secureSettingKey, enabled, userId);
        } catch (RemoteException re) {
            // What can we do?
            Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
        }
    }
    //省掉部分代码
}

同样经过aidl拜访LockSettingsService,调用它的setBoolean()办法

public class LockSettingsService extends ILockSettings.Stub {
    //省掉部分代码
    @Override
    public void setBoolean(String key, boolean value, int userId) {
        checkWritePermission(userId);
        setStringUnchecked(key, userId, value ? "1" : "0");
    }
    //省掉部分代码
    private void setStringUnchecked(String key, int userId, String value) {
        Preconditions.checkArgument(userId != USER_FRP, "cannot store lock settings for FRP user");
        mStorage.writeKeyValue(key, value, userId);
        if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) {
            BackupManager.dataChanged("com.android.providers.settings");
        }
    }
    //省掉部分代码
}

终究经过LockSettingsStorage的writeKeyValue()办法来保存

class LockSettingsStorage {
    //省掉部分代码
    public void writeKeyValue(String key, String value, int userId) {
        writeKeyValue(mOpenHelper.getWritableDatabase(), key, value, userId);
    }
    public void writeKeyValue(SQLiteDatabase db, String key, String value, int userId) {
        //经过sqlite数据库来耐久保存
        ContentValues cv = new ContentValues();
        cv.put(COLUMN_KEY, key);
        cv.put(COLUMN_USERID, userId);
        cv.put(COLUMN_VALUE, value);
        db.beginTransaction();
        try {
            db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
                    new String[] {key, Integer.toString(userId)});
            db.insert(TABLE, null, cv);
            db.setTransactionSuccessful();
            //将数据保存到缓存中
            mCache.putKeyValue(key, value, userId);
        } finally {
            db.endTransaction();
        }
    }
    //省掉部分代码
}

梳理完锁屏办法的保存和读取后,再回到KeyguardViewMediator的doKeyguardLocked()办法傍边

public class KeyguardViewMediator extends SystemUI {
    /**
     * 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
        //假如有其他app不让显现,则不显现
        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
        //假如锁屏页现已处于显现状况,则不处理
        if (mStatusBarKeyguardViewManager.isShowing()) {
            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
            Log.d("jason", "resetStateLocked10");
            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);
            //是否存在短少的SIM卡,也便是空卡槽
            final boolean absent = SubscriptionManager.isValidSubscriptionId(
                    mUpdateMonitor.getNextSubIdForState(ABSENT));
            //是否存在未授权的SIM卡
            final boolean disabled = SubscriptionManager.isValidSubscriptionId(
                    mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.PERM_DISABLED));
            //是否有任一SIM卡是安全的
            boolean simPinSecure = mUpdateMonitor.isSimPinSecure();
            final boolean lockedOrMissing = simPinSecure
                    || ((absent || disabled) && requireSim);
            Log.d("jason", "simPinSecure:"+simPinSecure);
            Log.d("jason", "requireSim:"+requireSim+", absent:"+absent+", disabled:"+disabled+", lockedOrMissing:"+lockedOrMissing);
            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);
            //用户是否禁用锁屏,假如锁屏办法设为None,则为true,否则为false
            //-----代码1-----
            boolean lockScreenDisabled = mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser());
            Log.d("jason", "lockScreenDisabled:"+lockScreenDisabled+", lockedOrMissing:"+lockedOrMissing+", forceShow:"+forceShow);
            //-----代码2-----
            if (lockScreenDisabled
                    && !lockedOrMissing && !forceShow) {
                if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
                return;
            }
            if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
                if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
                // Without this, settings is not enabled until the lock screen first appears
                setShowingLocked(false);
                hideLocked();
                return;
            }
        }
        if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
        Log.d("jason", "showing the lock screen");
        //显现锁屏
        //-----代码3-----
        showLocked(options);
    }
}

假如用户设置的为None(由于现象便是设为None后依然显现锁屏页),那么代码1处,lockScreenDisabled就为true,而lockedOrMissing和forceShow经过日志打印均为false,所以,代码2处的if条件是成立的,终究直接return,不会履行代码3。

SIM卡状况监听

在上面KeyguardViewMediator.handleSystemReady()办法中,当doKeyguardLocked()履行完后会注册KeyguardUpdate监听,当键盘锁发生任何改变会回调相对应的办法

public class KeyguardViewMediator extends SystemUI {
    //省掉部分代码
    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
        //省掉部分代码
        @Override
        public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simState) {
            //Sim卡状况改变回调
            //省掉部分代码
            switch (simState) {
                case NOT_READY:
                case ABSENT:
                    // only force lock screen in case of missing sim if user hasn't
                    // gone through setup wizard
                    synchronized (KeyguardViewMediator.this) {
                        if (shouldWaitForProvisioning()) {
                            if (!mShowing) {
                                if (DEBUG_SIM_STATES) Log.d(TAG, "ICC_ABSENT isn't showing,"
                                        + " we need to show the keyguard since the "
                                        + "device isn't provisioned yet.");
                                Log.d("jason", "doKeyguardLocked2");
                                doKeyguardLocked(null);
                            } else {
                                Log.d("jason", "resetStateLocked2");
                                resetStateLocked();
                            }
                        }
                        if (simState == ABSENT) {
                            // MVNO SIMs can become transiently NOT_READY when switching networks,
                            // so we should only lock when they are ABSENT.
                            if (simWasLocked) {
                                if (DEBUG_SIM_STATES) Log.d(TAG, "SIM moved to ABSENT when the "
                                        + "previous state was locked. Reset the state.");
                                Log.d("jason", "resetStateLocked3");
                                resetStateLocked();
                            }
                        }
                    }
                    break;
                case PIN_REQUIRED:
                case PUK_REQUIRED:
                    synchronized (KeyguardViewMediator.this) {
                        if (!mShowing) {
                            if (DEBUG_SIM_STATES) Log.d(TAG,
                                    "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
                                    + "showing; need to show keyguard so user can enter sim pin");
                            Log.d("jason", "doKeyguardLocked3");
                            doKeyguardLocked(null);
                        } else {
                            Log.d("jason", "resetStateLocked4");
                            //更新当时屏幕锁的状况
                            //-----代码4-----
                            resetStateLocked();
                        }
                    }
                    break;
                case PERM_DISABLED:
                    synchronized (KeyguardViewMediator.this) {
                        if (!mShowing) {
                            if (DEBUG_SIM_STATES) Log.d(TAG, "PERM_DISABLED and "
                                  + "keygaurd isn't showing.");
                            Log.d("jason", "doKeyguardLocked4");
                            doKeyguardLocked(null);
                        } else {
                            if (DEBUG_SIM_STATES) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
                                  + "show permanently disabled message in lockscreen.");
                            Log.d("jason", "resetStateLocked5");
                            resetStateLocked();
                        }
                    }
                    break;
                case READY:
                    synchronized (KeyguardViewMediator.this) {
                        if (DEBUG_SIM_STATES) Log.d(TAG, "READY, reset state? " + mShowing);
                        if (mShowing && simWasLocked) {
                            if (DEBUG_SIM_STATES) Log.d(TAG, "SIM moved to READY when the "
                                    + "previous state was locked. Reset the state.");
                            Log.d("jason", "resetStateLocked6");
                            resetStateLocked();
                        }
                    }
                    break;
                default:
                    if (DEBUG_SIM_STATES) Log.v(TAG, "Unspecific state: " + simState);
                    break;
            }
        }
        //省掉部分代码
    };
    private void handleSystemReady() {
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            Log.d("jason", "doKeyguardLocked5");
            doKeyguardLocked(null);
            //注册KeyguardUpdate监听
            mUpdateMonitor.registerCallback(mUpdateCallback);
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }
    //省掉部分代码
}

当开机后,体系底层(Modem)会去读取SIM卡状况,然后将状况值返给上层(也是运用的aidl进行跨进程通讯,此处不做过多剖析),这儿注册KeyguardUpdate监听后能在onSimStateChanged()回调办法里拿到SIM卡的状况。SIM卡的状况包含以下几种

public class IccCardConstants {
    //省掉部分代码
    public enum State {
        UNKNOWN,        /** ordinal(0) == {@See TelephonyManager#SIM_STATE_UNKNOWN} */
        ABSENT,         /** ordinal(1) == {@See TelephonyManager#SIM_STATE_ABSENT} */
        PIN_REQUIRED,   /** ordinal(2) == {@See TelephonyManager#SIM_STATE_PIN_REQUIRED} */
        PUK_REQUIRED,   /** ordinal(3) == {@See TelephonyManager#SIM_STATE_PUK_REQUIRED} */
        NETWORK_LOCKED, /** ordinal(4) == {@See TelephonyManager#SIM_STATE_NETWORK_LOCKED} */
        READY,          /** ordinal(5) == {@See TelephonyManager#SIM_STATE_READY} */
        NOT_READY,      /** ordinal(6) == {@See TelephonyManager#SIM_STATE_NOT_READY} */
        PERM_DISABLED,  /** ordinal(7) == {@See TelephonyManager#SIM_STATE_PERM_DISABLED} */
        CARD_IO_ERROR,  /** ordinal(8) == {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR} */
        CARD_RESTRICTED,/** ordinal(9) == {@See TelephonyManager#SIM_STATE_CARD_RESTRICTED} */
        LOADED;         /** ordinal(9) == {@See TelephonyManager#SIM_STATE_LOADED} */
        //省掉部分代码
    }
}

首要初始状况是NOT_READY,但此刻不会做任何操作,然后由于咱们开启了SIM卡锁,所以状况紧接着会变为PIN_REQUIRED,这时代码4会履行,

public class KeyguardViewMediator extends SystemUI {
    //省掉部分代码
    private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                //省掉部分代码
                case RESET:
                    handleReset();
                    break;
                //省掉部分代码
            }
        }
    };
    //省掉部分代码
    private void resetStateLocked() {
        if (DEBUG) Log.e(TAG, "resetStateLocked");
        Message msg = mHandler.obtainMessage(RESET);
        mHandler.sendMessage(msg);
    }
    //省掉部分代码
    private void handleReset() {
        synchronized (KeyguardViewMediator.this) {
            if (DEBUG) Log.d(TAG, "handleReset");
            Log.d("jason", "reset1");
            mStatusBarKeyguardViewManager.reset(true /* hideBouncerWhenShowing */);
        }
    }
    //省掉部分代码
}

首要resetStateLocked中,Handler发送了一条RESET音讯,经过handleReset()办法来处理此音讯,handleReset()办法中调用了StatusBarKeyguardViewManager的reset()办法

public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
        StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
        PanelExpansionListener, NavigationModeController.ModeChangedListener {
    //省掉部分代码
    /**
     * Shows the notification keyguard or the bouncer depending on
     * {@link KeyguardBouncer#needsFullscreenBouncer()}.
     */
    protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
        if (mBouncer.needsFullscreenBouncer() && !mDozing) {
            Log.d("jason", "show bouncer");
            // The keyguard might be showing (already). So we need to hide it.
            mStatusBar.hideKeyguard();
            //显现SIM卡解锁页面
            mBouncer.show(true /* resetSecuritySelection */);
        } else {
            Log.d("jason", "show keyguard");
            //显现锁屏页面
            mStatusBar.showKeyguard();
            if (hideBouncerWhenShowing) {
                hideBouncer(shouldDestroyViewOnReset() /* destroyView */);
                mBouncer.prepare();
            }
        }
        updateStates();
    }
    //省掉部分代码
    /**
     * Reset the state of the view.
     */
    public void reset(boolean hideBouncerWhenShowing) {
        if (mShowing) {
            if (mOccluded && !mDozing) {
                mStatusBar.hideKeyguard();
                if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) {
                    hideBouncer(false /* destroyView */);
                }
            } else {
                //显现SIM卡解锁页面或者锁屏界面
                //-----代码5-----
                showBouncerOrKeyguard(hideBouncerWhenShowing);
            }
            KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
            updateStates();
        }
    }
}

reset()办法中会依据当时状况来决定是隐藏仍是显现解锁页面,这儿会履行代码5,依据办法名就能够知道,该办法的作用是操控显现Bouncer(SIM卡解锁页面)仍是Keyguard(锁屏页面),留意,这两个不是一个概念

  • Bouncer:在Settings->Security->SIM card lock中设置,设置的是SIM卡解锁,状况保存在SIM卡中,从头刺进另一个设备傍边依然需求PIN码解锁;
  • Keyguard:在Settings->Security->Screen lock中设置,设置的是体系解锁,状况保存在sqlite数据库傍边,显现与否取决于当时体系的设置;

由于在问题现象傍边,Bouncer是正常显现的,所以这儿对Bouncer不做深入研究,主要是Keyguard显现异常,这儿咱们也能够看到,Keyguard显现是经过mStatusBar.showkeyguard()来完结的,这也意味着Keyguard是StatusBar的一部分,而咱们在运用开发傍边经常打交道的所谓的StatusBar其实仅仅StatusBar顶部那一块罢了。

剖析思路

OK,开机解锁流程的源码剖析到这儿,现在问题的要害在于为啥在解锁完两张SIM卡之后还会显现锁屏页,经过上述源码剖析,猜测肯定是在show完两次bouncer之后,又show了一次keyguard,也便是又履行了一次代码5,意味着代码5所在的reset()办法又履行了一次,同理往上推,所以,我将一切或许履行到reset()办法的当地都打上log,并给它们编上号,然后抓一下开机操作日志,对比一下正常状况和异常状况的日志差异,经过多次操作,总算抓到这两份日志,别离如下:

正常状况(未显现锁屏页)的日志

image-20230112114934071

异常状况(显现锁屏页)的日志

image-20230112115022816

能够看到,当解锁完第二张SIM卡时,异常状况会多履行一次doKeyguardLocked()办法,并且是在SIM卡状况回调中履行的

public class KeyguardViewMediator extends SystemUI {
    //省掉部分代码
    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
        //省掉部分代码
        @Override
        public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simState) {
            //Sim卡状况改变回调
            //省掉部分代码
            switch (simState) {
                //省掉部分代码
                case PIN_REQUIRED:
                case PUK_REQUIRED:
                    synchronized (KeyguardViewMediator.this) {
                        if (!mShowing) {
                            if (DEBUG_SIM_STATES) Log.d(TAG,
                                    "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
                                    + "showing; need to show keyguard so user can enter sim pin");
                            Log.d("jason", "doKeyguardLocked3");
                            //多履行了一次这儿的逻辑
                            //-----代码6-----
                            doKeyguardLocked(null);
                        } else {
                            Log.d("jason", "resetStateLocked4");
                            resetStateLocked();
                        }
                    }
                    break;
                //省掉部分代码
            }
        }
        //省掉部分代码
    };
    private void handleSystemReady() {
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            Log.d("jason", "doKeyguardLocked5");
            doKeyguardLocked(null);
            //注册KeyguardUpdate监听
            mUpdateMonitor.registerCallback(mUpdateCallback);
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }
    //省掉部分代码
}

如上述源码,多履行了一次代码6,而该逻辑是在PIN_REQUIRED状况回调中履行的,这就很奇怪,按道理,解锁完SIM卡,状况应该由PIN_REQUIRED转变为READY,为啥又变回去了,所以,我将一切履行onSimStateChanged()回调的当地打上日志,看下状况究竟是怎样流通的

public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
    //省掉部分代码
    private void handleSimSubscriptionInfoChanged() {
        for (int i = 0; i < changedSubscriptions.size(); i++) {
            SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
            for (int j = 0; j < mCallbacks.size(); j++) {
                KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
                if (cb != null) {
                    //SIM卡状况回调,由于支撑双卡双待,所以运用for循坏将一切SIM的状况全部回调回去
                    Log.d("jason", "onSimStateChanged0: subId:"+data.subId+", slotId:"+data.slotId+", simState:"+data.simState);
                    cb.onSimStateChanged(data.subId, data.slotId, data.simState);
                }
            }
        }
    }
    //省掉部分代码
    @VisibleForTesting
    void handleSimStateChange(int subId, int slotId, State state) {
        //省掉部分代码
        if ((changed || becameAbsent) && state != State.UNKNOWN) {
            for (int i = 0; i < mCallbacks.size(); i++) {
                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
                if (cb != null) {
                    //SIM卡状况回调
                    Log.d("jason", "onSimStateChanged2: subId:"+subId+", slotId:"+slotId+", simState:"+state);
                    cb.onSimStateChanged(subId, slotId, state);
                }
            }
        }
    }
    //省掉部分代码
    private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
        // Notify listener of the current state
        callback.onRefreshBatteryInfo(mBatteryStatus);
        callback.onTimeChanged();
        callback.onRingerModeChanged(mRingMode);
        callback.onPhoneStateChanged(mPhoneState);
        callback.onRefreshCarrierInfo();
        callback.onClockVisibilityChanged();
        callback.onKeyguardVisibilityChangedRaw(mKeyguardIsVisible);
        callback.onTelephonyCapable(mTelephonyCapable);
        for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
            final SimData state = data.getValue();
            //SIM卡状况回调
            Log.d("jason", "onSimStateChanged3: subId:"+state.subId+", slotId:"+state.slotId+", simState:"+state.simState);
            callback.onSimStateChanged(state.subId, state.slotId, state.simState);
        }
    }
}

捕捉到的日志如下,重点关注解锁第二张SIM卡后的状况流通

正常状况(未显现锁屏页)的日志

image-20230112133642231

异常状况(显现锁屏页)的日志

image-20230112133739311

能够看到,正常状况下,解锁完两张SIM卡,卡1和卡2的状况都会置为READY,而异常状况下,后面会再次流通为PIN_REQUIRED,并终究置为READY,而这异常的状况流通导致多履行了一次doKeyguardLocked()办法,终究使得keyguard显现出来了。

剖析结论

所以,以目前剖析结果来看,问题的根源应该不在上层,由于SIM的状况是由底层(Modem)来更改流通的,上层仅仅接纳底层的回调,然后做相应的处理,随后此问题转给了Modem端同事处理。

总结/扩展

其实正常来讲,类似这种问题一般都不会是上层的问题,由于咱们剖析的都是Android的原生代码,假如Google有这种bug,早就会在某个安全补丁中修正此问题,不会到我这儿才爆出来,除非是某些特别场景下有特别的需求,才会去更改Android原生代码,比方设备要支撑刺进两张以上的SIM卡,这个时候才会需求修改Android原生代码。

image-20230112135843406

而底层的代码就不一定是原生代码了,Google只提供协议规范,详细完结一般是由各个厂商自行发挥,所以不同的厂商代码不太一样,比较闻名的厂商有高通(Qualcomm),联发科(MediaTek)等,紫光展锐(Unisoc),他们底层的代码或许都不太一样。

下图是Google对于这些资深协作厂商提供专门的安全补丁,给个传送门:source.android.google.cn/docs/securi…

image-20230112141204476

写在最终

经过我个人作业中的一个实践案例,给framework开发同行一些心得和启发,同时也让运用层开发的小伙伴了解一些framework开发的作业内容和作业流程,假如觉得这篇文章能让你有所收获,那就动动小手,一键三连吧,后续我将不定期分享一些我作业中遇到的一些典型问题以及处理进程,日子不易,一起加油成长吧!