WMS

几个重要类型

1.W:Activity向WMS提供的接口

每个Activity创建时都会通过View RootImpl创建并持有一个W对象(extend IWindow),它也是一个Binder对象,向WMS提供服务;
WMS通过该Activity的WindowState持有W的代理对象从而间接调用Activity;

2.WindowSession: WMS向Activity提供的接口

WMS的WindowState中持有session extends IWindowSession 它也是一个Binder对象向Application进程提供服务;
每个Activity需要调用WMS的方法都要通过session对象的代理;

3.其他:

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的窗口令牌。

WMS_第1张图片

ActivityWindow创建过程:

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);
}

WMS用途:

添加一个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);

你可能感兴趣的:(WMS)