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.