說雙向通信之前,首先了解下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;
}
這裏可以通過如下圖來解釋
https://blog.csdn.net/luoshengyang/article/details/6642463羅老師博客.png” title=”” />
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來通信