7.0SystemUI启动流程及整体视图介绍

做了SystemUI模块将近2年了,期间自己也通过努力将Google原生的界面改为市场上流行的UI效果,今天就系统总结一下

这个模块。

一:SystemUI主体框架启动流程

android设备上电,引导程序引导进入boot(通常是uboot),加载initramfs、kernel镜像,启动kernel后,进入用户态程序。第一个用户空间程序是init, PID固定是1.
init的基本功能有:

  • 管理设备
  • 解析并处理Android启动脚本init.rc
  • 实时维护这个init.rc中的服务,包括加载 Zygote

而在Zygote中将启动SystemServer组件。

本文将从SystemServer开始分析。
SystemServer 名为系统服务进程,负责启动 Android 系统的关键服务。

其入口是SystemServer.main():

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

可以看到main()中生成了SystemServer对象并执行了run方法。
SystemServer.run():

private void run() {
    ......

     // Start services.
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
            ......
       } catch (Throwable ex) {
           ...
            throw ex;
        }
        ...
        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
}

先看一眼startBootstrapServices();

 private void startBootstrapServices() {
        ......
        Installer installer = mSystemServiceManager.startService(Installer.class);

        // Activity manager runs the show.
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        ......
 }

在startBootstrapServices()中启动了mActivityManagerService。
随后,我们再回头去看startOtherServices():

private void startOtherServices() {
        final Context context = mSystemContext;
        AccountManagerService accountManager = null;
        ContentService contentService = null;
        .......

         mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {
              ......

                try {
                    startSystemUi(context);
                } catch (Throwable e) {
                    reportWtf("starting System UI", e);
                }
         .......

mActivityManagerService.systemReady创建线程去执行startSystemUi(context),从方法名称可以看出,这里将启动systemUI。

static final void startSystemUi(Context context) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui",
                    "com.android.systemui.SystemUIService"));
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.OWNER);
    }

通过intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
设置启动systemui程序的SystemUIService

进入SystemUIService:

public class SystemUIService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
    }
......

onCreate方法中获得SystemUIApplication对象并调用其startServicesIfNeeded方法:

 public void startServicesIfNeeded() {
        final int N = SERVICES.length;
        for (int i=0; i cl = SERVICES[i];
            try {
                mServices[i] = (SystemUI)cl.newInstance();//加载实例
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InstantiationException ex) {
                throw new RuntimeException(ex);
            }
            mServices[i].mContext = this;
            mServices[i].mComponents = mComponents;
            mServices[i].start();//start服务
            if (mBootCompleted) {
                mServices[i].onBootCompleted();
            }
        }
        mServicesStarted = true;
    }

可以看到startServicesIfNeeded()循环start了很多Services。
数组SERVICES的定义如下:

/**
 * The classes of the stuff to start.
 */
private final Class[] SERVICES = new Class[] {
        com.android.systemui.tuner.TunerService.class,//定制service暂时不清楚干什么的,没用过
        com.android.systemui.keyguard.KeyguardViewMediator.class,//锁屏
        com.android.systemui.recents.Recents.class,//最近进程
        com.android.systemui.volume.VolumeUI.class,//音量控制
        Divider.class,//好像是分屏
        com.android.systemui.statusbar.SystemBars.class,//系统状态栏
        com.android.systemui.usb.StorageNotification.class,//存储通知
        com.android.systemui.power.PowerUI.class,//电量
        com.android.systemui.media.RingtonePlayer.class,//铃声播放
        com.android.systemui.keyboard.KeyboardUI.class,//键盘相关,没用过
        com.android.systemui.tv.pip.PipUI.class,//暂时不清楚没用过
        com.android.systemui.shortcut.ShortcutKeyDispatcher.class//这个也没用过
};

