说双向通信之前,首先了解下WindowManagerGlobal,ViewRootImpl的创建
WindowManagerGlobal的创建
创建过程如下图

- ActivityManagerService->ActivityThread
在AMS里面的main函数里会创建ActivityThread
public static void main(String[] args) {
//省略...
ActivityThread thread = new ActivityThread();
//省略...
}
ActivityThread是应用程序的UI线程,它主要负责对Android四大组件的创建和管理,以及控制Activity的生命周期等。
- ActivityThread-> WindowManagerGlobal
当我们执行startActivity启动一个页面时,最终会执行到ActivityThread的
handlerLauncherActivity方法来。在这个方法里,会创建一个WindowManagerGlobal。
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
//省略...
// 创建Activity之前初始化WindowManagerGlobal
WindowManagerGlobal.initialize();
//省略...
}
ViewRootImpl创建
创建过程如下图

- ActivityThread->Activity
创建Activity也是在AndroidThread的handleLauncherActivity方法里面,创建完WindowManagerGlobal之后调用
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
//省略...
// 创建Activity之前初始化WindowManagerGlobal
Activity a = performLaunchActivity(r, customIntent);
//省略...
}
- Activity->PhoneWindow
来到performLaunchActivity方法里面创建Activity,并且会执行Activity的attach方法来创建PhoneWindow
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//省略...
Activity activity = null;
//省略...
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
//省略...
} catch (Exception e) {
//省略...
}
}
if (activity != null) {
//省略...
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);
//省略...
}
- PhoneWindow->WindowManagerImpl
在Activity里的attach方法创建完PhoneWindow之后会执行Window的setWindowManager方法。
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) {
//省略...
mWindow = new PhoneWindow(this, window);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
//省略...
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
//省略...
}
PhoneWindow它是Window的唯一实现类,它会在setContentView方法里面创建DecoView,然后DecoView会添加一个id为content的FrameLayout作为根布局,关系如下图

创建好
PhoneWindow后,继续执行Window的setWindowManager方法,去创建WindowManagerImpl对象
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
- WindowManagerImpl->WindowManagerGlobal
在WindowManagerImpl里面会和WindowManagerGlobal进行关联,从而通过addView方法,removeView等方法来做为管理View的桥梁,传递给WindowManagerGlobal。
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
调用WindowManagerImpl的addView的位置主要有两个地方
1.Activity的makeVisible方法会调用
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
-
ActivityThread的handleResumeActivity会直接执行addView方法
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
//省略...
if (r.window == null && !a.mFinished && willBeVisible) {
//省略...
if (a.mVisibleFromClient && !a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
}
//省略...
if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
//省略...
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
//省略...
}
}
在添加DecoView的时候会调用addView方法,添加DecoView子View的时候就直接调用Activity的makeVisible的方法,然后在makeVisible调用addView方法。
- WindowManagerGlobal->ViewRootImpl
在WindowManagerGlobal的addView方法里面会创建ViewRootImpl
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
//省略...
ViewRootImpl root;
//省略...
root = new ViewRootImpl(view.getContext(), display);
}
ViewRootImpl它主要管理Window中所有的View的类,每个Activity中ViewRootImpl的数量取决于调用mWindowManager.addView的调用次数,Activity提供与AMS通信的Token(IBinder对象),创建Window为View提供显示的地方,而具体的View管理任务由ViewRootImpl来完成。
Activity->WMS通信
Activity到WMS通信主要是通过WindowManagerGlobal和ViewRootImpl来完成的,上面说到WindowManagerGlobal的initialize方法
public static void initialize() {
getWindowManagerService();
}
public static IWindowManager getWindowManagerService() {
synchronized (WindowManagerGlobal.class) {
if (sWindowManagerService == null) {
sWindowManagerService = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
try {
sWindowManagerService = getWindowManagerService();
//...省略
首先可以知道WindowManagerGlobal是个单例,最终调用的是getWindowManagerService方法。ServiceManager.getService("window")获取一个IBinder对象,来到getService方法
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
然后来到getIServiceManager()方法
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
这里可以通过如下图来解释

BinderInternal.getContextObject()其实获取的是BinderProxy这个代理类,然后通过asInterface()方法传给IServiceManager的代理类ServiceManagerProxy,也是ServiceManager的Java远程接口,从而实现Binder通信。
然后回到getService()方法,传入一个name参数,然后通过name获取指定的service,比如这里传入的是window,也就是获取到WindowManagerService对应的IBinder对象。最后调用IWindowManager.Stub.asInterface()方法获取到WindowManagerService的抽象类IWindowManager。
获取到WMS之后,然后会在ViewRootImpl初始化的时候调用openSession,获取IWindowSession
final IWindowSession mWindowSession;
public ViewRootImpl(Context context, Display display) {
mWindowSession = WindowManagerGlobal.getWindowSession();
}
getWindowSession方法
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
通过上面获取到的IWindowManager去调用openSession获取IWindowSession对象。然后通过IWindowSession进行通信。如下图

IWindowSession是Client端的代理,而它的Server端是Session。Session接收到请求后,就会转交给WMS进行处理。流程如下图

这样就实现了Activity到WMS的通信
WMS -> Activity通信
WMS到Activity通信,也是使用的代理模式,通过IWindow.Stub接口来实现,而WMS的代理对象就是在ViewRootImpl里面的W内部类,它通过上面获取的IWindowSession来在ViewRootImpl的setView方法里面调用addToDisplay方法把W代理传递给WMS
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
//..省略
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
//..省略
}
它传递的第一个参数mWindow就是W。mWindow中保存了W类型的Binder本地对象,这样通过函数addToDisplay就可以将W的代理对象传递Session然后给WMS服务。Session的addToDisplay如下
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
Rect outOutsets, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
然后来到WindowManagerService的addWindow方法,从这里可以看出每次ViewRootImpl的setView调用一次,对应一个Session请求。然后来到addWindow方法里面,在里面创建了一个WindowState对象,并且把W保存的Binder对象和Session保存在WindowState中,
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
//省略...
WindowState win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
//省略...
win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
win.attach();
win.applyScrollIfNeeded();
win.applyAdjustForImeIfNeeded();
}
创建WindowState
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent) {
mWindowId = new IWindowId.Stub() {
@Override
public void registerFocusObserver(IWindowFocusObserver observer) {
WindowState.this.registerFocusObserver(observer);
}
@Override
public void unregisterFocusObserver(IWindowFocusObserver observer) {
WindowState.this.unregisterFocusObserver(observer);
}
@Override
public boolean isFocused() {
return WindowState.this.isFocused();
}
};
}
创建IWindowId主要是用于标识指定窗口。它会在View的getWindowId方法里面获取到。
综上,WMS到Activity的通信主要是通过IWindow的代理对象W来进行通信。过程如下

Activity到WMS是通过IWindowSession来通信,WMS到Activity是通过IWindow代理w来通信