Posts WindowManagerService分析
Post
Cancel

WindowManagerService分析

Window

Window字面意思为窗口,是一个抽象类,负责管理View,它的唯一子类为PhoneWindow。它的官方定义如下:

Abstract base class for a top-level window look and behavior policy. An instance of this class should be used as the top-level view added to the window manager. It provides standard UI policies such as a background, title area, default key processing, etc.

The only existing implementation of this abstract class is android.view.PhoneWindow, which you should instantiate when needing a Window.

顶层窗口外观和行为策略的抽象基类。 该类的一个实例应被用作添加到窗口管理器的顶层视图。它提供了标准的UI策略,如背景、标题区域、默认键处理等。

这个抽象类现有的唯一实现是android.view.PhoneWindow,当你需要一个窗口时,应该实例化它。

Window创建过程

每一个Activity都会创建一个PhoneWindow对象,那么PhoneWindow是何时创建的呢?

ActivityThreadperformLaunchActivity方法会创建Activity,并调用Activityattach方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//frameworks/base/core/java/android/app/ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //...
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);//创建Activity
        //...
    } catch (Exception e) {
        //...
    }

    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation); //创建application

        if (activity != null) {
            //...
            //调用Activity的调用attach方法
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback,
                    r.assistToken);

            //调用Activity的onCreate方法 
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            //...
        }
        //...

    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
       //...
    }

    return activity;
}

Activity#attach

Activityattach方法会创建PhoneWindow对象,并创建一个WindowManager对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//frameworks/base/core/java/android/app/Activity.java
private Window mWindow;
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) {
  	//...
  	//创建PhoneWindow
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    //...
    //设置WindowManager 
    mWindow.setWindowManager(
            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), //调用ContextImpl的getSystemService方法
            mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
  	//...
    //赋值
    mWindowManager = mWindow.getWindowManager();
    //...
}

Activity#setContentView

ActivitysetContentView方法,实际上是调用的PhoneWindowsetContentView方法。

1
2
3
4
public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);//调用Window的setContentView
    initWindowDecorActionBar();
}

PhoneWindowsetContentView方法会调用installDecor创建mDecormContentParent。并把传入的View添加到mContentParent

PhoneWindow

setContentView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
private DecorView mDecor;
ViewGroup mContentParent;
public void setContentView(int layoutResID) {
    // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
    // decor, when theme attributes and the like are crystalized. Do not check the feature
    // before this happens.
    if (mContentParent == null) {
        installDecor(); //
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }

    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                getContext());
        transitionTo(newScene);
    } else {
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
    mContentParentExplicitlySet = true;
}

installDecor

installDecor创建mDecormContentParent.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void installDecor() {
    mForceDecorInstall = false;
    if (mDecor == null) { //如果Decoder为空
        mDecor = generateDecor(-1); //调用generateDecor创建DecorView
        mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        mDecor.setIsRootNamespace(true);
        if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
            mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
        }
    } else {
        mDecor.setWindow(this);//设置Window
    }
    if (mContentParent == null) { //调用generateLayout创建mContentParent
        mContentParent = generateLayout(mDecor);
        //...
    }
    //...
}

generateDecor

1
2
3
4
5
protected DecorView generateDecor(int featureId) {
    //...
    //创建DecorView
    return new DecorView(context, featureId, this, getAttributes());
}

generateLayout

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//创建ViewGroup
protected ViewGroup generateLayout(DecorView decor) {
    //...
    int layoutResource; //布局资源
    int features = getLocalFeatures();
    //根据设置不同的特性,设置不同的布局
    // System.out.println("Features: 0x" + Integer.toHexString(features));
    if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
        if (mIsFloating) {
            TypedValue res = new TypedValue();
            getContext().getTheme().resolveAttribute(
                    R.attr.dialogTitleIconsDecorLayout, res, true);
            layoutResource = res.resourceId;
        } else {
            layoutResource = R.layout.screen_title_icons;
        }
        // XXX Remove this once action bar supports these features.
        removeFeature(FEATURE_ACTION_BAR);
        // System.out.println("Title Icons!");
    } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
            && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
        // Special case for a window with only a progress bar (and title).
        // XXX Need to have a no-title version of embedded windows.
        layoutResource = R.layout.screen_progress;
        // System.out.println("Progress!");
    } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
        // Special case for a window with a custom title.
        // If the window is floating, we need a dialog layout
        if (mIsFloating) {
            TypedValue res = new TypedValue();
            getContext().getTheme().resolveAttribute(
                    R.attr.dialogCustomTitleDecorLayout, res, true);
            layoutResource = res.resourceId;
        } else {
            layoutResource = R.layout.screen_custom_title;
        }
        // XXX Remove this once action bar supports these features.
        removeFeature(FEATURE_ACTION_BAR);
    } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
        // If no other features and not embedded, only need a title.
        // If the window is floating, we need a dialog layout
        if (mIsFloating) {
            TypedValue res = new TypedValue();
            getContext().getTheme().resolveAttribute(
                    R.attr.dialogTitleDecorLayout, res, true);
            layoutResource = res.resourceId;
        } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
            layoutResource = a.getResourceId(
                    R.styleable.Window_windowActionBarFullscreenDecorLayout,
                    R.layout.screen_action_bar);
        } else {
            layoutResource = R.layout.screen_title;
        }
        // System.out.println("Title!");
    } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
        layoutResource = R.layout.screen_simple_overlay_action_mode;
    } else {
        // Embedded, so no decoration is needed.
        layoutResource = R.layout.screen_simple;
        // System.out.println("Simple!");
    }
    mDecor.startChanging();
    //填充布局并添加到mDecor
    mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
    //调用findViewById获取id为R.id.content的ViewGroup
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
    if (contentParent == null) { //如果获取不到,抛出异常
        throw new RuntimeException("Window couldn't find content container view");
    }
    //... 
    //返回 contentParent
    return contentParent;
}