可以看到子服务包括:TunerService,KeyguardViewMediator,Recents,VolumeUI,SystemBars,StorageNotification,PowerUI
RingtonePlayer,KeyboardUI。
不过这里的service与我们平时所讲的四大组件的service并不一样。这里的service只是继承了SystemUI类的普通对象而已。
例如SystemBars:

public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {
           ......
}

小结:

查看到这里,可以总结一下systemUI主体框架的启动流程:
SystemServer启动Android核心服务包括了ActivityManagerService
--->ActivityManagerService一旦启动完成就会在systemReady的回调里启动SystemUIService
--->SystemUIService.onCreate—--->SystemUIApplication.startServicesIfNeeded

--->循环中调用mServices[i].start()启动SystemUI的各种核心service。

二:各个service的基本流程介绍

①首先讲打交道最多的也是最复杂的一块:SystemBar

上述各服务启动之后其中的一项就包括SystemBar的启动

调用start

@Override
public void start() {
    if (DEBUG) Log.d(TAG, "start");
    mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
            mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
    mServiceMonitor.start();  // will call onNoService if no remote service is found
}

然后通过回调调用

@Override
public void onNoService() {
    if (DEBUG) Log.d(TAG, "onNoService");
    createStatusBarFromConfig();  // fallback to using an in-process implementation
}

private void createStatusBarFromConfig() {
    if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
    final String clsName = mContext.getString(R.string.config_statusBarComponent);
    if (clsName == null || clsName.length() == 0) {
        throw andLog("No status bar component configured", null);
    }
    Class cls = null;
    try {
        cls = mContext.getClassLoader().loadClass(clsName);
    } catch (Throwable t) {
        throw andLog("Error loading status bar component: " + clsName, t);
    }
    try {
        mStatusBar = (BaseStatusBar) cls.newInstance();
    } catch (Throwable t) {
        throw andLog("Error creating status bar component: " + clsName, t);
    }
    mStatusBar.mContext = mContext;
    mStatusBar.mComponents = mComponents;
    mStatusBar.start();
    if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}

name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar
PhoneStatusBar的start方法
@Override
public void start() {
super.start(); // calls createAndAddWindows()
}
@Override
public void createAndAddWindows() {
    addStatusBarWindow();
}

private void addStatusBarWindow() {
    makeStatusBarView();
    mStatusBarWindowManager = new StatusBarWindowManager(mContext);
    mRemoteInputController = new RemoteInputController(mStatusBarWindowManager,
            mHeadsUpManager);
    mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
protected PhoneStatusBarView makeStatusBarView() {
    final Context context = mContext;

    updateDisplaySize(); // populates mDisplayMetrics
    updateResources();

    inflateStatusBarWindow(context);
}
protected void inflateStatusBarWindow(Context context) {
    mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
            R.layout.super_status_bar, null);
}

至此我我找到了PhoneStatusBar的关键布局,现在结束,下面的布局细分我后续细讲。

②接下来我们讲解一下KeyguardViewMediator(也就是锁屏界面启动流程)

Zygote进程启动后会首先创建一个SystemServer进程,SystemServer进程在调用startOtherServices同时也会调用WindowManagerService的systemReady()方法

//frameworks/base/services/java/com/android/server/SystemServer.java 
private void startOtherServices() {
      ...
      wm = WindowManagerService.main(context, inputManager,
                   mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                   !mFirstBoot, mOnlyCore);
       ...
       try {
           wm.systemReady();
           Slog.i( "jason11" , "SystemServer wm.systemReady" );
       } catch (Throwable e) {
           reportWtf( "making Window Manager Service ready" , e);
       }
       ...
   }
在WindowManagerService中直接调用了PhoneWindowManager里的systemReady()

//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
//final WindowManagerPolicy mPolicy = new PhoneWindowManager(); 
   public void systemReady() {
       mPolicy.systemReady();
   }
