KeyguardBouncer start process

In this paper, the main line is to start the machine and show the PIN code unlocking interface for the first time. It introduces the organizational structure of KeyguardService and analyzes the presenting process of the password unlocking interface.

1, Boot to PhoneWindowManager

Start the init - > zygote - > systemserver process
The systemserver entry is main(), instantiating the systemserver object and calling its run() method.

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

   /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }

In the run() method, we focus on startOtherServices();
WindowManagerService is started at startOtherServices(),
Some codes are as follows:

private void startOtherServices() {
    WindowManagerService wm = null;
    wm = WindowManagerService.main(context, inputManager,
         mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
         !mFirstBoot, mOnlyCore);//Startup service
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);//Register to ServiceManager for other processes to call
        ......
    wm.systemReady();
}

WindowManagerService.systemReady():

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    final WindowManagerPolicy mPolicy = new PhoneWindowManager();//Generate a PhoneWindowManager instance
    public void systemReady() {
        mPolicy.systemReady();//Call PhoneWindowManager.systemReady()
    }
}

PhoneWindowManager.systemReady():

public void systemReady() {
    mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
    mKeyguardDelegate.onSystemReady();//Instance lock screen proxy class and call its onSystemReady()
}

2, Organization structure of KeyguardService

Here is an overall flow chart for you to view and analyze:

KeyguardServiceDelegate.onSystemReady():

protected KeyguardServiceWrapper mKeyguardService;//Lock screen service packaging
public void onSystemReady() {
        if (mKeyguardService != null) {
            mKeyguardService.onSystemReady();
        } else {
            mKeyguardState.systemIsReady = true;
        }
}

KeyguardServiceWrapper.onSystemReady():

private IKeyguardService mService;
public KeyguardServiceWrapper(Context context, IKeyguardService service) {
        mService = service;//Ikeguardservice is assigned in the constructor of KeyguardServiceWrapper
        mKeyguardStateMonitor = new KeyguardStateMonitor(context, service);
}
public void onSystemReady() {
        try {
            mService.onSystemReady();
        } catch (RemoteException e) {
            Slog.w(TAG , "Remote Exception", e);
        }
}

You can see that KeyguardServiceWrapper encapsulates the ikeguardservice. Its method implementation is mainly to
Call to ikeguardservice. Ikeguardservice is assigned in the constructor of KeyguardServiceWrapper.
Where is KeyguardServiceWrapper instantiated?
Take a look at the initialization process of KeyguardServiceDelegate later:

/**
* Use bindService to bind services. How to use bindService:
* The caller is bound with the service, and the service is terminated when the caller exits.
* ps => bind The execution order of the service is as follows:
* onCreate()->onBind()->onUnbind()->onDestroy()
*/
 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));
        //config_keyguardComponent->com.android.systemui/com.android.systemui.keyguard.KeyguardService

        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        intent.setComponent(keyguardComponent);
        
        //Here, the KeyguardServiceDelegate and KeyguardService are bound together.
        if (!context.bindServiceAsUser(intent, mKeyguardConnection,
                Context.BIND_AUTO_CREATE, mScrimHandler, 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;
                hideScrim();
            }
        } 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!)");
            //Get the Binder proxy object of KeyguardService through onServiceConnected(), and create the KeyguardService wrapper class
            //Instantiate KeyguardServiceWrapper
            mKeyguardService = new KeyguardServiceWrapper(mContext,
                    IKeyguardService.Stub.asInterface(service));
           ......
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
            mKeyguardService = null;
        }
    };

You can see that KeyguardServiceDelegate binds to KeyguardService. KeyguardServiceDelegate is equivalent to a client
KeyguardService is the server.
Take a look at KeyguardService:

public class KeyguardService extends Service {
    static final String TAG = "KeyguardService";
    static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;

    private KeyguardViewMediator mKeyguardViewMediator;

    @Override
    public void onCreate() {
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        mKeyguardViewMediator =
                ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;//This return value will be returned to onServiceConnected() of KeyguardServiceDelegate, through which the client and server can connect
    }
    
    
    //mBinder instantiation, overriding related interface methods
    private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
    
