Android10_原理機制系列_Window介紹及WMS的啓動過程

簡介

Window簡介

Android中,Window是一個重要部分,用戶看到的界面、觸摸顯示界面進行一系列操做都涉及到Window。但實際上,Window自己並不具有繪製功能。
該篇簡單介紹下Window的一點內容,同時總結下WMS的啓動過程。在下篇會逐步介紹一個Activity是如何建立出窗口 並 添加到WMS中的。
該篇基於Andorid10的代碼。html

窗口涉及到一下幾個功能:java

  1. 窗口管理-WMS
    WMS管理窗口的建立、添加、刪除、大小、層級等等。android

  2. 輸入中轉-IMS(InputManagerService)
    觸摸窗口產生觸摸事件,IMS對觸摸事件進行處理,最後尋找一個最合適窗口進行反饋處理。app

  3. 窗口動畫 ---WindowAnimator
    窗口間進行切換時,使用窗口動畫能夠實現更好的效果,窗口動畫主要由WindowAnimator管理。能夠在開發者模式菜單找到相應設置。ide

  4. Surface管理 ---SurfaceFlinger
    窗口不具有有繪製的功能,所以每一個窗口都須要有一塊Surface來供本身繪製。爲每一個窗口分配Surface是由WMS來完成的。
    Surface就像畫布,而後經過Canvas或OpenGL繪製。
    SurfaceFlinger的做用主要是merge Surface,它接受多個來源的Surface圖形顯示數據(全部Surface:全部Window的Surface,特殊狀況 有些Surface跟Window無關,如StrictMode),而後將他們合併(根據特定順序Z-order),而後發送到顯示設備。如最多見的界面是3層,頂部的statusbar,底部的導航欄,應用界面。

    oop

WMS簡介

WMS同以前總結過的AMS、PMS同樣(連接:AMS的啓動AMS之應用的第一次啓動過程PMS的啓動及應用的安裝過程),是系統服務,做爲Binder的服務端。 下表簡單對比列出下:字體

系統服務 binder服務端 binder客戶端 服務名
AMS ActivityManagerService(extends IActivityManager.Stub) ActivityManager activity(Context.ACTIVITY_SERVICE)
PMS PackageManagerService(extends IPackageManager.Stub) PackageManager package
WMS WindowManagerService(extends IWindowManager.Stub) WindowManager window(Context.WINDOW_SERVICE)

通常獲取方法:
獲取binder客戶端,與服務通訊,相似:
ActivityManager am = (ActivityManager) context.getSystemService("activity");
ActivityManager am = context.getSystemService(ActivityManager.class);
從ServiceManager獲取服務的Binder,相似:
IBinder binder = ServiceManager.getService(Context.ACTIVITY_SERVICE);
下面兩個也是用的ServiceManager.getService():
IActivityManager mgr = ActivityManager.getService();
PackageManagerService pm = (PackageManagerService) ServiceManager.getService("package");

動畫

WMS的啓動過程

以前總結了 AMS的啓動AMS之應用的第一次啓動過程PMS的啓動及應用的安裝過程。 這裏WMS的啓動相似,下面會簡單介紹下。ui

WMS是在system server啓動後的startOtherServices()中啓動。下面截取了其中關於WMS相關的代碼。this

