簡(jiǎn)介
我之前分析過(guò),但是感覺(jué)當(dāng)時(shí)迷迷糊糊的,自己也沒(méi)徹底弄清楚,今天我再次突破,這次感覺(jué)比以前清楚了,為什么要寫這個(gè)關(guān)系,因?yàn)樵陧?xiàng)目中Activity中見到Window win = getWindow();這種寫法。所以要想了解Wundow類我們就要明白WMS與我們的應(yīng)用到底有什么聯(lián)系。
應(yīng)用于WMS關(guān)聯(lián)的來(lái)源
AT.handleLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
handleConfigurationChanged(null, null);
//獲取WMS代理對(duì)象
WindowManagerGlobal.initialize();//[1.1]
Activity a = performLaunchActivity(r, customIntent);//[1.2]
if (a != null) {
//最終回調(diào)目標(biāo)Activity的onStart,onResume.
handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed);//[1.3]
...
} else {
...
}
...
}

1.1
我們?cè)赪indowManagerGlobal.java中看看
public final class WindowManagerGlobal {
...
public static void initialize() {
getWindowManagerService();
}
public static IWindowManager getWindowManagerService() {
synchronized (WindowManagerGlobal.class) {
if (sWindowManagerService == null) {
sWindowManagerService = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
...
}
return sWindowManagerService;
}
}
...
}
通過(guò)這里可以看到WindowManagerGlobal 持有WMS的Binder代理并且唯一。
1.2
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
//獲取ClassLoader
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
//創(chuàng)建目標(biāo)Activity對(duì)象
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
...
//創(chuàng)建Application對(duì)象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
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);//[2.1]
...
}
...
return activity;
}
- 創(chuàng)建目標(biāo)Activity對(duì)象
- 創(chuàng)建Application對(duì)象
- 執(zhí)行
activity.attach()
2.1
public class Activity extends ContextThemeWrapper implements ... {
private Window mWindow;
final void attach(...) {
...
mWindow = new PhoneWindow(this); //創(chuàng)建PhoneWindow
...
mUiThread = Thread.currentThread(); //獲取UI線程
mToken = token; //遠(yuǎn)程ActivityRecord的appToken的代理端
mApplication = application; //所屬的Appplication
...
//設(shè)置并獲取WindowManagerImpl對(duì)象
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
...
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
...
}
}
Window.setWindowManager
由于PhoneWindow繼承Window
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,boolean hardwareAccelerated) {
...
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
...
}
我們看到通過(guò)mWindow.setWindowManager()這個(gè)方法我們創(chuàng)建并獲取了WindowManagerImpl對(duì)象
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
....
}
這里我們就看出,當(dāng)Activity執(zhí)行到attach方法的時(shí)候就會(huì)創(chuàng)建PhoneWindow,PhoneWindow創(chuàng)建WindowManagerImpl,WindowManagerImpl持有WindowManagerGlobal
所以每個(gè)Activity的mWindowManager 是WindowManagerImpl對(duì)象,WindowManagerImpl 存有WindowManagerGlobal這個(gè)對(duì)象是進(jìn)程唯一。
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>();
private final ArraySet<View> mDyingViews = new ArraySet<View>();
...
WindowManagerGlobal這個(gè)對(duì)象管理當(dāng)前進(jìn)程里面所有的View(DecorView),ViewRootImpl,WindowManager.LayoutParams(頂層View的layout參數(shù))