        @Override // Binder interface
        public void onSystemReady() {
            checkPermission();
            mKeyguardViewMediator.onSystemReady();//The actual KeyguardService calls the corresponding method of KeyguardViewMediator
        }
        ......
    }
}

KeyguardViewMediator.onSystemReady():

   /**
     * Let us know that the system is ready after startup.
     */
    public void onSystemReady() {
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            mWaitingKeyguardShowing = true;
            mKeyguardViewManager.setSystemReady(mSystemReady);
            mUpdateMonitor.registerCallback(mUpdateCallback);
            doKeyguardLockedIgnoreSecViewTimeout(null);//The real entrance for screen lock adjustment is used for screen lock pretreatment
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }

3, KeyguardBouncer presentation process

The above call is as follows:
WindowManagerService.systemReady() ->PhoneWindowManager.systemReady()->KeyguardServiceDelegate.onSystemReady()
->KeyguardServiceWrapper.onSystemReady()->KeyguardService.onSystemReady()->
KeyguardViewMediator.onSystemReady():doKeyguardLocked().

KeyguardViewMediator.doKeyguardLocked():

private void doKeyguardLocked(Bundle options) {
        //If other apps prevent us from displaying, then do not display.. For example: answering and calling
        if (!mExternallyEnabled || PowerOffAlarmManager.isAlarmBoot()) {
            return;
        }
        
        //If the lock screen is showing, we won't show it
        if (mStatusBarKeyguardViewManager.isShowing()) {
            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
            resetStateLocked();
            if (DEBUG) {
                Log.d(TAG, "doKeyguard: not showing because it is already showing");
            }
            return;
        }

        ......
        //After the above judgment, go to display the lock screen
        showLocked(options);
    }

KeyguardViewMediator.showLocked():

