對於Activity,在ActivityThread.java在handleLaunchActivity會調用performLaunchActivity,而performLaunchActivity則調用Activity中的attach函數,實現創建window(實際是PhoneWindow):
Activity.java
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) {
//創建window
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
//獲取WindowManager
mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
mWindowManager = mWindow.getWindowManager();
}
PolicyManager.java
public static Window makeNewWindow(Context context) {
//使用sPolicy來創建window
return sPolicy.makeNewWindow(context);
}
這裡的sPolicy定義是:private static final IPolicy sPolicy;
那麼,如何初始化?
private static final String POLICY_IMPL_CLASS_NAME =
"com.Android.internal.policy.impl.Policy";
static {
// 獲取Policy這個class並實例化
try {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
}
}
再往下:
Policy.java
public class Policy implements IPolicy {
public Window makeNewWindow(Context context) {
/*可見,activity.attach中的PolicyManager.makeNewWindow(this)是新建一個PhoneWindow
*context則是Activity中實現的ContextImpl實例
*而PhoneWindow是window的子類,故而可以賦給window
*/
return new PhoneWindow(context);
}
……
}
由Policy的定義可知,Policy implement IPolicy,並且實現了它定義的接口。
/*至此,實現了創建一個PhoneWindow*/
接著Activity.attach往下:
//設置window的Callback,Activity是實現了Window.Callback的接口的
mWindow.setCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
//設置soft input mode
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
我們回到最初,我們說過,在ActivityThread中會在performLaunchActivity之後判斷是否成功,並真正調用handleResumeActivity();
ActivityThread.java
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
ActivityClientRecord r = performResumeActivity(token, clearHide);
//這個layoutParams是在ActivityClientRecord 這裡的。
WindowManager.LayoutParams l = r.window.getAttributes();
……
/*
*r是ActivityClientRecord,在performResumeActivity之前並沒有將window加入到r中
*那麼,activity如何創建並且是如何加入到這個activityClientRecord中的呢?
*/
if (r.window == null && !a.mFinished && willBeVisible) {
//在activity的attach函數中創建的activity的window賦給r.window
r.window = r.activity.getWindow();
//我們知道attach創建的是PhoneWindow,那PhoneWindow中DecorView如何創建的?
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
//WindowManager是ViewManager的子類
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
//將decor賦給Activity的mDecor
a.mDecor = decor;
//type的數值是1
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
//將主View(decorView)添加到WindowManager中
wm.addView(decor, l);
}
}
}
我們在Context的分析中已經分析過,WindowManager實際上初始化的是WindowManagerImpl,通過它來進行各種操作,我們轉到WindowManagerImpl.java分析addView
PhoneWindow.java
是這樣獲取DecorView的
public final View getDecorView() {
if (mDecor == null) {
installDecor();
}
return mDecor;
}
private void installDecor() {
if (mDecor == null) {
//創建DecorView,接著往下去看如何創建DecorView,DecorView是個什麼?
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
}
if (mContentParent == null) {
//這個mContentParent是干什麼的?
mContentParent = generateLayout(mDecor);
}
}
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker
{
public DecorView(Context context, int featureId) {
super(context);
mFeatureId = featureId;
}
/*
*DecorView中還實現了派發key event、key快捷方式等方法
*/
public boolean dispatchKeyEvent(KeyEvent event) {
……
}
public boolean dispatchKeyShortcutEvent(KeyEvent ev) {
……
}
}
由DecorView定義我們可以知道,DecorView是一個擴張的FrameLayout,它是所有當前的Activity中View的主View
WindowManagerImpl.java
public void addView(View view, ViewGroup.LayoutParams params, CompatibilityInfoHolder cih) {
addView(view, params, cih, false);
}
private void addView(View view, ViewGroup.LayoutParams params,
CompatibilityInfoHolder cih, boolean nest) {
//這說明將DecorView添加到WindowManager必須要滿足下面這個條件,否則會報異常
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException(
"Params must be WindowManager.LayoutParams");
}
final WindowManager.LayoutParams wparams
= (WindowManager.LayoutParams)params;
ViewRootImpl root;
View panelParentView = null;
synchronized (this) {
//主要是查看要添加的View是否已經在mViews中了,若有就返回對應的index
int index = findViewLocked(view, false);
if (index >= 0) {
if (!nest) {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
//為什麼這樣,因為若添加了view到mViews,那麼mRoots也對應添加
root = mRoots[index];
root.mAddNesting++;
// Update layout parameters.
view.setLayoutParams(wparams);
root.setLayoutParams(wparams, true);
return;
}
root = new ViewRootImpl(view.getContext());
//第一次添加view到mView,mViews是還沒有分配空間的
if (mViews == null) {
index = 1;
mViews = new View[1];
mRoots = new ViewRootImpl[1];
mParams = new WindowManager.LayoutParams[1];
} else {
//這裡奇怪的是,為什麼將mViews、mRoots中內容先保存然後再拷貝一遍呢?
index = mViews.length + 1;
Object[] old = mViews;
mViews = new View[index];
System.arraycopy(old, 0, mViews, 0, index-1);
old = mRoots;
mRoots = new ViewRootImpl[index];
System.arraycopy(old, 0, mRoots, 0, index-1);
old = mParams;
mParams = new WindowManager.LayoutParams[index];
System.arraycopy(old, 0, mParams, 0, index-1);
}
index--;
//這裡就完成了添加View到WindowManager
mViews[index] = view;
mRoots[index] = root;
mParams[index] = wparams;
}
//這一步非常重要
root.setView(view, wparams, panelParentView);
}
ViewRootImpl.java
public ViewRootImpl(Context context) {
getWindowSession(context.getMainLooper());
//獲取當前activity的線程
mThread = Thread.currentThread();
//IWindow的代理,在ViewRootImpl中創建
//這裡強調一下,創建W時傳入this,代指ViewRootImpl的ContextImpl,而這個ContextImpl又是由
//WindowManagerImpl傳入的ContextImpl,再之後就是當前的調用者的ContextImpl傳遞給//ContextImpl.java的獲取Service時傳入的。這樣看來,在當前的上下文創建了一個實例,只要傳入它的//Context,那麼,都是可以通過Context找到這個當前調用者的
mWindow = new W(this);
}
public static IWindowSession getWindowSession(Looper mainLooper) {
synchronized (mStaticInit) {
if (!mInitialized) {
try {
//先獲取InputMethodManager,然後用它調用InputMethodManagerService
InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
//獲取WindowManagerService中的Session,同時我們看到這裡用到了
//InputMethodManagerService的mClient和ControlledInputConnectionWrapper
sWindowSession = Display.getWindowManager().openSession(
imm.getClient(), imm.getInputContext());
mInitialized = true;
} catch (RemoteException e) {
}
}
//注意:sWindowSession是個全局變量
return sWindowSession;
}
}
WindowManagerService.java
這個sWindowSession是在WindowManagerService中實現的,是client調用WindowManagerService的接口。
每一個ViewRoot對應在WindowManagerService中有一個sWindowSession
同時我們注意,這裡傳入的client是InputMethodManager中的IInputMethodClient類型的mClient
public IWindowSession openSession(IInputMethodClient client,
IInputContext inputContext) {
……
//創建一個Session並返回
//在這個Session的構造函數中有如下操作:
//mService.mInputMethodManager.addClient(client, inputContext, mUid, mPid);
//將InputMethodManger中的mClient添加進去了
Session session = new Session(this, client, inputContext);
return session;
}
我們接著,WindowManagerImpl往下看,在setView的最後會調用ViewRoot.setView(),這個是連接client和
WindowManagerService的關鍵地方:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
……
try {
mOrigWindowType = mWindowAttributes.type;
//這裡調用
res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets, mInputChannel);
} catch (RemoteException e) {
……
}
}
Session.java
public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
//如此,將Client端提供給WindowManagerService的接口IWindow賦給WindowManagerService使用
return mService.addWindow(this, window, seq, attrs, viewVisibility, outContentInsets,
outInputChannel);
}
WindowManagerService.java
//主要是將PhoneWindow的回調函數IWindow傳遞給WindowManagerService
//outInputChannel是inputChannel
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility,
Rect outContentInsets, InputChannel outInputChannel) {
WindowState win = null;
win = new WindowState(this, session, client, token,
attachedWindow, seq, attrs, viewVisibility);
……
win.attach();
if (outInputChannel != null && (attrs.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
String name = win.makeInputChannelName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
win.setInputChannel(inputChannels[0]);
inputChannels[1].transferTo(outInputChannel);
mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
}
}
在windowState.java中調用attach:
void attach() {
mSession.windowAddedLocked();
}
最後在Session.java中實現添加:
void windowAddedLocked() {
if (mSurfaceSession == null) {
mSurfaceSession = new SurfaceSession();
mService.mSessions.add(this);
}
mNumWindow++;
}
至此,正式建立activity的client和windowManagerService之間的聯系:
ViewRootImpl 通過IWindowSession 訪問 WindowManagerService
WindowManagerService通過IWindow訪問ViewRootImpl