應(yīng)用程序如何通知WMS呢?
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
final W mWindow;
final IWindowSession mWindowSession;
public ViewRootImpl(Context context, Display display) {
...
mWindowSession = WindowManagerGlobal.getWindowSession();//[1.1]
...
}
}
1.1
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;
}
}
由于前面說(shuō)過(guò)getWindowManagerService()返回的是WMS的代理,所以在WMS方法如下:
WMS
@Override
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
IInputContext inputContext) {
...
Session session = new Session(this, callback, client, inputContext);
return session;
}
Session是用aidl生成的Binder對(duì)象。因此WMS將這個(gè)Binder代理返回給了應(yīng)用程序,這樣應(yīng)用程序就可以通過(guò)WindowManagerGlobal 與WMS進(jìn)行通信了。其中WindowManagerGlobal持有的sWindowSession是WMS中的Session代理對(duì)象。
小結(jié)
也就是當(dāng)前應(yīng)用中有一份WindowManagerGlobal 唯一,這里有WMS的代理也有ViewRootImpl,ViewRootImpl 中的sWindowSession變量映射著WMS的Session Binder代理。
WMS如何通知應(yīng)用程序呢?
要想知道這個(gè)問(wèn)題我們就要研究ViewRootImpl這個(gè)類,我們就從它的成員變量開始:
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
final IWindowSession mWindowSession;
final W mWindow;
public ViewRootImpl(Context context, Display display) {
mWindowSession = WindowManagerGlobal.getWindowSession();
mWindow = new W(this);
}
...
}
我們看到了W對(duì)象,這個(gè)對(duì)象是Binder對(duì)象。
與此同時(shí)我們應(yīng)該看看WindowState對(duì)象。
final class WindowState implements WindowManagerPolicy.WindowState {
final WindowManagerService mService;
final Session mSession;
final IWindow mClient;
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent) {
...
mService = service;
mSession = s;
mClient = c;
...
}
}
在WMS中:
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();
...
}
我們看到在WMS中我們將這些核心的參數(shù)傳遞進(jìn)去,比如Session,client等。
上面這兩段代碼說(shuō)明,WindowState持有WMS,client,mSession的引用。持有這些引用就可以管理。Session我們知道,就是每一個(gè)WindowManagerGlobal持有唯一的一個(gè)由WMS產(chǎn)生的Session與app進(jìn)程對(duì)應(yīng)。client是什么?
這個(gè)就又要追溯到我們Activity的啟動(dòng)時(shí)候了。(也就是我們?cè)贏T.handleLaunchActivity中寫的1.3)
1.3
ActivityThread
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {
//執(zhí)行到onResume方法()
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
final Activity a = r.activity;
...
if (...) {
...
mNumVisibleActivities++;
if (...) {
//添加視圖[1.3.1]
r.activity.makeVisible();
}
}
...
} else {
...
}
}
1.3.1
Activity.makeVisible
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();//得到WindowManagerImpl對(duì)象此對(duì)象內(nèi)部擁有WindowManagerGlobal
wm.addView(mDecor, getWindow().getAttributes());//[1.3.2]
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
1.3.2
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
在這里也可以看的出來(lái),WindowManagerImpl其實(shí)都是轉(zhuǎn)調(diào)WindowManagerGlobal進(jìn)行操作。
WindowManagerGlobal
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
root = new ViewRootImpl(view.getContext(), display);
mViews.add(view);//這里的View是頂層View
mRoots.add(root);
mParams.add(wparams);
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
...
throw e;
}
}
我們看到利用ViewRootImpl去做setView的工作。
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
final W mWindow;
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
mView = view;//將頂層View保存
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
...
}
}
mWindowSession是持有WMS里面的Session,使用addToDisplay,我們將mWindow也就是W對(duì)象傳入到Session。所以WMS就可以通過(guò)W對(duì)象與應(yīng)用程序進(jìn)行通信了。
我們最后小結(jié)核心就好:
- WindowManagerImpl持有WindowManagerGlobal的引用
- WindowManagerGlobal可以和WMS進(jìn)行通信
- PhoneWindow可以得到WindowManagerImpl
- PhoneWindow在actvitiy的attach中創(chuàng)建
- WindowManagerGlobal.getWindowSession()得到WMS中Session(Binder)的代理
- ViewRootImpl持有sessopn代理
- ViewRootImpl中創(chuàng)建W對(duì)象
- W對(duì)象在activity啟動(dòng)過(guò)程中setView方法到了WMS中
- WMS在addView過(guò)程中通過(guò)WindowState將Session與W代理和WMS引用都保存。
應(yīng)用向WMS通信

WMS向應(yīng)用通信
