每个Activity创建时都会通过View RootImpl创建并持有一个W对象(extend IWindow),它也是一个Binder对象,向WMS提供服务;
WMS通过该Activity的WindowState持有W的代理对象从而间接调用Activity;
WMS的WindowState中持有session extends IWindowSession 它也是一个Binder对象向Application进程提供服务;
每个Activity需要调用WMS的方法都要通过session对象的代理;
WindowManagerService:系统单例,提供统一的Window管理;
Window:抽象,实现类是PhoneWindow,不可直接访问;每个Window对应一个View和一个ViewRootImpl
WindowManager:是一个接口,实现类是WindowManagerImpl,访问Window只能通过WindowManager;
WindowManagerGlobal:WindowManagerImpl的实际处理逻辑都委托给该类处理(桥接模式);
WindowState:每个Window实体都对应着一个WindowState,存储在WMS的一张Map中
WindowToken:
1.一个 WindowToken 就代表着一个应用组件,应用组件包括Activity等,Windowtoken和Window不是一一对应的关系,在WMS中属于同一 WindowToken 的做统一处理;
2.同时WindowToken 具有令牌的作用,应用组件在添加 Window 时都需要提供一个有效的 WindowToken 以表明自己的身份(系统窗口除外,WMS 会自动为该系统窗口隐式的创建 WindowToken)
AppWindowToken:WindowToken的子类,代表Activity的窗口令牌。
1.Activity执行attach时创建Window:
Activity.attach在创建新的Activity后onCreate之前执行,具体参考Activity启动过程
void attach() {
...
mWindow = PolicyManager.makeNewWindow(this); //return new PhoneWindow;
}
2.setContentView:
public void setContentView(int layoutResId) {
getWindow().setContentView(layoutResId);
}
PhoneWindow#setContentView:
@Override
public void setContentView(int layoutResID) {
//DecorView默认有两个子View,一个是Title,一个是Content
//这里的mContentParent是PhoneWindow的一个成员变量,代表DecorView的Content
if (mContentParent == null) { // 1
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
//加载layoutResID这个资源到mContentParent上
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent); // 2
}
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
3.PhoneWindow新建一个DecorView
//className = PhoneWindow#installDecor:
private void installDecor() {
//mDecor就是PhoneWindow的成员变量DecorView
if(mDecor == null){
DecorView = new DecorView();
View view = mLayoutInflater.inflate(layoutResId);
DecorView.addView(view);
}
//mDecor就是PhoneWindow的成员变量DecorView
if (mContentParent == null) {
//这个方法根据有无Title等属性向mDecor中添加Title布局和Content布局,并把Content返回赋给mContentParent
mContentParent = generateLayout(mDecor);
}
}
4.回调Activity的onContentChanged方法通知View已经初始化完毕;(此时Window和DecorView还没有建立联系)
acitivty.onContentChanged();
5.通过WMS把DecorView添加至Window:
在Activity的Resume阶段会执行:
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
//...
ActivityClientRecord r = performResumeActivity(token, clearHide); // 这里面会调用到onResume()方法
if (r != null) {
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 (a.mVisibleFromClient) {
a.mWindowAdded = true;
// 调用addView方法会创建ViewRootImpl
wm.addView(decor, l);
}
//...
}
}
}
WindowManagerImpl的addView方法:
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
...
@Override
public void addView(View view, ViewGroup.LayoutParams params) {
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// 创建了ViewRootImpl
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
//通过跨进程的方式向WMS(WindowManagerService)发起一个调用,从而将DecorView最终添加到Window上
//在这个过程中,ViewRootImpl、DecorView和WMS会彼此关联,参考ViewRootImpl类的结构
root.setView(view, wparams, panelParentView);
}
可以看到ViewRootImpl是在Activity启动的resume前创建的
6.在WindowManagerGlobal中新建ViewRootImpl;
Window添加过程:通过WindowManagerGlobal.addView(View,LayoutParams)
class WindowManagerGlobal{
//当前进程中所有Window对应的View;
private final ArrayList<View> mViews = new ArrayList<View>();
//当前进程中所有Window对应的ViewRootImpl;
private final ArrayList<ViewRootImpl> mRoots= new ArrayList<ViewRootImpl>();
//当前进程中所有Window对应的View的LayoutParams;
private final ArrayList<WindowManager.LayoutParams> mViews = new ArrayList<View>();
private final ArraySet<View> mDyingViewViews = new ArraySet<View>();
public void scheduleTraversals() //完成Measuer,Layout,Draw 三个过程
public void addView(View view,LayoutParams params) {
root = new ViewRootImpl(view.getContext());
view.setLayoutParams(params);
mViews.add(view);
mRoots.add(root);
mParams.add(params);
}
}
WindowManagerGlobal添加View时为该View创建了ViewRoolImpl;
7.在新建ViewRootImpl时创建W:
在Client端,ViewRootImpl创建时会创建一个W extends IWindowSession 对象:
public ViewRootImpl(Context context, Display display) {
mWindow = new W(this);
mWindowSession = WindowManagerGlobal.getWindowSession();
}
8.创建W的同时也创建了IWindowSession:
//className = WindowMangagerGlobal
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
InputMethodManager imm = InputMethodManager.getInstance();
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(imm, ...); //跨进程调用
}
return sWindowSession;
}
}
//className = WindowManagerService
public IWindowSession openSession(InputMethodManager imm) {
return new Session(this, imm, ...);
}
9.然后通过viewRootImpl.scheduleTraversals对View进行绘制;
public void requestLayout(){
scheduleTraversals();
}
再调用WindowSession代理调用WMS的addToDisplay()去添加一个窗口,WMS中为每一个窗口保留一个Session;
res = wWindowSession.addToDisPlay(mWindow,attr, ...) //这里只传递了Window,并没有把View传给WMS
WindowSession:
public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs, ...) {
return mService.addWindow(this, window, attrs, ...); //Call WMS
}
10.WMS对新的Window进行处理:
Map<Binder,WindowState> mWindowMap; //client = W extends Binder即为key
public int addWindow(Session session, IWindow client, WindowManager.LayoutParams attrs, ...) {
//参数token是所添加窗口对应的WindowToken
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
mPolicy.adjustWindowParamsLw(win.mAttrs);
win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
res = mPolicy.prepareAddWindowLw(win, attrs);
if (res != WindowManagerGlobal.ADD_OKAY) {
return res;
}
win.attach();
mWindowMap.put(client.asBinder(), win);
}
WindowManagerService描述:
class WindowManagerService IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
final IActivityManager mActivityManager;
final InputManagerService mInputManager;
//Key值为AMS binder
final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<>();
final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();
final HashMap<IBinder, AppWindowToken> mApptokenMap = new HashMap();
@Override //这里根据token来创建WindowToken并保存在map中;
public void addWindowToken(IBinder token, int type) {
//省略检查android.Manifest.permission.MANAGE_APP_TOKENS权限;
synchronized(mWindowMap) {
WindowToken wtoken = mTokenMap.get(token);
if (wtoken != null) {
return;
}
wtoken = new WindowToken(this, token, type, true);
mTokenMap.put(token, wtoken);
}
}
//这个方法是AMS调用的,AMS在创建完一个新的ActivityRecord之后会调用WMS的这个方法,即向WMS注册此Activity
//这里的token就是ActivityRecord中的appBinder;
public void addAppToken(IApplicationToken token, ...) {
......
synchronized(mWindowMap) {
AppWindowToken atoken = findAppWindowToken(token.asBinder());
if (atoken != null) {
return;
}
atoken = new AppWindowToken(this, token, voiceInteraction);
mApptokenMap.put(token.asBinder(), atoken);
}
}
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
win.attach();
mWindowMap.put(client.asBinder(), win);
win.mToken.addWindow(win);
}
}
ViewRootImpl 描述:
public class ViewRootImpl extends AbsViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
static IWindowSession sWindowSession;
final W mWindow;
View mView;
public ViewRootImpl(Context context, Display display) {
mWindow = new W(this, context);
}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
res = mWindowSession.addToDisplay(mWindow, mWindowAttributes, ...);
}
}
W描述:
static class W extends IWindow.Stub {
private final WeakReference<ViewRootImpl> mViewAncestor;
private final IWindowSession mWindowSession;
W(ViewRootImpl viewAncestor) {
mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
mWindowSession = viewAncestor.mWindowSession;
}
}
WindowState描述:
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState parentWindow, WindowManager.LayoutParams a, ...) {
mService = service;
mSession = s;
mClient = c;
mToken = token;
mAppToken = mToken.asAppWindowToken();
}
这里addWindowToken中所需要的token就是在AMS中创建的对应与Activity的token
WindowToken描述:
class WindowToken extends WindowContainer<WindowState> {
private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowToken" : TAG_WM;
protected final WindowManagerService mService;
final IBinder token;
final int windowType;
protected DisplayContent mDisplayContent;
WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
DisplayContent dc, boolean ownerCanManageAppTokens) {
mService = service;
token = _token;
windowType = type;
mPersistOnEmpty = persistOnEmpty;
mOwnerCanManageAppTokens = ownerCanManageAppTokens;
onDisplayChanged(dc);
}
void onDisplayChanged(DisplayContent dc) {
dc.reParentWindowToken(this);
mDisplayContent = dc;
SurfaceControl.openTransaction();
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState win = mChildren.get(i);
win.mWinAnimator.updateLayerStackInTransaction();
}
SurfaceControl.closeTransaction();
super.onDisplayChanged(dc);
}
}
WindowToken会在WindowManagerService.addWindowToken中创建
ViewManager描述:
public interface ViewManager {
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
添加一个Button到(100,100)这个坐标
Button btn = new Button(this);
WindowManager.LayoutParams layoutParams =
new WindowManager.LayoutParams(WRAP_CONTENT,WRAP_CONTENT,0,0,TRANSPARENT);
layoutParams.x = 100;
layoutParams.y = 100;
mWindowManager.addView(btn,layoutParams);