//SystemServer.java
private void startOtherServices() {
    final Context context = mSystemContext;
    WindowManagerService wm = null;
   
    try {
        // WMS 依賴 sensor service
        ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
        //標記1:StartWindowManagerService
        //建立WMS實例
        wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
        //註冊WINDOW_SERVICE 服務到 ServiceManager。 
        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);

        //標記2:SetWindowManagerService
        //WMS設置到AMS/ATMS中。     
        mActivityManagerService.setWindowManager(wm);
        
        //標記3:WindowManagerServiceOnInitReady
        //WMS初始化完成。 
        wm.onInitReady();

        inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
        inputManager.start();

        mDisplayManagerService.windowManagerAndInputReady();
    }

    // Before things start rolling, be sure we have decided whether
    // we are in safe mode.
    final boolean safeMode = wm.detectSafeMode();
    try {
        //標記4:MakeDisplayReady
        //初始化顯示信息
        wm.displayReady();
    } 

    if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        if (!isWatch) {
            try {
                statusBar = new StatusBarManagerService(context, wm);
                ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
            } 
        }
    }

    try {
        //標記5:MakeWindowManagerServiceReady
        //通知WMS系統準備好了,初始化完成了。    
        wm.systemReady();
    } 

    final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
    DisplayMetrics metrics = new DisplayMetrics();
    WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    w.getDefaultDisplay().getMetrics(metrics);
    context.getResources().updateConfiguration(config, metrics);

    final WindowManagerService windowManagerF = wm;

    mActivityManagerService.systemReady(() -> {      
        try {
            startSystemUi(context, windowManagerF);
        } 
    }, BOOT_TIMINGS_TRACE_LOG);
}

startOtherServices()中,建立了WindowManagerService對象 並 註冊了服務Context.WINDOW_SERVICE。而後進行了各類初始化等操做。
注意上面的註釋,下面主要看下其中的5行代碼(標記1-標記5)。

標記1:wm = WindowManagerService.main(...)

//public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
//WindowManagerService.java
private static WindowManagerService sInstance;
static WindowManagerService getInstance() {
    return sInstance;
}

public static WindowManagerService main(final Context context, final InputManagerService im,
        final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm) {
    return main(context, im, showBootMsgs, onlyCore, policy, atm,
            SurfaceControl.Transaction::new);
}

@VisibleForTesting
public static WindowManagerService main(final Context context, final InputManagerService im,
        final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
    //android.display線程中執行
    DisplayThread.getHandler().runWithScissors(() ->
            sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                    atm, transactionFactory), 0);
    return sInstance;
}


private WindowManagerService(Context context, InputManagerService inputManager,
        boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
    ......
    //ActivityTaskManagerService
    mAtmService = atm;
    //context是mSystemContext   system server進程上下文
    mContext = context;
    mOnlyCore = onlyCore;
    mInTouchMode = context.getResources().getBoolean(
            com.android.internal.R.bool.config_defaultInTouchMode);
    mMaxUiWidth = context.getResources().getInteger(
            com.android.internal.R.integer.config_maxUiWidth);
    mLowRamTaskSnapshotsAndRecents = context.getResources().getBoolean(
            com.android.internal.R.bool.config_lowRamTaskSnapshotsAndRecents);
    //輸入法管理
    mInputManager = inputManager; // Must be before createDisplayContentLocked.
    mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
    mDisplayWindowSettings = new DisplayWindowSettings(this);
    mPolicy = policy;
    //管理窗口動畫
    mAnimator = new WindowAnimator(this);
    mRoot = new RootWindowContainer(this);
    mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
    mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
    mActivityManager = ActivityManager.getService();
    mActivityTaskManager = ActivityTaskManager.getService();
    mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
    mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
    mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
    ......
}

WindowManagerService.main()主要就是建立了WindowManagerService對象。
WindowManagerService的構造方法沒有完整附上了,沒什麼特別的,基本是初始化並保存 WMS中須要用到的各類對象等數據。上面列出了幾個常見的。
DisplayThread.getHandler().runWithScissors(),注意這裏是DisplayThread(繼承ServiceThread),是在android.display線程上執行。

題外話DisplayThread.getHandler().runWithScissors(() -> sInstance = new WindowManagerService(...),0);lambda表達式 ,這裏至關於:

DisplayThread.getHandler().runWithScissors(
    new Runnable() {
        @Override
        public void run() {
            sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                    atm, transactionFactory)
        }
    }, 0);

標記2:mActivityManagerService.setWindowManager(wm)

這個很簡單,wm被設置的到AMS和ATMS中。

