Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 7.1.1 鎖屏界面啟動流程

Android 7.1.1 鎖屏界面啟動流程

編輯:關於Android編程

Android 7.1.1 鎖屏界面啟動流程。前幾天遇到一個低概率復現鎖屏界面不顯示,只顯示狀態欄的問題,跟了下鎖屏界面啟動顯示的流程,在這分享下,也方便以後自己查看。前面簡單介紹了下Zygote啟動流程,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的,就不在一步步跟了

\

 

通過上面的分析知道,無論是在systemReady或systemBooted,都調用了KeyguardServiceDelegate對象的bindService方法,下面就以這個方法開始,看看鎖屏界面是怎麼顯示出來的,先看看下面的時序圖,再來分步講解

 

\

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
    
    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;
        }

    };
    ...
}
						
		
	
				
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved