Window相关类

基于Android U

Window、WindowManager和WMS的关系

Window是一个抽象类,具体的实现类为PhoneWindow,它对View进行管理。

WindowManager是一个接口类,继承自接口ViewManager,它是用来管理Window的,它的实现类为WindowManagerImpl。如果我们想要对Window(View)进行添加、更新和删除操作就可以使用WindowManager,WindowManager会将具体的工作交由WMS来处理,WindowManager和WMS通过Binder来进行跨进程通信,WMS作为系统服务有很多API是不会暴露给WindowManager的。

Window包含了View并对View进行管理,Window用虚线来表示是因为Window是一个抽象概念,用来描述一个窗口,并不是真实存在的,Window的实体其实也是View。WindowManager用来管理Window,而WindowManager所提供的功能最终会由WMS进行处理。

WindowManager相关方法

WindowManager是一个接口类,继承自接口ViewManager,ViewManager中定义了三个方法,分别用来添加、更新和删除View。

1
2
3
4
5
6
7
frameworks/base/core/java/android/view/ViewManager.java
public interface ViewManager
{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}

WindowManager也继承了这些方法,而这些方法传入的参数都是View类型,说明Window是以View的形式存在的。WindowManager在继承ViewManager的同时,又加入很多功能,包括Window的类型和层级相关的常量、内部类以及一些方法,其中有两个方法是根据Window的特性加入的:

1
2
3
frameworks/base/core/java/android/view/WindowManager.java
public Display getDefaultDisplay();
public void removeViewImmediate(View view);

getDefaultDisplay()方法能够得知这个WindowManager实例将Window添加到哪个屏幕上了,换句话说,就是得到WindowManager所管理的屏幕(Display)。

removeViewImmediate()方法则规定在这个方法返回前要立即执行View.onDetachedFromWindow(),来完成传入的View相关的销毁工作。

PhoneWindow相关方法

PhoneWindow是在Activity创建的attach()方法中创建的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
frameworks/base/core/java/android/app/Activity.java
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
IBinder shareableActivityToken) {
...
mWindow = new PhoneWindow(this, window, activityConfigCallback); // 1
...
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); // 2
...
}

注释1处创建了PhoneWindow,注释2处调用PhoneWindow#setWindowManager()方法,这个方法在PhoneWindow的父类Window中实现。

1
2
3
4
5
6
7
8
9
10
11
frameworks/base/core/java/android/view/Window.java
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated;
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); // 1
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this); // 2
}
  1. 如果传入的WindowManager为null,就会在注释1处调用Context#getSystemService()方法,并传入服务的名称Context。WINDOW_SERVICE(值为window),具体在ContextImpl中实现。

    1
    2
    3
    4
    5
    frameworks/base/core/java/android/app/ContextImpl.java
    public Object getSystemService(String name) {
    ...
    return SystemServiceRegistry.getSystemService(this, name);
    }

    调用SystemServiceRegistry#getSystemService()方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    frameworks/base/core/java/android/app/SystemServiceRegistry.java
    public static Object getSystemService(ContextImpl ctx, String name) {
    ...
    final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    ...
    final Object ret = fetcher.getService(ctx);
    ...
    return ret;
    }

    SYSTEM_SERVICE_FETCHERS是一个ArrayMap,其Key为系统服务名,Value为ServiceFetcher对象。

    • SYSTEM_SERVICE_FETCHERS是在什么时候被赋值的?

      1
      2
      3
      4
      5
      6
      7
      frameworks/base/core/java/android/app/SystemServiceRegistry.java
      private static <T> void registerService(@NonNull String serviceName,
      @NonNull Class<T> serviceClass, @NonNull ServiceFetcher<T> serviceFetcher) {
      SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
      SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
      SYSTEM_SERVICE_CLASS_NAMES.put(serviceName, serviceClass.getSimpleName());
      }
    • registerService()方法是什么时候被调用的?

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      frameworks/base/core/java/android/app/SystemServiceRegistry.java
      static {
      ...
      registerService(Context.WINDOW_SERVICE, WindowManager.class,
      new CachedServiceFetcher<WindowManager>() {
      @Override
      public WindowManager createService(ContextImpl ctx) {
      return new WindowManagerImpl(ctx); // 1
      }});
      ...
      }

      在SystemServiceRegistry的静态代码块中会调用多个registerService()方法,registerService()方法内部会将传入的服务的名称存入到SYSTEM_SERVICE_FETCHERS中。从注释1处可以看出,传入的Context.WINDOW_SERVICE对应的就是WindowManagerImpl实例。

  2. mContext.getSystemService()得到WindowManagerImpl实例后转为WindowManager类型,在注释2处调用了WindowManagerImpl#createLocalWindowManager()方法。

    1
    2
    3
    4
    frameworks/base/core/java/android/view/WindowManagerImpl.java
    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
    return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken);
    }

    createLocalWindowManager()方法同样也是创建WindowManagerImpl,不同的是这次创建WindowManagerImpl时将创建它的Window作为参数传了进来,这样WindowManagerImpl就持有了Window的引用,可以对Window进行操作,比如在Window中添加View,会调用WindowManagerImpl的addView()方法,如下所示:

    1
    2
    3
    4
    5
    6
    7
    frameworks/base/core/java/android/view/WindowManagerImpl.java
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    android.util.SeempLog.record_vg_layout(383,params);
    applyTokens(params);
    mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
    mContext.getUserId()); // 1
    }

    注释1处调用了WindowManagerGlobal的addView()方法,其中参数mParentWindow就是上面提到的Window,可以看出WindowManagerImpl虽然是WindowManage的实现类,但是没有实现什么功能,而是将功能实现委托给了WindowManagerGlobal,这里用到的是桥接模式。

我们来查看WindowManagerImpl中是如何定义WindowManagerGlobal的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public final class WindowManagerImpl implements WindowManager {
@UnsupportedAppUsage
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance(); // 1
@UiContext
@VisibleForTesting
public final Context mContext;
private final Window mParentWindow; // 2

private WindowManagerImpl(Context context, Window parentWindow,
@Nullable IBinder windowContextToken) {
mContext = context;
mParentWindow = parentWindow; // 3
mWindowContextToken = windowContextToken;
mWindowMetricsController = new WindowMetricsController(mContext);
}
}

注释1处可以看出WindowManagerGlobal是一个单例,说明在一个进程中只有一个WindowManagerGlobal实例。

注释2处结合注释3处说明这个WindowManagerImpl实例会作为哪个Window的子Window,这也就说明在一个进程中WindowManagerImpl可能会有多个实例。

通过如上的源码分析,WindowManager的关联类如下图所示:

从图中可以看出,PhoneWindow继承自Window,Window通过setWindowManager()方法与WindowManager发生关联。WindowManager继承自接口ViewManager,WindowManagerImpl是WindowManager接口的实现类,但是具体的功能都会委托给WindowManagerGlobal来实现。


Window相关类
https://citrus-maxima.github.io/2024/03/10/Window相关类/
作者
柚子树
发布于
2024年3月10日
许可协议