private void showLocked(Bundle options) {
        ......
        //Acquire the lock screen lock to prevent the cpu from entering sleep, so as to display the lock screen completely
        mShowKeyguardWakeLock.acquire();
        Message msg = mHandler.obtainMessage(SHOW, options);
        mHandler.sendMessage(msg);//Send SHOW message
}

 public void handleMessage(Message msg) {
            switch (msg.what) {
                case SHOW:
                    handleShow((Bundle) msg.obj);
                    break;
}

KeyguardViewMediator.handleShow():

private void handleShow(Bundle options) {
        mStatusBarKeyguardViewManager =
                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
                        mViewMediatorCallback, mLockPatternUtils);
        synchronized (KeyguardViewMediator.this) {
            ......
            mStatusBarKeyguardViewManager.show(options);//Mainly called here
            ......
}

StatusBarKeyguardViewManager.show():

public void show(Bundle options) {
        ......
        reset();
}

StatusBarKeyguardViewManager.reset():

public void reset() {
    if (mShowing) {
        if (mOccluded) {//If there is any obstruction, hide the lock screen if there is one. If not, judge whether to display the lock screen or the password unlocking interface
                mPhoneStatusBar.hideKeyguard();
                mPhoneStatusBar.stopWaitingForKeyguardExit();
                mBouncer.hide(false /* destroyView */);
            } else {
                showBouncerOrKeyguard();//Judge whether to display lock screen or password unlocking interface
            }
       KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
       updateStates();
    }
}

StatusBarKeyguardViewManager.showBouncerOrKeyguard():

protected void showBouncerOrKeyguard() {
    if (mBouncer.needsFullscreenBouncer()) {//Whether to display password lock screen interface
            // The keyguard might be showing (already). So we need to hide it.
        mPhoneStatusBar.hideKeyguard();//Hide the lock screen and display the password unlocking interface
        mBouncer.show(true /* resetSecuritySelection */);
    } else {
        mPhoneStatusBar.showKeyguard();//Display the lock screen and hide the password unlocking interface
        mBouncer.hide(false /* destroyView */);
        mBouncer.prepare();
    }
}

Bouncer.needsFullscreenBouncer():

public boolean needsFullscreenBouncer() {
        ensureView();
        SecurityMode mode = mSecurityModel.getSecurityMode();//Get the current security mode
        return mode == SecurityMode.SimPinPukMe1
                || mode == SecurityMode.SimPinPukMe2
                || mode == SecurityMode.SimPinPukMe3
                || mode == SecurityMode.SimPinPukMe4
                || mode == SecurityMode.AntiTheft
                || mode == SecurityMode.AlarmBoot;
}

KeyguardSecurityModel.getSecurityMode():

public SecurityMode getSecurityMode() { 
        KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);

        SecurityMode mode = SecurityMode.None;

        if (PowerOffAlarmManager.isAlarmBoot()) { /// M: add for power-off alarm
            mode = SecurityMode.AlarmBoot;
        } else {
            //Check whether the Pin/Puk/Me of the current sim card has been unlocked
            for (int i = 0; i < KeyguardUtils.getNumOfPhone(); i++) {
                if (isPinPukOrMeRequiredOfPhoneId(i)) {//Determine whether password unlocking is required for this card
                    if (0 == i) {
                        mode = SecurityMode.SimPinPukMe1;
                    } else if (1 == i) {
                        mode = SecurityMode.SimPinPukMe2;
                    } else if (2 == i) {
                        mode = SecurityMode.SimPinPukMe3;
                    } else if (3 == i) {
                        mode = SecurityMode.SimPinPukMe4;
                    }
                    break;
                }
            }
        }
        //Need to display anti-theft protection
        if (AntiTheftManager.isAntiTheftPriorToSecMode(mode)) {
            Log.d("KeyguardSecurityModel", "should show AntiTheft!") ;
            mode = SecurityMode.AntiTheft;
        }
//If the current security mode is neither Pin/Puk/Me nor anti-theft protection of sim card, check whether it is PIN code, password or gesture
        if (mode == SecurityMode.None) {
            final int security = mLockPatternUtils.getActivePasswordQuality(
                    KeyguardUpdateMonitor.getCurrentUser());
            switch (security) {
                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
                    return SecurityMode.PIN;

                case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
                case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
                case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
                    return SecurityMode.Password;

                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
                    return SecurityMode.Pattern;
                case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
                    return SecurityMode.None;

                default:
                    throw new IllegalStateException("Unknown security quality:" + security);
            }
        }

        Log.d(TAG, "getSecurityMode() - mode = " + mode);
        return mode;
    }