//ActivityManagerService.java
public void setWindowManager(WindowManagerService wm) {
    synchronized (this) {
        mWindowManager = wm;
        mActivityTaskManager.setWindowManager(wm);
    }
}

標記3:wm.onInitReady()

//WindowManagerService.java
public void onInitReady() {
    //初始化PhoneWindowManager (PhoneWindowManager implements WindowManagerPolicy)
    initPolicy();

    // Add ourself to the Watchdog monitors.
    Watchdog.getInstance().addMonitor(this);
    //SurfaceControl.openTransaction();
    openSurfaceTransaction();
    try {
        //水印,這裏瞭解了下
        createWatermarkInTransaction();
    } finally {
        closeSurfaceTransaction("createWatermarkInTransaction");
    }

    showEmulatorDisplayOverlayIfNeeded();
}

private void initPolicy() {
    //android.ui線程上執行
    UiThread.getHandler().runWithScissors(new Runnable() {
        @Override
        public void run() {
            WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
            mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
        }
    }, 0);
}

void createWatermarkInTransaction() {
    ...
    File file = new File("/system/etc/setup.conf");
    ...
    try {
        ...
        if (line != null) {
            String[] toks = line.split("%");
            if (toks != null && toks.length > 0) {
                // TODO(multi-display): Show watermarks on secondary displays.
                final DisplayContent displayContent = getDefaultDisplayContentLocked();
                mWatermark = new Watermark(displayContent, displayContent.mRealDisplayMetrics,
                        toks);
            }
        }
    }
    ...
}

onInitReady()這裏幾個地方記錄下,我的以爲比較值得注意的:

  1. initPolicy()中,mPolicy即PhoneWindowManager對象,從開始處startOtherServices()中能夠看到。startOtherServices()建立了PhoneWindowManager,這裏完成了PhoneWindowManager的init()操做。

  2. initPolicy()中,是運行在UiThread,也是繼承的ServiceThread。執行mPolicy.init()。

  3. createWatermarkInTransaction():這個能夠看一下。這是在window manager的窗口上添加水印。這個功能幾乎沒有用過,嘗試了下,效果以下圖。

日後跟蹤,能夠看到:顯示的字符配置到/system/etc/setup.conf裏的,Watermark有個解析過程(相似解密),詳細的能夠本身看下Watermark的構造方法。以下圖中顯示的字符串「WMS」,我在setup.conf配置的是「A8B2A<%30」,%後面是字體大小。「A8B2A<」即「WMS」。

wms_watermark

標記4:wm.displayReady()

//WindowManagerService.java
public void displayReady() {
    synchronized (mGlobalLock) {
        if (mMaxUiWidth > 0) {
            mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
        }
        //全局設置僅適用於默認顯示。設置Display size、Display density、Display scaling mode。
        //getDefaultDisplayContentLocked()。
        final boolean changed = applyForcedPropertiesForDefaultDisplay();
        mAnimator.ready();
        mDisplayReady = true;
        if (changed) {
            reconfigureDisplayLocked(getDefaultDisplayContentLocked());
        }
        mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_TOUCHSCREEN);
    }

    try {
        //初始化配置完成,ATMS完成第一次Configuration更新
        mActivityTaskManager.updateConfiguration(null);
    } catch (RemoteException e) {
    }

    updateCircularDisplayMaskIfNeeded();
}

看下注釋。這裏主要是初始化顯示信息。初始化配置完成,ATMS完成第一次Configuration更新。

標記5:wm.systemReady()

//WindowManagerService.java
public void systemReady() {
    mSystemReady = true;
    mPolicy.systemReady();
    ...
}

系統初始化完成,通知WMS系統準備好了。這裏主要完成:mPolicy.systemReady()

在標記3 時,有在android.ui線程執行的mPolicy.init(),這裏有mPolicy.systemReady()。 mPolicy是PhoneWindowManager,關於這兩個方法這裏不關注,在後續相似事件傳遞時應該會再觸及。

相關文章
相關標籤/搜索