1、WMS
- WMS主要功能
- 窗口管理:WMS負責整個系統窗口的啓動、添加、刪除工作,系統中每個程序的顯示都由WMS管理
- 窗口動畫管理:WMS負責窗口添加或切換時動畫效果的執行
- 窗口輸入管理:WMS負責對窗口的觸摸事件進行反饋和處理
- Surface管理:每個Window都有對應的Surface負責窗口的顯示,而WMS負責所有Surface的管理調度
- WMS屬性介紹
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
final WindowManagerPolicy mPolicy;
final ArraySet<Session> mSessions = new ArraySet<>();
final WindowHashMap mWindowMap = new WindowHashMap();
final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>();
final H mH = new H();
final WindowAnimator mAnimator;
final InputManagerService mInputManager;
final IActivityManager mActivityManager;
}
- mPolicy:WindowManagerPolicy的實例,WindowManagerPolicy是窗口管理策略的接口類,它的具體實現類爲PhoneWindowManager
- mSessions:ArraySet對象,保存元素類型爲Session,主要用於應用程序與WMS間的進程通信,每個應用程序對應一個Session,WMS內部保存這些Session,用來記錄所有像WMS提出窗口服務的客戶端
- mWindowMap:WindowHashMap對象,它內部以IBinder爲Key,WindowState爲Value,所以mWindowMap中保存着WMS中所有窗口的集合,而WindowState中保存着每個窗口的所有信息;
- mFinishedStarting:ArrayList對象,內部保存着已經啓動窗口的WindowToken,WindowToken爲窗口令牌,當程序像WMS申請創建Window時需要出具Token,程序中的每個Activity對應一個AppWindowToken(WindowToken的子類),WindowToken會將統一Actiivty的窗口組合在一起進行管理;
- mAnimator:WindowAnimator的對象,用於窗口的動畫管理
- mH:H的實例,負責將任務添加到主線程中
- mInputManager:InputManagerService對象負責輸入系統的管理,對窗口的觸摸事件反饋和處理
- mActivityManager:內部保存AMS的對象
2、創建過程
由Android進程的啓動過程知道,程序會同過JNI調用ZygiteInit.main()進入Java層,在main()方法中完成啓動工作,其中重要的一步就是調用startSystemServer()啓動系統服務,WMS就是其中一個系統服務,startSystemServer()使用反射最終調用SystemServer.main()方法(本文源碼參照Android P),
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
mSystemServiceManager = new SystemServiceManager(mSystemContext);
startBootstrapServices();
startCoreServices();
startOtherServices();
}
在main方法中直接調用SystemService的run(),在run中首先創建SystemServiceManager對象,然後利用SystemServiceManager分別啓動引導服務、核心服務、其他服務,WMS的啓動就在startOtherServices()過程中;
- startOtherServices()
inputManager = new InputManagerService(context);
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm, false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
false, DUMP_FLAG_PRIORITY_CRITICAL);
在startOtherServices()中首先創建InputManagerService對象,然後調用WindowManagerService.main()創建WMS對象,此時最後一個參數就是前面講的窗口策略類PhoneWindowManager,最後調用ServiceManager.addService()將WMS和InputManagerService保存在ServiceManager中;
- WindowManagerService.main()
public class WindowManagerService extends IWindowManager.Stub{
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
WindowManagerPolicy policy) {
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
onlyCore, policy), 0);
return sInstance;
}
}
從上面代碼中看出WindowManagerService是IWindowManager接口的代理類,在main()方法中調用DisplayThread.getHandler().runWithScissors()方法執行WindowManagerService的創建;
DisplayThread.getHandler().runWithScissors()其實就是發送一個事件消息,DisplayThread繼承ServiceThread,而ServiceThread繼承與HandlerThread,熟悉HandlerThread的同學都知道它是Android內部封裝好的工具類,DisplayThread.getHandler()就是利用HandlerThread內部創建的Looper而創建的Handler,所以本質上執行的是Handler.runWithScissors()
- Handler.runWithScissors()
public final boolean runWithScissors(final Runnable r, long timeout) {
if (Looper.myLooper() == mLooper) {
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
runWithScissors()中接收到事件runnable後,先判斷當前線程是否爲創建Looper的線程,如果是則直接在當前線程執行,否則創建BlockingRunnable封裝事件併發送到創建線程的隊列中,由上面的啓動知道此時程序執行在systemserver線程,所以此處會創建BlockingRunnable對象
- BlockingRunnable
private static final class BlockingRunnable implements Runnable {
883 private final Runnable mTask;
884 private boolean mDone;
886 public BlockingRunnable(Runnable task) {
887 mTask = task;
888 }
889
890 @Override
891 public void run() {
892 try {
893 mTask.run();
894 } finally {
895 synchronized (this) {
896 mDone = true;
897 notifyAll();
898 }
899 }
900 }
901
902 public boolean postAndWait(Handler handler, long timeout) {
903 if (!handler.post(this)) {
904 return false;
905 }
906
907 synchronized (this) {
908 if (timeout > 0) {
909 final long expirationTime = SystemClock.uptimeMillis() + timeout;
910 while (!mDone) {
911 long delay = expirationTime - SystemClock.uptimeMillis();
912 if (delay <= 0) {
913 return false; // timeout
914 }
915 try {
916 wait(delay);
917 } catch (InterruptedException ex) {
918 }
919 }
920 } else {
921 while (!mDone) {
922 try {
923 wait();
924 } catch (InterruptedException ex) {
925 }
926 }
927 }
928 }
929 return true;
930 }
931 }
BlockingRunnable是Handler的內部類,是專門用來處理線程安全的類,在postAndWait中首先使用Handler發送事件到當前隊列,然後調用wait()方法使當前線程進入等待,然後在run()中執行傳入的事件,在事件執行結束後調用notifyAll()方法喚醒線程,結合這裏的啓動過程總結一下:
- 在WindowManagerService.main()中即在system_service線程中,使用DisplayThread初始化的Handler發送事件,執行WMS的創建
- 在DisplayThread初始化的Handler中,首先會調用wait()使system_service線程執行等待,然後發送post發送事件到當前隊列,即執行display線程
- 在display線程執行創建後,調用notify喚醒system_service線程繼續執行
- WindowManagerService
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
WindowManagerPolicy policy) {
mAnimator = new WindowAnimator(this);
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
mActivityManager = ActivityManager.getService();
}
在搞清楚上面的線程和執行的順序後,下面進入到WMS的創建過程中,在WindowManagerService的構造函數中完成了WindowAnimator、mDisplayManager、mActivityManager的初始化,到此WMS啓動已經完成
3、添加過程
對與Window添加過程的前半部分見Android進階知識樹—— 理解WindowManager,本文只分析WMS執行的部分,上一文章中知道添加過程最終調用到WMS中的addWindow(),下面分步驟閱讀源碼;
- 對添加窗口的檢查
public int addWindow(){
int res = mPolicy.checkAddPermission(attrs, appOp);//1
final DisplayContent displayContent = getDisplayContentOrCreate(displayId);//2
if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
parentWindow = windowForClientLocked(null, attrs.token, false);
if (parentWindow == null) {
return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
}
if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
&& parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
}
}
}
在addWindow()中具體執行如下:
- 首先調用傳入的窗口策略對窗口進行權限檢查,具體執行在PhoneWindowManager中,
- 根據displayId獲取要添加到對應的DisplayContent
- 根據添加的Type確定添加窗口的類型
- 調用windowForClientLocked根據窗口令牌token查找窗口是否已添加過
- 創建WindowToken
WindowToken token = displayContent.getWindowToken(
1191 hasParent ? parentWindow.mAttrs.token : attrs.token);//1
final int rootType = hasParent ? parentWindow.mAttrs.type : type;
token = new WindowToken(this, binder, type, false, displayContent,
1247 session.mCanAddInternalSystemWindow, isRoundedCornerOverlay);//2
atoken = token.asAppWindowToken();
總結:
- 調用displayContent.getWindowToken()獲取WindowToken,然後判斷是否有父窗口和父窗口的Type類型
- 創建窗口令牌WindowToken
- 將WindowToken轉換爲程序窗口令牌AppWindowToken
- 窗口添加和數據保存
final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);// 1
mPolicy.adjustWindowParamsLw(win, win.mAttrs, hasStatusBarServicePermission);//2
res = mPolicy.prepareAddWindowLw(win, attrs);//3
mWindowMap.put(client.asBinder(), win);//4
win.mToken.addWindow(win);//5
addWindow()最後部分執行以下步驟:
- 創建WidowState保存Window的全部信息
- 調用mPolicy.adjustWindowParamsLw()根據窗口Type修改Window的LayoutParam
- 調用prepareAddWindowLw()執行Window的添加
- 以Binder爲Key將WindowState對象保存在mWindowMap中
- 將WindowState保存在窗口的Token中
4、刪除過程
關於Window的刪除過程見Android進階知識樹—— 理解WindowManager,程序最終調用WMS的removeWindow(),在removeWindow()中首先獲取到保存Window所有信息的WidowState對象,然後調用WindowState.removeIfPossible()方法,removeIfPossible中直接調用重載的方法,最終調用 removeImmediately();
void removeWindow(Session session, IWindow client) {
synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return;
}
win.removeIfPos();
}
}
- removeImmediately()
@Override
void removeImmediately() {
super.removeImmediately();
mPolicy.removeWindowLw(this);
1921 disposeInputChannel();
1923 mWinAnimator.destroyDeferredSurfaceLocked();
1924 mWinAnimator.destroySurfaceLocked();
1925 mSession.windowRemovedLocked();
1927 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
1933 mService.postWindowRemoveCleanupLocked(this);
}
removeImmediately中主要做一些清理工作,移除當前Widow、通知當前窗口動畫、移除mSession等;
到此這對WMS的介紹和窗口的添加就介紹完畢了,希望有所幫助,後面會繼續整理相關內容!