setContentView方法通过PhoneWindow创建DecorView,并通过findViewById获取到DecorView的子ViewmContentParent,并把传入的View添加到mContentParent中。

AT#handleResumeActivity

ActivityThreadhandleResumeActivity方法中,会调用WindowManageraddView方法添加DecorView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//frameworks/base/core/java/android/app/ActivityThread.java
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
        String reason) {
    //a赋值     
    final Activity a = r.activity;
    if (r.window == null && !a.mFinished && willBeVisible) {
        r.window = r.activity.getWindow(); //获取Window
        View decor = r.window.getDecorView(); //获取DecorView
        decor.setVisibility(View.INVISIBLE);
        ViewManager wm = a.getWindowManager(); //获取WindowManager
        WindowManager.LayoutParams l = r.window.getAttributes();
        a.mDecor = decor;
        l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
        l.softInputMode |= forwardBit;
        if (r.mPreserveWindow) {
            a.mWindowAdded = true;
            r.mPreserveWindow = false;
            // Normally the ViewRoot sets up callbacks with the Activity
            // in addView->ViewRootImpl#setView. If we are instead reusing
            // the decor view we have to notify the view root that the
            // callbacks may have changed.
            ViewRootImpl impl = decor.getViewRootImpl();
            if (impl != null) {
                impl.notifyChildRebuilt();
            }
        }
        if (a.mVisibleFromClient) {
            if (!a.mWindowAdded) {//没有添加
                a.mWindowAdded = true;
                //调用WindowManager
                wm.addView(decor, l); 
            } else {
                //...
            }
        }
        //...
    } else if (!willBeVisible) {
      //...
    }
    //...
    Looper.myQueue().addIdleHandler(new Idler());
}

WindowManager

WindowManger继承自ViewManager接口,负责View的添加、更新和移除。ViewManager为上述的3个操作提供了3个方法:

1
2
3
4
5
6
public interface ViewManager
{
    public void addView(View view, ViewGroup.LayoutParams params);//添加View
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);//更新View布局
    public void removeView(View view);//移除View
}

WM创建过程

Activityattach方法会调用ContextImplgetSystemService方法获取WindowManager

1
2
3
4
5
6
//frameworks/base/core/java/android/app/ContextImpl.java
public Object getSystemService(String name) {
    //...
  	//调用SystemServiceRegistry的getSystemService方法
    return SystemServiceRegistry.getSystemService(this, name);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//frameworks/base/core/java/android/app/SystemServiceRegistry.java
public static Object getSystemService(ContextImpl ctx, String name) {
      if (name == null) {
          return null;
      }
      //获取ServiceFetcher
      final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
      if (fetcher == null) {
          if (sEnableServiceNotFoundWtf) {
              Slog.wtf(TAG, "Unknown manager requested: " + name);
          }
          return null;
      }
      //从fetcher中获取服务
      final Object ret = fetcher.getService(ctx);
      //...
      return ret;
}

SYSTEM_SERVICE_FETCHERS是一个ArrayMapkey是服务名称,value是服务对象。

1
2
private static final Map<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
        new ArrayMap<String, ServiceFetcher<?>>();

SystemServiceRegistry的静态代码块中,注册了多个服务。

1
2
3
4
5
6
7
8
9
10
11
12
static{
    //...
    //调用registerService注册WindManager
    registerService(Context.WINDOW_SERVICE, WindowManager.class,
            new CachedServiceFetcher<WindowManager>() {
        @Override
        public WindowManager createService(ContextImpl ctx) {
            return new WindowManagerImpl(ctx);//创建WindowManagerImpl
        }});
  //...
}

registerService方法很简单,就是将映射关系存入到ArrayMap中。

1
2
3
4
5
6
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);//添加到map中
    SYSTEM_SERVICE_CLASS_NAMES.put(serviceName, serviceClass.getSimpleName());
}

