Android的知识体系搭建

WMS系列

一 概述

今日,咱们介绍 WindowManagerService(后续简称 WMS)的发动流程,WMS 是 Android 体系中,担任窗口显现的的服务。在 Android 中它也起着承上启下的作用。

如下图,便是《深化了解 Android》书本中的一张图。

WMS的启动流程

图中展现了,WMS 在 Android 体系的位置,它作为中间层,连接了上层的 View 结构和下层的 SurfaceFingler。了解了 WMS 的工作机制,咱们就完全打通了上层 VIew 到底层 Surface,甚至到显现器如何显现的逻辑。

接下来,咱们仍旧从 WMS 的发动开始,来看 WMS 是如何发动的。

二 从 SystemServer 开始

2.1 startOtherServices

[frameworks/base/services/java/com/android/server/SystemServer.java]
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
	WindowManagerService wm = null;
	// 这儿传入的 PhoneWindowManager 便是 WMS 中的 WindowManagerPolicy
	wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
			new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
	ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
			DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
	// 将 WMS 设置到 AMS 中
	mActivityManagerService.setWindowManager(wm);
	wm.onInitReady();
	...
	try {
		wm.displayReady();
	} catch (Throwable e) {
		reportWtf("making display ready", e);
	}
	...
	try {
		wm.systemReady();
	} catch (Throwable e) {
		reportWtf("making Window Manager Service ready", e);
	}
	...
	// 更新上下文中,关于显现窗口相关的属性
	final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
	DisplayMetrics metrics = new DisplayMetrics();
	context.getDisplay().getMetrics(metrics);
	context.getResources().updateConfiguration(config, metrics);
}

和 AMS 不同的是,WMS 的发动是在 SystemServer 的 startOtherServices 中,发动进程仍旧是咱们之前提过的结构、注册,仅仅少了 onStart 这个步骤。

并且,在 WMS 发动之后,还会连续调用一些其他的函数

  • onInitReady
  • displayReady
  • systemReady
  • updateConfiguration

接下来,咱们会依据 WMS 发动进程中调用的函数,以此检查它们详细的完结原理。

从 AMS 和 WMS 的发动,咱们能够看出来,它们都是隶属于 SystemServer 进程的,依据之前咱们对使用和 AMS 的了解,也经常看到它们交互的流程中,有 WMS 的身影,所以尽管说是使用和 AMS,WMS 的通信,实践上便是使用和 SystemServer 进程的通信。

2.2 main

[frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java]
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,
			new DisplayWindowSettingsProvider(), SurfaceControl.Transaction::new, Surface::new,
			SurfaceControl.Builder::new);
}
public static WindowManagerService main(final Context context, final InputManagerService im,
		final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
		ActivityTaskManagerService atm, DisplayWindowSettingsProvider
		displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
		Supplier<Surface> surfaceFactory,
		Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
	DisplayThread.getHandler().runWithScissors(() ->
			sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
					atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory,
					surfaceControlFactory), 0);
	return sInstance;
}

在 WMS 的 main 函数中首要做了两件事

  1. 创立了一个 WMS 目标
  2. 将这个 WMS 目标传递给了 DisplayThread

咱们首先看这个 WMS 目标的结构函数

三 WindowManagerService

3.1 WMS 的结构函数

private WindowManagerService(Context context, InputManagerService inputManager,
		boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
		ActivityTaskManagerService atm, DisplayWindowSettingsProvider
		displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
		Supplier<Surface> surfaceFactory,
		Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
	installLock(this, INDEX_WINDOW);
	// ActivityTaskManagerService
	mGlobalLock = atm.getGlobalLock();
	mAtmService = atm;
	mContext = context;
	mIsPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
	mAllowBootMessages = showBootMsgs;
	...
	// 输入法办理
	mInputManager = inputManager; // Must be before createDisplayContentLocked.
	// 显现办理
	mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
	// Surface 图画相关
	mSurfaceControlFactory = surfaceControlFactory;
	mTransactionFactory = transactionFactory;
	mSurfaceFactory = surfaceFactory;
	mTransaction = mTransactionFactory.get();
	mPolicy = policy;
	// 窗口动画
	mAnimator = new WindowAnimator(this);
	// 根窗口容器
	mRoot = new RootWindowContainer(this);
	final ContentResolver resolver = context.getContentResolver();
	mUseBLAST = Settings.Global.getInt(resolver,
		Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_VR, 1) == 1;
	mSyncEngine = new BLASTSyncEngine(this);
	mWindowPlacerLocked = new WindowSurfacePlacer(this);
	mTaskSnapshotController = new TaskSnapshotController(this);
	mWindowTracing = WindowTracing.createDefaultAndStartLooper(this,
			Choreographer.getInstance());
	LocalServices.addService(WindowManagerPolicy.class, mPolicy);
	mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
	mKeyguardDisableHandler = KeyguardDisableHandler.create(mContext, mPolicy, mH);
	mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
	mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
	if (mPowerManagerInternal != null) {
		mPowerManagerInternal.registerLowPowerModeObserver(
				new PowerManagerInternal.LowPowerModeListener() {
			@Override
			public int getServiceType() {
				return ServiceType.ANIMATION;
			}
			@Override
			public void onLowPowerModeChanged(PowerSaveState result) {
				synchronized (mGlobalLock) {
					final boolean enabled = result.batterySaverEnabled;
					if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
						mAnimationsDisabled = enabled;
						dispatchNewAnimatorScaleLocked(null);
					}
				}
			}
		});
		mAnimationsDisabled = mPowerManagerInternal
				.getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
	}
	mScreenFrozenLock = mPowerManager.newWakeLock(
			PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
	mScreenFrozenLock.setReferenceCounted(false);
	mDisplayNotificationController = new DisplayWindowListenerController(this);
	// AMS 相关
	mActivityManager = ActivityManager.getService();
	mActivityTaskManager = ActivityTaskManager.getService();
	mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
	mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
	... 
}

