簡介
Window簡介
Android中,Window是一個重要部分,用戶看到的界面、觸摸顯示界面進行一系列操作都涉及到Window。但實際上,Window本身並不具備繪制功能。
該篇簡單介紹下Window的一點內容,同時總結下WMS的啟動過程。在下篇會逐步介紹一個Activity是如何創建出窗口 並 添加到WMS中的。
該篇基於Andorid10的代碼。
窗口涉及到一下幾個功能:
-
窗口管理-WMS
WMS管理窗口的創建、添加、刪除、大小、層級等等。 -
輸入中轉-IMS(InputManagerService)
觸摸窗口產生觸摸事件,IMS對觸摸事件進行處理,最后尋找一個最合適窗口進行反饋處理。 -
窗口動畫 ---WindowAnimator
窗口間進行切換時,使用窗口動畫可以實現更好的效果,窗口動畫主要由WindowAnimator管理。可以在開發者模式菜單找到相應設置。 -
Surface管理 ---SurfaceFlinger
窗口不具備有繪制的功能,因此每個窗口都需要有一塊Surface來供自己繪制。為每個窗口分配Surface是由WMS來完成的。
Surface就像畫布,然后通過Canvas或OpenGL繪制。
SurfaceFlinger的作用主要是merge Surface,它接受多個來源的Surface圖形顯示數據(所有Surface:所有Window的Surface,特殊情況 有些Surface跟Window無關,如StrictMode),然后將他們合並(根據特定順序Z-order),然后發送到顯示設備。如最常見的界面是3層,頂部的statusbar,底部的導航欄,應用界面。
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的啟動類似,下面會簡單介紹下。
WMS是在system server啟動后的startOtherServices()中啟動。下面截取了其中關於WMS相關的代碼。
//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()這里幾個地方記錄下,個人覺得比較值得注意的:
-
initPolicy()中,mPolicy即PhoneWindowManager對象,從開始處startOtherServices()中可以看到。startOtherServices()創建了PhoneWindowManager,這里完成了PhoneWindowManager的init()操作。
-
initPolicy()中,是運行在UiThread,也是繼承的ServiceThread。執行mPolicy.init()。
-
createWatermarkInTransaction():這個可以看一下。這是在window manager的窗口上添加水印。這個功能幾乎沒有用過,嘗試了下,效果如下圖。
往后跟蹤,可以看到:顯示的字符配置到/system/etc/setup.conf里的,Watermark有個解析過程(類似解密),詳細的可以自己看下Watermark的構造方法。如下圖中顯示的字符串“WMS”,我在setup.conf配置的是“A8B2A<%30”,%后面是字體大小。“A8B2A<”即“WMS”。
標記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,關於這兩個方法這里不關注,在后續類似事件傳遞時應該會再觸及。