说双向通信之前,首先了解下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来通信