在PhoneWindowManager的systemReady()会根据一个Boolean值bindKeyguardNow来决定是否绑定keyguard service
//frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java 
/** {@inheritDoc} */
   @Override
   public void systemReady() {
       mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
       mKeyguardDelegate.onSystemReady();
 
       readCameraLensCoverState();
       updateUiMode();
       boolean bindKeyguardNow;
       synchronized (mLock) {
           updateOrientationListenerLp();
           mSystemReady = true ;
           mHandler.post( new Runnable() {
               @Override
               public void run() {
                   updateSettings();
               }
           });
 
           bindKeyguardNow = mDeferBindKeyguard;
           if (bindKeyguardNow) {
               // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
               mDeferBindKeyguard = false ;
           }
       }
       if (bindKeyguardNow) {
           mKeyguardDelegate.bindService(mContext);
           mKeyguardDelegate.onBootCompleted();
       }
       mSystemGestures.systemReady();
   }
看到这里,可能会想到如果bindKeyguardNow为false就会不绑定,后面通过继续跟踪发现在PhoneWindowManager的 systemBooted()里也会去绑定keyguard service,如果在 systemBooted里绑定了就不在systemReady里再去绑定,自己测试的时候是在 systemBooted绑定的

//frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java 
    /** {@inheritDoc} */
   @Override
   public void systemBooted() {
       boolean bindKeyguardNow = false ;
       synchronized (mLock) {
           // Time to bind Keyguard; take care to only bind it once, either here if ready or
           // in systemReady if not.
           if (mKeyguardDelegate != null ) {
               bindKeyguardNow = true ;
           } else {
               // Because mKeyguardDelegate is null, we know that the synchronized block in
               // systemReady didn't run yet and setting this will actually have an effect.
               mDeferBindKeyguard = true ;
           }
       }
       if (bindKeyguardNow) {
           mKeyguardDelegate.bindService(mContext);
           mKeyguardDelegate.onBootCompleted();
       }
       synchronized (mLock) {
           mSystemBooted = true ;
       }
       startedWakingUp();
       screenTurningOn( null );
       screenTurnedOn();
   }

下面就通过如下的时序图看看是如何调用到systemBooted的,就不在一步步跟了

7.0SystemUI启动流程及整体视图介绍_第1张图片

通过上面的分析知道,无论是在systemReady或systemBooted,都调用了KeyguardServiceDelegate对象的bindService方法,下面就以这个方法开始,看看锁屏界面是怎么显示出来的,先看看下面的时序图,再来分步讲解7.0SystemUI启动流程及整体视图介绍_第2张图片

1、先来看看在KeyguardServiceDelegate如何绑定KeyguardService的

//frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
public class KeyguardServiceDelegate {
     ...
     public void bindService(Context context) {
         Intent intent = new Intent();
         final Resources resources = context.getApplicationContext().getResources();
 
         final ComponentName keyguardComponent = ComponentName.unflattenFromString(
                 resources.getString(com.android.internal.R.string.config_keyguardComponent));
         intent.setComponent(keyguardComponent);
 
         if (!context.bindServiceAsUser(intent, mKeyguardConnection,
                 Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
             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" );
         }
     }
     ...
}

在bindService中调用了bindServiceAsUser绑定指定intent的service,config_keyguardComponent的定义如下

//frameworks/base/core/res/res/values/config.xml
    
     "config_keyguardComponent" translatable= "false" >com.android.systemui/com.android.systemui.keyguard.KeyguardService

当绑定成功后会调用mKeyguardConnection里的onServiceConnected方法

//frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
public class KeyguardServiceDelegate {
     ...
       private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)" );
             mKeyguardService = new KeyguardServiceWrapper(mContext,
                     IKeyguardService.Stub.asInterface(service));
             if (mKeyguardState.systemIsReady) {
                 // If the system is ready, it means keyguard crashed and restarted.
                 mKeyguardService.onSystemReady();
                 // This is used to hide the scrim once keyguard displays.
                 if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
                     mKeyguardService.onStartedWakingUp();
                 }
                 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);
             }
         }
 
         @Override
         public void onServiceDisconnected(ComponentName name) {
             if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)" );
             mKeyguardService = null ;
         }
 
     };
     ...
}
               