WMS 的结构函数的代码非常长,其中有包含各种服务,咱们这儿只关注和咱们使用 Activity 相关的,还有和显现相关的窗口容器 RootWindowContainer,还有和刷新相关的 Surface

3.2 runWithScissors

别的,在 main 函数中,还调用了一个 runWithScissors,这个函数是 Handler 中界说的函数,这儿咱们简单看一下。

public final boolean runWithScissors(@NonNull Runnable r, long timeout) {
	if (r == null) {
		throw new IllegalArgumentException("runnable must not be null");
	}
	if (timeout < 0) {
		throw new IllegalArgumentException("timeout must be non-negative");
	}
	if (Looper.myLooper() == mLooper) {
		r.run();
		return true;
	}
	BlockingRunnable br = new BlockingRunnable(r);
	return br.postAndWait(this, timeout);
}

runWithScissors 是 Handler 中的函数,用一句话概括便是,如果发送音讯的线程与 Handler 处理的线程相同,就直接调用。如果不同,就堵塞调用

3.3 onInitReady

public void onInitReady() {
	initPolicy();
	// Add ourself to the Watchdog monitors.
	Watchdog.getInstance().addMonitor(this);
	createWatermark();
	showEmulatorDisplayOverlayIfNeeded();
}

3.4 initPolicy

private void initPolicy() {
	UiThread.getHandler().runWithScissors(new Runnable() {
		@Override
		public void run() {
			WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
			// mPolicy 其实便是 PhoneWindowManager【5.1】
			mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
		}
	}, 0);
}

mPolicy 其实是 PhoneWindowManager,runWithScissors 前面介绍过了,如果是当时线程,就直接运转,如果不是当时线程,就堵塞运转。

所以这儿是在 android.ui 线程中,运转 mPolicy 的初始化逻辑

3.5 createWatermark

void createWatermark() {
	if (mWatermark != null) {
		return;
	}
	File file = new File("/system/etc/setup.conf");
	FileInputStream in = null;
	DataInputStream ind = null;
	try {
		in = new FileInputStream(file);
		ind = new DataInputStream(in);
		String line = ind.readLine();
		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, mTransaction);
				mTransaction.apply();
			}
		}
	} ...
}

createWatermark 创立体系水印(只能显现文字)。

3.6 displayReady

[frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java]
public void displayReady() {
	synchronized (mGlobalLock) {
		if (mMaxUiWidth > 0) {
			mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
		}
		applyForcedPropertiesForDefaultDisplay();
		mAnimator.ready();
		mDisplayReady = true;
		// createWatermark重新配置所有显现器巨细
		mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked);
		// 是否触屏
		mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_TOUCHSCREEN);
		mIsFakeTouchDevice = mContext.getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_FAKETOUCH);
	}
	try {
		// ATMS
		mActivityTaskManager.updateConfiguration(null);
	} catch (RemoteException e) {
	}
}

displayReady 便是初始化显现器巨细。

3.7 systemReady

[frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java]
public void systemReady() {
	mSystemReady = true;
	// 调用 PhoneWindowManager 的 systemReady
	mPolicy.systemReady();
	// 调用 DisplayPolicy 的 systemReady
	mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
	// 调用 TaskSnapshotController 的 systemReady
	mTaskSnapshotController.systemReady();
	mHasWideColorGamutSupport = queryWideColorGamutSupport();
	mHasHdrSupport = queryHdrSupport();
	// 加载体系设置
	UiThread.getHandler().post(mSettingsObserver::loadSettings);
	// VR
	IVrManager vrManager = IVrManager.Stub.asInterface(
			ServiceManager.getService(Context.VR_SERVICE));
	if (vrManager != null) {
		try {
			final boolean vrModeEnabled = vrManager.getVrModeState();
			synchronized (mGlobalLock) {
				vrManager.registerListener(mVrStateCallbacks);
				if (vrModeEnabled) {
					mVrModeEnabled = vrModeEnabled;
					mVrStateCallbacks.onVrStateChanged(vrModeEnabled);
				}
			}
		} catch (RemoteException e) {
			// Ignore, we cannot do anything if we failed to register VR mode listener
		}
	}
}

