我们先来看应用和WMS的通信
一、应用到WMS的通道
Activity对象中都有一个类型为Window的成员变量mWindow,定义如下:
-
public
class Activity {
-
.......
-
private Window mWindow;
-
....
-
}
Window对象在应用进程中代表一个窗口。从WMS的角度,不关心各种View,只关心Window对象。Window是一个抽象类。
-
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) {
-
attachBaseContext(context);
-
-
mFragments.attachActivity(
this, mContainer,
null);
-
-
mWindow = PolicyManager.makeNewWindow(
this);
再来看看Activity的attach方法,这个方法是Activity被创建的时候调用的。其初始化了mWindow对象。这里就不跟代码了,最后返回的是PhoneWindow对象。在Activity操作的Window,实际都是PhoneWindow。
在应用进程中WindowManager是和WMS进行通信的。
private WindowManager mWindowManager;
WindowManager也是一个接口类:
public interface WindowManager extends ViewManager {
再来看看attach方法:
-
final void attach(Context context, ActivityThread aThread,.........) {
-
........
-
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();
-
....
-
}
在attach方法中,对mWindowManager变量的赋值是调用mWIndow的getWindowManager,但是之前还调用了mWIndow的setWindowManager方法,这个方法不是在PhoneWindow中实现的,而是在基类中。
-
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);
-
}
在setWindowManager方法中调用了WindowManagerImpl类的createLocalWindowManager方法
-
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
-
return
new WindowManagerImpl(mDisplay, parentWindow);
-
}
因此Activity中的mWindowManager实际上是一个WindowManagerImpl对象,看看其定义
-
public
final
class WindowManagerImpl implements WindowManager {
-
private
final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
-
private
final Display mDisplay;
-
private
final Window mParentWindow;
在WindowManagerImpl 中定义了一个mGlobal变量,是通过WindowManagerGlobal.getInstance得到:
-
public static WindowManagerGlobal getInstance() {
-
synchronized (WindowManagerGlobal.class) {
-
if (sDefaultWindowManager ==
null) {
-
sDefaultWindowManager =
new WindowManagerGlobal();
-
}
-
return sDefaultWindowManager;
-
}
-
}
getInstance方法创建了一个全局唯一的WindowManagerGlobal对象,保存到静态变量sDefaultWindowManager
WindowManagerImpl类中各种方法的实现只是在转调WindowManagerGlobal类的方法,由此可见一个应用进程中所有Activity都是通过这个进程内唯一的WindowManagerGlobal对象和WMS通信。
-
public
final
class WindowManagerGlobal {
-
.....
-
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>();
-
.....
-
}
WindowManagerGlobal 保存了应用所有顶层view相关信息
mViews保存所有顶层View对象(DecorView)
mRoots保存和顶层View关联的ViewRootImpl
mParams保存的是创建顶层View的layout参数
ViewRootImpl类有很多成员变量,来看看和WMS相关的,
-
public
final
class ViewRootImpl {
-
.....
-
final IWindowSession mWindowSession;
-
.....
-
final W mWindow;
-
}
来看下ViewRootImpl的构造函数:
-
public ViewRootImpl(Context context, Display display) {
-
mContext = context;
-
mWindowSession = WindowManagerGlobal.getWindowSession();
-
.......
-
mWindow =
new W(
this);
其中mWIndowSession变量是IWindowSession,它是WMS中某个Binder对象的引用对象。mWindowSession的值是通过WindowManagerGlobal的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) {
-
Log.e(TAG,
"Failed to open window session", e);
-
}
-
}
-
return sWindowSession;
-
}
-
}
而getWindowManagerService就是获取WMS的客户端的Binder
-
public static IWindowManager getWindowManagerService() {
-
synchronized (WindowManagerGlobal.class) {
-
if (sWindowManagerService ==
null) {
-
sWindowManagerService = IWindowManager.Stub.asInterface(
-
ServiceManager.getService(
"window"));
-
try {
-
sWindowManagerService = getWindowManagerService();
-
ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
-
}
catch (RemoteException e) {
-
Log.e(TAG,
"Failed to get WindowManagerService, cannot set animator scale", e);
-
}
-
}
-
return sWindowManagerService;
-
}
-
}
最后调用了WMS的openSession函数
-
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
-
IInputContext inputContext) {
-
if (client ==
null)
throw
new IllegalArgumentException(
"null client");
-
if (inputContext ==
null)
throw
new IllegalArgumentException(
"null inputContext");
-
Session session =
new Session(
this, callback, client, inputContext);
-
return session;
-
}
openSession函数戒指创建了一个Session对象,是一个Binder服务对象。返回给用户进程的是Session的客户对象,这个客户对象就保存在WindowManagerGlobal的静态变量sWindowSession。调用函数getWindowSession方法返回的都是这个保存在sWindowSession中的IWindowSession对象。因此一个用户进程中所有ViewRootImpl对象中的mWIndowSession都是相同的。它就是建立了一条和WMS的通道。
二、WMS到应用的通道
Activity启动的时候会调用ActivityThread的handleResumeActivity方法,该方法调用了Activity的makeVisible方法:
-
void makeVisible() {
-
if (!mWindowAdded) {
-
ViewManager wm = getWindowManager();
-
wm.addView(mDecor, getWindow().getAttributes());
-
mWindowAdded =
true;
-
}
-
mDecor.setVisibility(View.VISIBLE);
-
}
这个方法中又调用了WindowManager的addView方法,最后实际是调用WindowManagerGlobal的addView方法
-
public void addView(View view, ViewGroup.LayoutParams params,
-
Display display, Window parentWindow) {
-
........
-
root =
new ViewRootImpl(view.getContext(), display);
//创建ViewRootImpl对象
-
-
view.setLayoutParams(wparams);
-
-
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);
-
}
-
......
-
}
在WindowManagerGlobal的addView方法中创建了ViewRootImpl对象,通过其setView方法。把它和顶层的View对象关联在了一起:
-
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
-
synchronized (
this) {
-
if (mView ==
null) {
-
mView = view;
-
......
-
try {
-
mOrigWindowType = mWindowAttributes.type;
-
mAttachInfo.mRecomputeGlobalAttributes =
true;
-
collectViewAttributes();
-
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
-
getHostVisibility(), mDisplay.getDisplayId(),
-
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel);
-
}
catch (RemoteException e) {
-
.....
-
}
方法中会检查mView的值,如果已经赋值了就不再赋了。因此ViewRootImpl对象和顶层的View之前的关联只会执行一次。在setView方法中会调用Session的addToDisplay方法,这个方法的第一个参数mWIndow,它是类W的实例对象。在ViewRootImpl构造函数中创建的。W是ViewRootImpl的嵌入类。
-
static
class W extends IWindow.Stub {
-
private
final WeakReference<ViewRootImpl> mViewAncestor;
-
private
final IWindowSession mWindowSession;
W是一个Binder服务类,通过addToDisplay方法将它的实例对象传到WMS。W在WMS中的客户对象的类型是IWindow,WMS保存了应用中每个顶层窗口的IWindow对象。
在WMS中,WindowState对象代表一个窗口。WindowState类定义了表示每个窗口的窗口信息
-
final
class WindowState implements WindowManagerPolicy.WindowState {
-
static
final String TAG =
"WindowState";
-
-
final WindowManagerService mService;
-
final WindowManagerPolicy mPolicy;
-
final Context mContext;
-
final Session mSession;
-
final IWindow mClient;
其中mClient是客户进程的Binder对象在WMS的引用,而mSession是WMS中和客户进程创建的Binder服务对象。
final class Session extends IWindowSession.Stub
Session类是从IWindowSession.Stub派生的。应用调用了Session的addToDisplay,最后调用了WMS的addWindow函数。
-
@Override
-
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
-
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
-
InputChannel outInputChannel) {
-
return mService.addWindow(
this, window, seq, attrs, viewVisibility, displayId,
-
outContentInsets, outStableInsets, outInputChannel);
-
}
WMS的addWindows方法
-
public int addWindow(Session session, IWindow client,...) {
-
......
-
win =
new WindowState(
this, session, client, token,
-
attachedWindow, appOp[
0], seq, attrs, viewVisibility, displayContent);
-
......
-
win.attach();
-
mWindowMap.put(client.asBinder(), win);
-
......
-
}
addWIndow函数较长,这里创建了WindowState对象,并把它加入mWindowMap列表中,这里面保存了系统所有的顶层窗口信息。
这样从应用到WMS,和从WMS到应用的通道都建立了。
应用 WMS
WindowManagerGlobal ———IWindowSession——–> Session
Window <———–IWindow————– WindowState
三、WMS的成员变量
-
final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
-
final ArraySet<Session> mSessions =
new ArraySet<Session>();
-
final HashMap<IBinder, WindowState> mWindowMap =
new HashMap<IBinder, WindowState>();
-
final HashMap<IBinder, WindowToken> mTokenMap =
new HashMap<IBinder, WindowToken>();
mSessions保存的是Session服务类的对象,每个应用在WMS都有一个对应的Session
mTokenMap保存的是所有窗口的WindowToken对象
mWindowMap保存的是所有窗口的WindowState对象
mPolicy是WMS的窗口策略类,目前只有一个PhoneWindowService。