当mKeyguardState.systemIsReady为true是,就会通过KeyguardServiceWrapper的实例mKeyguardService调用onSystemReady方法,在KeyguardServiceWrapper的onSystemReady里调用了上面刚刚绑定成功的KeyguardService的onSystemReady方法
//frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
public class KeyguardServiceWrapper implements IKeyguardService {
     ...
     @Override // Binder interface
     public void onSystemReady() {
         try {
             mService.onSystemReady();
         } catch (RemoteException e) {
             Slog.w(TAG , "Remote Exception" , e);
         }
     }
     ...
}

在KeyguardService的onSystemReady里调用了KeyguardViewMediator里的onSystemReady,在这里就不贴这个代码了,直接看看KeyguardViewMediator.onSystemReady这个里面干啥了

2、KeyguardViewMediator.onSystemReady

//frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
public class KeyguardViewMediator extends SystemUI {
     ...
     public void onSystemReady() {
         mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
         synchronized ( this ) {
             if (DEBUG) Log.d(TAG, "onSystemReady" );
             mSystemReady = true ;
             doKeyguardLocked( null );
             mUpdateMonitor.registerCallback(mUpdateCallback);
         }
         // Most services aren't available until the system reaches the ready state, so we
         // send it here when the device first boots.
         maybeSendUserPresentBroadcast();
     }
     ...
}

在这个方法里主要调用了doKeyguardLocked和注册了KeyguardUpdateMonitorCallback

3、通过调用doKeyguardLocked显示锁屏界面

//frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
public class KeyguardViewMediator extends SystemUI {
     ...
     private void doKeyguardLocked(Bundle options) {
         // if another app is disabling us, don't show
         if (!mExternallyEnabled) {
             if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled" );
 
             // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
             // for an occasional ugly flicker in this situation:
             // 1) receive a call with the screen on (no keyguard) or make a call
             // 2) screen times out
             // 3) user hits key to turn screen back on
             // instead, we reenable the keyguard when we know the screen is off and the call
             // ends (see the broadcast receiver below)
             // TODO: clean this up when we have better support at the window manager level
             // for apps that wish to be on top of the keyguard
             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" );
             resetStateLocked();
             return ;
         }
 
         // if the setup wizard hasn't run yet, don't show
         final boolean requireSim = !SystemProperties.getBoolean( "keyguard.no_require_sim" , false );
         final boolean absent = SubscriptionManager.isValidSubscriptionId(
                 mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.ABSENT));
         final boolean disabled = SubscriptionManager.isValidSubscriptionId(
                 mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.PERM_DISABLED));
         final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()
                 || ((absent || disabled) && requireSim);
 
         if (!lockedOrMissing && shouldWaitForProvisioning()) {
             if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
                     + " and the sim is not locked or missing" );
             return ;
         }
 
         if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
                 && !lockedOrMissing) {
             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();
             mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();
             return ;
         }
 
         if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen" );
         showLocked(options);
     }
     ...
}
这段代码主要是在是否要显示锁屏之前做了5个判断:1.如果启用第三方锁屏界面,不显示原生界面;2.锁屏界面已经显示了话,重新更新下状态;3.如果第一次开机引导界面setup wizard还没有运行,也先不显示;4.屏幕没有亮不显示;5.当前正在解密界面不显示。如果这几个条件都不满足,则调用showLocked显示锁屏界面。在showLocked通过mHandler发送Message,在handleMessage里“case SHOW:”时调用handleShow

4、在handleShow里设置一些锁屏状态和显示锁屏界面

//frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
public class KeyguardViewMediator extends SystemUI {
     ...
         private void handleShow(Bundle options) {
         synchronized (KeyguardViewMediator. this ) {
             if (!mSystemReady) {
                 if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready." );
                 return ;
             } else {
                 if (DEBUG) Log.d(TAG, "handleShow" );
             }
 
             setShowingLocked( true );
             mStatusBarKeyguardViewManager.show(options);
             mHiding = false ;
             mWakeAndUnlocking = false ;
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false ;
             updateActivityLockScreenState();
             adjustStatusBarLocked();
             userActivity();
 
             mShowKeyguardWakeLock.release();
         }
         mKeyguardDisplayManager.show();
     }
     ...
}

5、通过调用StatusBarKeyguardViewManager的show重置当前状态显示keyguard

//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
public class StatusBarKeyguardViewManager {
     ...
     public void show(Bundle options) {
         mShowing = true ;
         mStatusBarWindowManager.setKeyguardShowing( true );
         mScrimController.abortKeyguardFadingOut();
         reset();
     }
     ...
}
在reset里调用本类的showBouncerOrKeyguard,在这个方法里通过KeyguardBouncer的实例mBouncer调用prepare(),在prepare里调用了KeyguardHostView的showPrimarySecurityScreen

6、KeyguardSecurityContainer.showPrimarySecurityScreen

在KeyguardHostView的showPrimarySecurityScreen里调用KeyguardSecurityContainer的showPrimarySecurityScreen方法,如下

//frameworks/base/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {
     ...
     void showPrimarySecurityScreen( boolean turningOff) {
         SecurityMode securityMode = mSecurityModel.getSecurityMode();
         if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")" );
         showSecurityScreen(securityMode);
     }
     ...
}
在这个方法里调用了showSecurityScreen,根据mSecurityModel.getSecurityMode()获取的SecurityMode来显示不同界面,SecurityMode定义如下
//frameworks/base/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
public class KeyguardSecurityModel {
     public enum SecurityMode {
         Invalid, // NULL state
         None, // No security enabled
         Pattern, // Unlock by drawing a pattern.
         Password, // Unlock by entering an alphanumeric password
         PIN, // Strictly numeric password
         SimPin, // Unlock by entering a sim pin.
         SimPuk // Unlock by entering a sim puk
     }
     ...
}

showSecurityScreen方法如下:

//frameworks/base/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {
     ...
     private void showSecurityScreen(SecurityMode securityMode) {
         if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")" );
 
         if (securityMode == mCurrentSecuritySelection) return ;
 
         KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
         KeyguardSecurityView newView = getSecurityView(securityMode); //根据securityMode获取对应的view
 
         // Emulate Activity life cycle
         if (oldView != null ) {
             oldView.onPause();
             oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
         }
         if (securityMode != SecurityMode.None) {
             newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
             newView.setKeyguardCallback(mCallback);
         }
 
         // Find and show this child.
         final int childCount = mSecurityViewFlipper.getChildCount();
 
         final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
         for ( int i = 0 ; i < childCount; i++) {
             if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
                 mSecurityViewFlipper.setDisplayedChild(i);
                 break ;
             }
         }
 
         mCurrentSecuritySelection = securityMode;
         mSecurityCallback.onSecurityModeChanged(securityMode,
                 securityMode != SecurityMode.None && newView.needsInput());
     }
     ...
}
到这里锁屏就启动完成了,这里简单总结一下:
1. 在KeyguardServiceDelegate里绑定KeyguardService,并调用onSystemReady方法。
2. KeyguardViewMediator里调用doKeyguardLocked来决定是否需要显示锁屏界面;如果显示则调用StatusBarKeyguardViewManager的show,最后调用到KeyguardHostView的showPrimarySecurityScreen()。
3. 在KeyguardSecurityContainer的showPrimarySecurityScreen利用mSecurityModel.getSecurityMode()获取当前的securityMode,传入showSecurityScreen来显示不同锁屏界面。



你可能感兴趣的:(SystemUI)