3.8 computeNewConfiguration

public Configuration computeNewConfiguration(int displayId) {
	synchronized (mGlobalLock) {
		return computeNewConfigurationLocked(displayId);
	}
}

3.9 computeNewConfigurationLocked

private Configuration computeNewConfigurationLocked(int displayId) {
	if (!mDisplayReady) {
		return null;
	}
	final Configuration config = new Configuration();
	final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
	displayContent.computeScreenConfiguration(config);
	return config;
}

displayId 表示的是显现设备的 id,这两段代码,便是经过 mRoot(RootWindowContainer)获取显现指定设备的 DisplayContent。说人话便是,经过显现器的 id,获取显现器对应的实例类 DisplayContent

四 DisplayThread

[frameworks/base/services/core/java/com/android/server/DisplayThread.java]
public final class DisplayThread extends ServiceThread {
    private static DisplayThread sInstance;
    private static Handler sHandler;
	private DisplayThread() {
		// DisplayThread 运转重要的东西,但 AnimationThread 更重要。因此,优先级设置为 THREAD_PRIORITY_DISPLAY + 1
		// THREAD_PRIORITY_DISPLAY 的值为 -4,
		super("android.display", Process.THREAD_PRIORITY_DISPLAY + 1, false /*allowIo*/);
	}

DisplayThread 便是 Android 中的 android.display 线程,它的优先级为 THREAD_PRIORITY_DISPLAY + 1,THREAD_PRIORITY_DISPLAY 值为 -4,所以 android.display 线程的优先级是 -3。

再回到 【2.2】中,WMS 的 main 函数是经过 android.display 线程完结的,并且在 android.display 线程中,对 android.ui 线程进行了初始化。

五 UIThread

public final class UiThread extends ServiceThread {
    private static final long SLOW_DISPATCH_THRESHOLD_MS = 100;
    private static final long SLOW_DELIVERY_THRESHOLD_MS = 200;
    private static UiThread sInstance;
    private static Handler sHandler;
    private UiThread() {
        super("android.ui", Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
    }
    @Override
    public void run() {
        // Make sure UiThread is in the fg stune boost group
        Process.setThreadGroup(Process.myTid(), Process.THREAD_GROUP_TOP_APP);
        super.run();
    }

UiThread 和 DisplayThread 一样,也是继承自 ServiceThread,它的线程名是 android.ui,优先级是 THREAD_PRIORITY_FOREGROUND,值为-2,所以 android.ui 线程的优先级是 -2。

六 PhoneWindowManager

PhoneWindowManager 是 WindowManagerPolicy 的完结类,它界说了手机窗口、处理输入事情以及与体系 UI 交互的策略和行为。

PhoneWindowManager 中的函数有许多,这儿咱们罗列一个,其中的按键分发的函数 interceptKeyBeforeQueueing。

6.1 interceptKeyBeforeQueueing

[frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java]
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
	final int keyCode = event.getKeyCode();
	final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
	boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
			|| event.isWakeKey();
	if (!mSystemBooted) {
		// 体系发动前,只监听电源按键
		if (down && (keyCode == KeyEvent.KEYCODE_POWER
				|| keyCode == KeyEvent.KEYCODE_TV_POWER)) {
			wakeUpFromPowerKey(event.getDownTime());
		} else if (down && (isWakeKey || keyCode == KeyEvent.KEYCODE_WAKEUP)
				&& isWakeKeyWhenScreenOff(keyCode)) {
			wakeUpFromWakeKey(event);
		}
		// 阻拦掉电源键
		return 0;
	}
	// interceptKeyBeforeQueueing 首要便是对手机按键的事情阻拦,这儿咱们简单罗列几个
	// 回来键,音量键等等。
	switch (keyCode) {
		case KeyEvent.KEYCODE_BACK: {
			if (down) {
				mBackKeyHandled = false;
			} else {
				if (!hasLongPressOnBackBehavior()) {
					mBackKeyHandled |= backKeyPress();
				}
				// Don't pass back press to app if we've already handled it via long press
				if (mBackKeyHandled) {
					result &= ~ACTION_PASS_TO_USER;
				}
			}
			break;
		}
		case KeyEvent.KEYCODE_VOLUME_DOWN:
		case KeyEvent.KEYCODE_VOLUME_UP:

回来值是一个整型,如果是 0 就表示被阻拦,一开始的电源按键咱们就看到了,在体系没有发动前,电源按键只能用于体系发动,但是体系发动后,电源按键就能够用于其他的作用了,例如语音助手。

PhoneWindowManager 这个类首要的作用有:

  1. 按键的分发
  2. 窗口的办理

这儿咱们就不扩展了,后边遇到实践的场景再来阐明。

七 总结

WMS 的发动流程比较简单,首要便是发动了两个线程 "android.display""android.ui",下一篇,咱们再来看看 WMS 的如何进行窗口办理的。