一、WMS 的作用
WMS 在 Android 系统的地位,它作为中间层,连接了上层的 View 框架和下层的 SurfaceFingler。
- WMS 主要职责
- 窗口管理:负责启动、添加、删除窗口,管理窗口大小、层级,核心成员有:WindowContainer、RootWindowContainer、DisplayContent、TaskStack、Task、AppWindowToken、WindowState;
- 窗口动画:由其子系统 WindowAnimator 管理;
- 输入系统中转站:通过对窗口的触摸从而产生触摸事件,由 InputMethodService(IMS)对触摸事件进行处理,它会寻找一个最合适的窗口处理触摸反馈信息;
- Surface 管理:为每个窗口分配一块 Surface,用于绘制要显示的内容。
- WMS重要的类
- WMS继承于IWindowManager.Stub,作为Binder服务端
- 成员变量mSessions保存所有的Session对象,Session继承于IWindowSession.Stub,作为Binder服务端.Session的创建在 WindowState 的attach方法中:mSession.windowAddedLocked
- 成员变量mPolicy,实例是PhoneWindowManager,用于实现各种窗口相关的策略
- 成员变量mWindowMap,保存所有的WindowState对象;以IBinder为key, 是IWindow的Bp端;
- 每个窗口都对应一个WindowState对象, 该对象的成员变量mClient用于跟应用端交互,成员变量mToken用于跟AMS交互,WindowState的attach方法与SurfaceFlinger通信。
- WindowManager与WindowManagerService通过Session进行通信,具体的实现由WMS处理。
- WindowManager实现类是WindowManagerImpl ;
- WindowManagerImpl 中成员变量 mParentWindow (Window),mGlobal (WindowManagerGlobal)
AMS,WMS之间数据是对应的,通过token值可以在AMS,WMS,应用程序之后来唯一确定一组Window,token是关联着一组窗口的,可能有多个WindowState的token值是相同的.
二、WMS 的启动流程
wms 是运行在systemsever 系统进程的,在启动system 进程的时候,去初始化了 WMS
/frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("startOtherServices");
WindowManagerService wm = null;
t.traceBegin("StartInputManagerService");
// wms与 InputManagerService 息息相关,创建 InputManagerService 对象
inputManager = new InputManagerService(context);
t.traceEnd();
t.traceBegin("StartWindowManagerService");
// WMS needs sensor service ready
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
// 1. 创建 WindowManagerService 对象
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
// 将 WindowManagerService 和 InputManagerService 添加到服务中
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. wms 与 ams 关联
mActivityManagerService.setWindowManager(wm);
// 3. 初始化完成
wm.onInitReady();
// 4. InputManagerService 设置回调,并启动 InputManagerService
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
// 5. 调用 displayReady 方法
wm.displayReady();
// 6. 系统准备完毕,调用 systemReady
wm.systemReady();
final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
1. 创建 WindowManagerService 对象
WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm) {
// policy 是值是 new PhoneWindowManager(),继承了 WindowManagerPolicy
return main(context, im, showBootMsgs, onlyCore, policy, atm,
// 一个Supplier可以通过lambda表达式、方法引用或默认构造函数来实例化。
// Supplier在Java 8中被引入,属于java.util.function包
// transactionFactory 为 SurfaceControl.Transaction::new,创建 Transaction 对象
// 通过get 可以获取到对象 Transaction
new DisplayWindowSettingsProvider(), SurfaceControl.Transaction::new, Surface::new,
SurfaceControl.Builder::new);
}
==========
@VisibleForTesting
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) {
// 在 android.display 实例化 wms,所以wms 跑在android.display线程中
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory,
surfaceControlFactory), 0);
return sInstance;
}
PhoneWindowManager,主要是负责窗口管理的各种策略。在 android.display 实例化 wms,所以wms 跑在android.display线程中
/frameworks/base/services/core/java/com/android/server/DisplayThread.java
// ServiceThread 继承了 HandlerThread
public final class DisplayThread extends ServiceThread {
private static DisplayThread sInstance;
private static Handler sHandler;
private DisplayThread() {
// DisplayThread runs important stuff, but these are not as important as things running in
// AnimationThread. Thus, set the priority to one lower.
// 线程名字为 "android.display",优先级为 -3
super("android.display", Process.THREAD_PRIORITY_DISPLAY + 1, false /*allowIo*/);
}
private static void ensureThreadLocked() {
if (sInstance == null) {
sInstance = new DisplayThread();
sInstance.start();
sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
// 创建handler,looper 为 thread "android.display" 的looper
sHandler = new Handler(sInstance.getLooper());
}
}
// 获取到handler
public static Handler getHandler() {
synchronized (DisplayThread.class) {
ensureThreadLocked();
return sHandler;
}
}
handler 执行 runWithScissors 方法
/frameworks/base/core/java/android/os/Handler.java
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");
}
// 当前looper 不相等
if (Looper.myLooper() == mLooper) {
r.run();
return true;
}
// 将其pos 到 BlockingRunnable
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
===========
public BlockingRunnable(Runnable task) {
mTask = task;
}
@Override
public void run() {
try {
mTask.run();
} finally {
synchronized (this) {
mDone = true;
// 执行完则唤醒系统主线程
notifyAll();
}
}
}
public boolean postAndWait(Handler handler, long timeout) {
// 将其增加到消息队列中
if (!handler.post(this)) {
return false;
}
synchronized (this) {
if (timeout > 0) {
。。
} else {
while (!mDone) {
try {
// 阻塞systemserver 主线程
wait();
} catch (InterruptedException ex) {
}
}
}
}
return true;
}
}
DisplayThread 给系统使用的共享单例前台线程类,线程名字为 android.display,专门提供给WindowManager, DisplayManager, and InputManager来执行快速响应的实时操作。
执行构造函数
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);
// 锁机制与 atm 一致
mGlobalLock = atm.getGlobalLock();
// 缓存 AtmS
mAtmService = atm;
mContext = context;
。。。
// 是否允许在低电量开启动画
mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
// 缓存 inputManager
mInputManager = inputManager; // Must be before createDisplayContentLocked.
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mSurfaceControlFactory = surfaceControlFactory;
mTransactionFactory = transactionFactory;
mSurfaceFactory = surfaceFactory;
// 获取 Transaction 对象
mTransaction = mTransactionFactory.get();
// policy 为:PhoneWindowManager
mPolicy = policy;
// 创建 WindowAnimator 对象
mAnimator = new WindowAnimator(this);
// 创建 RootWindowContainer 对象
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);
// mH 为 final H mH = new H();
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);
mActivityManager = ActivityManager.getService();
mActivityTaskManager = ActivityTaskManager.getService();
mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
AppOpsManager.OnOpChangedInternalListener opListener =
new AppOpsManager.OnOpChangedInternalListener() {
@Override public void onOpChanged(int op, String packageName) {
updateAppOpsState();
}
};
mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener);
mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
mPmInternal = LocalServices.getService(PackageManagerInternal.class);
mTestUtilityService = LocalServices.getService(TestUtilityService.class);
final IntentFilter suspendPackagesFilter = new IntentFilter();
suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
context.registerReceiverAsUser(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String[] affectedPackages =
intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
final boolean suspended =
Intent.ACTION_PACKAGES_SUSPENDED.equals(intent.getAction());
updateHiddenWhileSuspendedState(new ArraySet<>(Arrays.asList(affectedPackages)),
suspended);
}
}, UserHandle.ALL, suspendPackagesFilter, null, null);
// Get persisted window scale setting
mWindowAnimationScaleSetting = Settings.Global.getFloat(resolver,
Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
mTransitionAnimationScaleSetting = Settings.Global.getFloat(resolver,
Settings.Global.TRANSITION_ANIMATION_SCALE,
context.getResources().getFloat(
R.dimen.config_appTransitionAnimationDurationScaleDefault));
setAnimatorDurationScale(Settings.Global.getFloat(resolver,
Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
mForceDesktopModeOnExternalDisplays = Settings.Global.getInt(resolver,
DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0;
final String displaySettingsPath = Settings.Global.getString(resolver,
DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH);
mDisplayWindowSettingsProvider = displayWindowSettingsProvider;
if (displaySettingsPath != null) {
mDisplayWindowSettingsProvider.setBaseSettingsFilePath(displaySettingsPath);
}
mDisplayWindowSettings = new DisplayWindowSettings(this, mDisplayWindowSettingsProvider);
IntentFilter filter = new IntentFilter();
// Track changes to DevicePolicyManager state so we can enable/disable keyguard.
filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
mLatencyTracker = LatencyTracker.getInstance(context);
mSettingsObserver = new SettingsObserver();
mHoldingScreenWakeLock = mPowerManager.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
mHoldingScreenWakeLock.setReferenceCounted(false);
mSurfaceAnimationRunner = new SurfaceAnimationRunner(mTransactionFactory,
mPowerManagerInternal);
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
mTaskPositioningController = new TaskPositioningController(
this, mInputManager, mActivityTaskManager, mH.getLooper());
mDragDropController = new DragDropController(this, mH.getLooper());
mHighRefreshRateDenylist = HighRefreshRateDenylist.create(context.getResources());
mConstants = new WindowManagerConstants(this, DeviceConfigInterface.REAL);
mConstants.start(new HandlerExecutor(mH));
LocalServices.addService(WindowManagerInternal.class, new LocalService());
mEmbeddedWindowController = new EmbeddedWindowController(mAtmService);
mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources(
mContext.getResources());
mDisplayHashController = new DisplayHashController(mContext);
setGlobalShadowSettings();
// anr 控制类,无响应,无焦点等
mAnrController = new AnrController(this);
mStartingSurfaceController = new StartingSurfaceController(this);
mBlurController = new BlurController(mContext, mPowerManager);
}
mH 为 final H mH = new H()
成员变量,因此WMS后面的消息也是运行在 android.display
线程中的。
2. wms 与 ams 关联
mActivityManagerService.setWindowManager(wm);
/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
973 public void setWindowManager(WindowManagerService wm) {
974 synchronized (mGlobalLock) {
975 mWindowManager = wm;
// 缓存 RootWindowContainer
976 mRootWindowContainer = wm.mRoot;
977 mTempConfig.setToDefaults();
978 mTempConfig.setLocales(LocaleList.getDefault());
979 mConfigurationSeq = mTempConfig.seq = 1;
980 mRootWindowContainer.onConfigurationChanged(mTempConfig);
981 mLockTaskController.setWindowManager(wm);
982 mTaskSupervisor.setWindowManager(wm);
// RootWindowContainer 设置 WindowManager
983 mRootWindowContainer.setWindowManager(wm);
984 }
985 }
3. 初始化完成 onInitReady
wm.onInitReady();
/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public void onInitReady() {
initPolicy();
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
createWatermark();
showEmulatorDisplayOverlayIfNeeded();
}
=========
private void initPolicy() {
// 在ui 线程执行下列函数,"android.ui"
UiThread.getHandler().runWithScissors(new Runnable() {
@Override
public void run() {
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
// 初始化 PhoneWindowManager
mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
}
}, 0);
}
// 初始化 PhoneWindowManager
/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs) {
mContext = context;
mWindowManager = windowManager;
mWindowManagerFuncs = windowManagerFuncs;
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mDisplayManager = mContext.getSystemService(DisplayManager.class);
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mPackageManager = mContext.getPackageManager();
mHasFeatureWatch = mPackageManager.hasSystemFeature(FEATURE_WATCH);
mHasFeatureLeanback = mPackageManager.hasSystemFeature(FEATURE_LEANBACK);
mHasFeatureAuto = mPackageManager.hasSystemFeature(FEATURE_AUTOMOTIVE);
mHasFeatureHdmiCec = mPackageManager.hasSystemFeature(FEATURE_HDMI_CEC);
mAccessibilityShortcutController =
new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
mLogger = new MetricsLogger();
mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
.createSleepTokenAcquirer("ScreenOff");
Resources res = mContext.getResources();
mWakeOnDpadKeyPress =
res.getBoolean(com.android.internal.R.bool.config_wakeOnDpadKeyPress);
mWakeOnAssistKeyPress =
res.getBoolean(com.android.internal.R.bool.config_wakeOnAssistKeyPress);
mWakeOnBackKeyPress =
res.getBoolean(com.android.internal.R.bool.config_wakeOnBackKeyPress);
// Init display burn-in protection
boolean burnInProtectionEnabled = context.getResources().getBoolean(
com.android.internal.R.bool.config_enableBurnInProtection);
// Allow a system property to override this. Used by developer settings.
boolean burnInProtectionDevMode =
SystemProperties.getBoolean("persist.debug.force_burn_in", false);
if (burnInProtectionEnabled || burnInProtectionDevMode) {
final int minHorizontal;
final int maxHorizontal;
final int minVertical;
final int maxVertical;
final int maxRadius;
if (burnInProtectionDevMode) {
minHorizontal = -8;
maxHorizontal = 8;
minVertical = -8;
maxVertical = -4;
maxRadius = (isRoundWindow()) ? 6 : -1;
} else {
....
// handler是跑在ui 线程
mHandler = new PolicyHandler();
4. InputManagerService 设置回调,并启动 InputManagerService
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
public InputManagerCallback getInputManagerCallback() {
return mInputManagerCallback;
}
// mInputManagerCallback 的值为对象 InputManagerCallback(this)
final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this);
setWindowManagerCallbacks 设置回调
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
// 保证只有一个 callback
if (mWindowManagerCallbacks != null) {
unregisterLidSwitchCallbackInternal(mWindowManagerCallbacks);
}
mWindowManagerCallbacks = callbacks;
registerLidSwitchCallbackInternal(mWindowManagerCallbacks);
}
========
void registerLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) {
synchronized (mLidSwitchLock) {
// 将 callback 保存到 mLidSwitchCallbacks
mLidSwitchCallbacks.add(callback);
// Skip triggering the initial callback if the system is not yet ready as the switch
// state will be reported as KEY_STATE_UNKNOWN. The callback will be triggered in
// systemRunning().
if (mSystemReady) {
boolean lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID)
== KEY_STATE_UP;
callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen);
}
}
}
然后启动inputmanagerservice
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
5. 调用 displayReady 方法
wm.displayReady();
public void displayReady() {
synchronized (mGlobalLock) {
if (mMaxUiWidth > 0) {
mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
}
applyForcedPropertiesForDefaultDisplay();
mAnimator.ready();
mDisplayReady = true;
// Reconfigure all displays to make sure that forced properties and
// DisplayWindowSettings are applied.
mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked);
mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TOUCHSCREEN);
mIsFakeTouchDevice = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_FAKETOUCH);
}
try {
mActivityTaskManager.updateConfiguration(null);
} catch (RemoteException e) {
}
}
6. 系统准备完毕,调用 systemReady
wm.systemReady();
public void systemReady() {
mSystemReady = true;
// 调用 PhoneWindowManager.java 的 systemReady
mPolicy.systemReady();
mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
// 快照控制类
mTaskSnapshotController.systemReady();
mHasWideColorGamutSupport = queryWideColorGamutSupport();
mHasHdrSupport = queryHdrSupport();
// ui线程执行 loadSettings
UiThread.getHandler().post(mSettingsObserver::loadSettings);
整个启动过程有3个线程,systemserver主线程,”android.display”,”android.ui”,整个过程采用阻塞的方式(利用runWithScissors)执行,WMS.mH的Looper运行在”android.display”进程。
参考:
WMS启动流程分析 | Skytoby
WMS—启动过程 - Gityuan博客 | 袁辉辉的技术博客
Android渲染(一)_系统服务WMS启动过程(基于Android10) - 掘金