In this paper, taking Pin code unlocking of sim card 1 as an example, getSecurityMode returns securitymode.simpinpkme1. To needsFullscreenBouncer(),
Then go to showbouncerkeyguard(), when the condition of mbouncer. Needsfullscrreenbouncer() is true, hide the lock screen and display the bouncer
mBouncer.show(true /* resetSecuritySelection * /); / / reset security selection

public void show(boolean resetSecuritySelection) {
    ......
    show(resetSecuritySelection, false) ;
}

public void show(boolean resetSecuritySelection, boolean authenticated) {
        ......
        if (resetSecuritySelection) {//At this time, resetSecuritySelection is true
            // showPrimarySecurityScreen() updates the current security method. This is needed in
            // case we are already showing and the current security method changed.
            mKeyguardView.showPrimarySecurityScreen();
        }
        ......
}
    
public void showPrimarySecurityScreen() {
      mSecurityContainer.showPrimarySecurityScreen(false);
}

KeyguardSecurityContainer.showPrimarySecurityScreen();

void showPrimarySecurityScreen(boolean turningOff) {
        //Obtain the current security mode, as analyzed above
        SecurityMode securityMode = mSecurityModel.getSecurityMode();
        ......
        showSecurityScreen(securityMode);
    }

KeyguardSecurityContainer.showSecurityScreen:

//At initial startup, mCurrentSecuritySelection is SecurityMode.Invalid
private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;

private void showSecurityScreen(SecurityMode securityMode) {
        //Determine whether the security mode of this parameter is the same as the current security mode. If it is the same, return directly.
        if ((securityMode == mCurrentSecuritySelection)
                && (securityMode != SecurityMode.AntiTheft)) {
            return;
        }
        //If different, notify the security mode of change
        VoiceWakeupManager.getInstance().notifySecurityModeChange(
                mCurrentSecuritySelection, securityMode);
        
        KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
       
        KeyguardSecurityView newView = getSecurityView(securityMode);//The key method is to obtain the corresponding view according to the security mode

        ......
        //Set related callback
        if (securityMode != SecurityMode.None) {
            newView.setKeyguardCallback(mCallback);
            newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
        }

        final int childCount = mSecurityViewFlipper.getChildCount();
        //Find and display the view corresponding to the current security mode. (at this time, PIN unlocking has been added to mSecurityViewFlipper in getSecurityView())
        //The view display here also reaches the end of the flow of this article.
        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
        for (int i = 0; i < childCount; i++) {
            if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
                mSecurityViewFlipper.setDisplayedChild(i);
                break;
            }
        }
        //Update current security selection
        mCurrentSecuritySelection = securityMode;
        ......
}

KeyguardSecurityContainer.getSecurityView():

private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);//Get the view id corresponding to the security mode
        KeyguardSecurityView view = null;
        final int children = mSecurityViewFlipper.getChildCount();
        //Take out the view corresponding to the view id of this security mode from mSecurityViewFlipper. According to the situation when the system first arrives here after power on, the obtained view is null
        for (int child = 0; child < children; child++) {
            if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {
                view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));
                break;
            }
        }
        //Get the corresponding layoutId according to the security mode
        int layoutId = getLayoutIdFor(securityMode);
        //If the mSecurityViewFlipper does not have this view and there is a layoutId corresponding to this security mode
        if (view == null && layoutId != 0) {
            //inflater Layout
            final LayoutInflater inflater = LayoutInflater.from(mContext);
            View v = inflater.inflate(layoutId, mSecurityViewFlipper, false);//view is drawn here to initialize each item.
            view = (KeyguardSecurityView) v;//
            //If it is keyguardsmimpipukmeview, you need to set the phone ID, and keyguardsmimpipukmeview will display the corresponding resources according to this phone ID
            if (view instanceof KeyguardSimPinPukMeView) {
                KeyguardSimPinPukMeView pinPukView = (KeyguardSimPinPukMeView) view;
                final int phoneId = mSecurityModel.getPhoneIdUsingSecurityMode(securityMode);
                pinPukView.setPhoneId(phoneId);
            }
            //Add this view to mSecurityViewFlipper
            mSecurityViewFlipper.addView(v);//Add view to mSecurityViewFlipper here
            updateSecurityView(v); //Update KeyguardSecurityView
        }
        return view;
}
private int getSecurityViewIdForMode(SecurityMode securityMode) {
        switch (securityMode) {
            case Pattern: return R.id.keyguard_pattern_view;
            case PIN: return R.id.keyguard_pin_view;
            case Password: return R.id.keyguard_password_view;
            case SimPinPukMe1:
            case SimPinPukMe2:
            case SimPinPukMe3:
            case SimPinPukMe4:
                return R.id.keyguard_sim_pin_puk_me_view ;
        }
        return 0;
}


protected int getLayoutIdFor(SecurityMode securityMode) {
        switch (securityMode) {
            case Pattern: return R.layout.keyguard_pattern_view;//gesture
            case PIN: return R.layout.keyguard_pin_view;//PIN code
            case Password: return R.layout.keyguard_password_view;//Password unlock

            case SimPinPukMe1:
            case SimPinPukMe2:
            case SimPinPukMe3:
            case SimPinPukMe4:
                return R.layout.mtk_keyguard_sim_pin_puk_me_view;//sim_pin_puk_me
            
            default:
                return 0;
        }
}

Here, view shows that the starting process is over.

 

Keywords: Android Java less

Added by Gecko24 on Thu, 09 Jan 2020 17:57:35 +0200