attach方法中,获取完WindowManager会调用PhoneWindowsetWindowManager方法。

1
2
3
4
5
6
7
8
9
10
11
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);
    }
    //调用WindowManagerImpl的createLocalWindowManager方法
    mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
1
2
3
4
//frameworks/base/core/java/android/view/WindowManagerImpl.java
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
    return new WindowManagerImpl(mContext, parentWindow); //创建WindowManagerImpl
}

addView

WindowManagerImpl中有一个WindowManagerGlobal实例mGlobalWindowManagerImpladdView方法调用的是WindowManagerGlobaladdView方法。

1
2
3
4
5
6
7
8
//frameworks/base/core/java/android/view/WindowManagerImpl.java
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
            mContext.getUserId());
}

WindowManagerGlobal是一个单例对象,可以通过getInstance方法获取它的实例。

1
2
3
4
5
6
7
8
9
//frameworks/base/core/java/android/view/WindowManagerGlobal.java
public static WindowManagerGlobal getInstance() {
    synchronized (WindowManagerGlobal.class) {
        if (sDefaultWindowManager == null) {
            sDefaultWindowManager = new WindowManagerGlobal();
        }
        return sDefaultWindowManager;
    }
}

WindowManagerGlobaladdView方法会创建ViewRootImpl对象,并调用ViewRootImplsetView方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private final ArrayList<View> mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
private final ArrayList<WindowManager.LayoutParams> mParams =
    new ArrayList<WindowManager.LayoutParams>();
public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow, int userId) {
        //...
        //创建ViewRootImpl
        root = new ViewRootImpl(view.getContext(), display);

        view.setLayoutParams(wparams);
        //分别将View、ViewRootImpl和参数添加到对应的ArrayList中
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);

        // do this last because it fires off messages to start doing things
        try {
            root.setView(view, wparams, panelParentView, userId); //调用ViewRootImpl的setView方法
        } catch (RuntimeException e) {
            // BadTokenException or InvalidDisplayException, clean up.
            if (index >= 0) {
                removeViewLocked(index, true);
            }
            throw e;
        }
    }
}

ViewRootImpl

构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//frameworks/base/core/java/android/view/ViewRootImpl.java
public ViewRootImpl(Context context, Display display) {
    this(context, display, WindowManagerGlobal.getWindowSession(),//获取WindowSession
            false /* useSfChoreographer */);
}

public ViewRootImpl(Context context, Display display, IWindowSession session) {
    this(context, display, session, false /* useSfChoreographer */);
}

public ViewRootImpl(Context context, Display display, IWindowSession session,
        boolean useSfChoreographer) {
    mContext = context;
    mWindowSession = session;//WindowSession赋值
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static IWindowSession getWindowSession() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowSession == null) {
            try {
                // Emulate the legacy behavior.  The global instance of InputMethodManager
                // was instantiated here.
                // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
                InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                //获取WindowManagerService
                IWindowManager windowManager = getWindowManagerService();
                //调用WindowManagerService的openSession方法
                sWindowSession = windowManager.openSession(
                        new IWindowSessionCallback.Stub() {
                            @Override
                            public void onAnimatorScaleChanged(float scale) {
                                ValueAnimator.setDurationScale(scale);
                            }
                        });
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return sWindowSession;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static IWindowManager getWindowManagerService() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowManagerService == null) {
            //获取代理类
            sWindowManagerService = IWindowManager.Stub.asInterface(
                    ServiceManager.getService("window"));
            try {
                if (sWindowManagerService != null) {
                    ValueAnimator.setDurationScale(
                            sWindowManagerService.getCurrentAnimatorScale());
                    sUseBLASTAdapter = sWindowManagerService.useBLAST();
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return sWindowManagerService;
    }
}

setView方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
    synchronized (this) {
        if (mView == null) {
            mView = view;
            try {
                //...
                //调用WindowSession的addToDisplayAsUser方法
                res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
                        getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
                        mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                        mAttachInfo.mDisplayCutout, inputChannel,
                        mTempInsets, mTempControls);
                setFrame(mTmpFrame);
            } catch (RemoteException e) {
              //...
            } finally {
                //...
            }

        }
    }
}
This post is licensed under CC BY 4.0 by the author.