- 浏览: 23897 次
- 性别:
- 来自: 北京
最新评论
page6
WindowManagerGlobal的getWindowSession函数的定义如下:
1 public static IWindowSession getWindowSession(Looper mainLooper) {
2 synchronized (WindowManagerGlobal.class) {
3 if (sWindowSession == null) {
4 try {
5 InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
6 IWindowManager windowManager = getWindowManagerService();
7 sWindowSession = windowManager.openSession(
8 imm.getClient(), imm.getInputContext());
9 float animatorScale = windowManager.getAnimationScale(2);
10 ValueAnimator.setDurationScale(animatorScale);
11 } catch (RemoteException e) {
12 Log.e(TAG, "Failed to open window session", e);
13 }
14 }
15 return sWindowSession;
16 }
17 }
第2行(WindowManagerGlobal->getWindowSession)会在WindowManagerGlobal上加锁,
sWindowSession是个static的成员变量, 定义如下:
private static IWindowSession sWindowSession;
第6行(WindowManagerGlobal->getWindowSession)会调用getWindowManagerService获得WindowManagerService服务.
第7-8行(WindowManagerGlobal->getWindowSession)会调用WindowManagerService服务的openSession函数, 这也就标志着和WindowManagerService建立了链接.关于WindowManagerService的openSession函数的分析可以参考page7文件.
第9-10行(WindowManagerGlobal->getWindowSession)会得到windowManager的动画放大的参数
page7
WindowManagerService的openSession函数的定义如下:
1 public IWindowSession openSession(IInputMethodClient client,
2 IInputContext inputContext) {
3 if (client == null) throw new IllegalArgumentException("null client");
4 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
5 Session session = new Session(this, client, inputContext);
6 return session;
7 }
第3-4行(WindowManagerService->openSession)判断传入的参数是否为空, 如果为空则会抛出异常.
第5行(WindowManagerService->openSession)会构造一个Session对象, 并返回该对象. 关于Session对象的构造过程可以参考page8文件.
page8
在这篇文章里我们分析一下Session对象的创建过程.
Session类的定义如下:
final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient
Session继承自IWindowSession.Stub,由此可见Session是一个Binder本地对象, 可以利用Binder机制在进程间传输. Session的构造函数的定义如下:
1 public Session(WindowManagerService service, IInputMethodClient client,
2 IInputContext inputContext) {
3 mService = service;
4 mClient = client;
5 mInputContext = inputContext;
6 mUid = Binder.getCallingUid();
7 mPid = Binder.getCallingPid();
8 StringBuilder sb = new StringBuilder();
9 sb.append("Session{");
10 sb.append(Integer.toHexString(System.identityHashCode(this)));
11 sb.append(" ");
12 sb.append(mPid);
13 if (mUid < Process.FIRST_APPLICATION_UID) {
14 sb.append(":");
15 sb.append(mUid);
16 } else {
17 sb.append(":u");
18 sb.append(UserHandle.getUserId(mUid));
19 sb.append('a');
20 sb.append(UserHandle.getAppId(mUid));
21 }
22 sb.append("}");
23 mStringName = sb.toString();
24
25 synchronized (mService.mWindowMap) {
26 if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
27 IBinder b = ServiceManager.getService(
28 Context.INPUT_METHOD_SERVICE);
29 mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
30 }
31 }
32 long ident = Binder.clearCallingIdentity();
33 try {
34 // Note: it is safe to call in to the input method manager
35 // here because we are not holding our lock.
36 if (mService.mInputMethodManager != null) {
37 mService.mInputMethodManager.addClient(client, inputContext,
38 mUid, mPid);
39 } else {
40 client.setUsingInputMethod(false);
41 }
42 client.asBinder().linkToDeath(this, 0);
43 } catch (RemoteException e) {
44 // The caller has died, so we can just forget about this.
45 try {
46 if (mService.mInputMethodManager != null) {
47 mService.mInputMethodManager.removeClient(client);
48 }
49 } catch (RemoteException ee) {
50 }
51 } finally {
52 Binder.restoreCallingIdentity(ident);
53 }
54 }
第25-31行(Session->Session)会确保WindowManagerService中INPUT_METHOD_SERVICE的服务.
第36-41行(Session->Session)会将IInputMethodClient传给mInputMethodManager去
第42行(Session->Session)会加入Binder死亡通知
page9
应用程序进程将一个Activity组件的视图对象设置到与它所关联的一个ViewRoot对象的内部的时候, 就会将一个实现了IWindow接口的Binder本地对象传递给WindowManagerService服务.
这个实现了IWindow接口的Binder本地对象唯一地识别了一个Activity组件, 当WindowManagerService服务接受到这个Binder本地对象之后, 就会为它创建一个WindowState对象, 这样WindowManagerService服务以后就可以通过它来和Activity组件通信, 以便可以要求Activity组件配合来管理系系统中的所有窗口.
在ViewRoot创建的过程中, 会创建一个W类型的对象, 并赋值给ViewRoot的成员变量mWindow.
我们先来看一下W类的创建过程, W类的定义如下, W类是ViewRootImpl类的一个内部类:
static class W extends IWindow.Stub
W类的构造函数的定义如下:
W(ViewRootImpl viewAncestor) {
mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
mWindowSession = viewAncestor.mWindowSession;
}
由此可见, 在W类的内部也拿着WindowSession对象.
我们以ViewRootImpl类的setView函数作为入口来分析Activity组件与WindowManagerService服务的连接过程, 即一个WindowState对象的创建过程.
1 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
2 synchronized (this) {
3 if (mView == null) {
4 mView = view;
5 mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
6 mFallbackEventHandler.setView(view);
7 mWindowAttributes.copyFrom(attrs);
8 attrs = mWindowAttributes;
9 // Keep track of the actual window flags supplied by the client.
10 mClientWindowLayoutFlags = attrs.flags;
11
12 setAccessibilityFocus(null, null);
13
14 if (view instanceof RootViewSurfaceTaker) {
15 mSurfaceHolderCallback =
16 ((RootViewSurfaceTaker)view).willYouTakeTheSurface();
17 if (mSurfaceHolderCallback != null) {
18 mSurfaceHolder = new TakenSurfaceHolder();
19 mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
20 }
21 }
22
23 CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
24 mTranslator = compatibilityInfo.getTranslator();
25
26 // If the application owns the surface, don't enable hardware acceleration
27 if (mSurfaceHolder == null) {
28 enableHardwareAcceleration(mView.getContext(), attrs);
29 }
30
31 boolean restore = false;
32 if (mTranslator != null) {
33 mSurface.setCompatibilityTranslator(mTranslator);
34 restore = true;
35 attrs.backup();
36 mTranslator.translateWindowLayout(attrs);
37 }
38 if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
39
40 if (!compatibilityInfo.supportsScreen()) {
41 attrs.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
42 mLastInCompatMode = true;
43 }
44
45 mSoftInputMode = attrs.softInputMode;
46 mWindowAttributesChanged = true;
47 mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED;
48 mAttachInfo.mRootView = view;
49 mAttachInfo.mScalingRequired = mTranslator != null;
50 mAttachInfo.mApplicationScale =
51 mTranslator == null ? 1.0f : mTranslator.applicationScale;
52 if (panelParentView != null) {
53 mAttachInfo.mPanelParentWindowToken
54 = panelParentView.getApplicationWindowToken();
55 }
56 mAdded = true;
57 int res; /* = WindowManagerImpl.ADD_OKAY; */
58
59 // Schedule the first layout -before- adding to the window
60 // manager, to make sure we do the relayout before receiving
61 // any other events from the system.
62 requestLayout();
63 if ((mWindowAttributes.inputFeatures
64 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
65 mInputChannel = new InputChannel();
66 }
67 try {
68 mOrigWindowType = mWindowAttributes.type;
69 mAttachInfo.mRecomputeGlobalAttributes = true;
70 collectViewAttributes();
71 res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
72 getHostVisibility(), mDisplay.getDisplayId(),
73 mAttachInfo.mContentInsets, mInputChannel);
74 } catch (RemoteException e) {
75 mAdded = false;
76 mView = null;
77 mAttachInfo.mRootView = null;
78 mInputChannel = null;
79 mFallbackEventHandler.setView(null);
80 unscheduleTraversals();
81 setAccessibilityFocus(null, null);
82 throw new RuntimeException("Adding window failed", e);
83 } finally {
84 if (restore) {
85 attrs.restore();
86 }
87 }
88
89 if (mTranslator != null) {
90 mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
91 }
92 mPendingContentInsets.set(mAttachInfo.mContentInsets);
93 mPendingVisibleInsets.set(0, 0, 0, 0);
94 if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow);
95 if (res < WindowManagerGlobal.ADD_OKAY) {
96 mAttachInfo.mRootView = null;
97 mAdded = false;
98 mFallbackEventHandler.setView(null);
99 unscheduleTraversals();
100 setAccessibilityFocus(null, null);
101 switch (res) {
102 case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
103 case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
104 throw new WindowManager.BadTokenException(
105 "Unable to add window -- token " + attrs.token
106 + " is not valid; is your activity running?");
107 case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
108 throw new WindowManager.BadTokenException(
109 "Unable to add window -- token " + attrs.token
110 + " is not for an application");
111 case WindowManagerGlobal.ADD_APP_EXITING:
112 throw new WindowManager.BadTokenException(
113 "Unable to add window -- app for token " + attrs.token
114 + " is exiting");
115 case WindowManagerGlobal.ADD_DUPLICATE_ADD:
116 throw new WindowManager.BadTokenException(
117 "Unable to add window -- window " + mWindow
118 + " has already been added");
119 case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
120 // Silently ignore -- we would have just removed it
121 // right away, anyway.
122 return;
123 case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
124 throw new WindowManager.BadTokenException(
125 "Unable to add window " + mWindow +
126 " -- another window of this type already exists");
127 case WindowManagerGlobal.ADD_PERMISSION_DENIED:
128 throw new WindowManager.BadTokenException(
129 "Unable to add window " + mWindow +
130 " -- permission denied for this window type");
131 case WindowManagerGlobal.ADD_INVALID_DISPLAY:
132 throw new WindowManager.InvalidDisplayException(
133 "Unable to add window " + mWindow +
134 " -- the specified display can not be found");
135 }
136 throw new RuntimeException(
137 "Unable to add window -- unknown error code " + res);
138 }
139
140 if (view instanceof RootViewSurfaceTaker) {
141 mInputQueueCallback =
142 ((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
143 }
144 if (mInputChannel != null) {
145 if (mInputQueueCallback != null) {
146 mInputQueue = new InputQueue(mInputChannel);
147 mInputQueueCallback.onInputQueueCreated(mInputQueue);
148 } else {
149 mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
150 Looper.myLooper());
151 }
152 }
153
154 view.assignParent(this);
155 mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
156 mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;
157
158 if (mAccessibilityManager.isEnabled()) {
159 mAccessibilityInteractionConnectionManager.ensureConnection();
160 }
161
162 if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
163 view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
164 }
165 }
166 }
167 }
第71-73行(ViewRootImpl->setView)会调用Session的addToDisplay函数将参数mWindow传递给WindowManagerService服务, 关于addToDisplay函数的详细分析可以参考page10文件.
page10
我们来看一下Session的addToDisplay函数的实现:
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets,
InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outInputChannel);
}
Session的addToDisplay函数只是简单地调用WindowManagerService的addWindow函数, WindowManagerService的addWindow函数的定义如下:
1 public int addWindow(Session session, IWindow client, int seq,
2 WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
3 Rect outContentInsets, InputChannel outInputChannel) {
4 int res = mPolicy.checkAddPermission(attrs);
5 if (res != WindowManagerGlobal.ADD_OKAY) {
6 return res;
7 }
8
9 boolean reportNewConfig = false;
10 WindowState attachedWindow = null;
11 WindowState win = null;
12 long origId;
13 final int type = attrs.type;
14
15 synchronized(mWindowMap) {
16 if (!mDisplayReady) {
17 throw new IllegalStateException("Display has not been initialialized");
18 }
19
20 final DisplayContent displayContent = getDisplayContentLocked(displayId);
21 if (displayContent == null) {
22 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
23 }
24
25 if (mWindowMap.containsKey(client.asBinder())) {
26 Slog.w(TAG, "Window " + client + " is already added");
27 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
28 }
29
30 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
31 attachedWindow = windowForClientLocked(null, attrs.token, false);
32 if (attachedWindow == null) {
33 Slog.w(TAG, "Attempted to add window with token that is not a window: "
34 + attrs.token + ". Aborting.");
35 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
36 }
37 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
38 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
39 Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
40 + attrs.token + ". Aborting.");
41 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
42 }
43 }
44
45 boolean addToken = false;
46 WindowToken token = mTokenMap.get(attrs.token);
47 if (token == null) {
48 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
49 Slog.w(TAG, "Attempted to add application window with unknown token "
50 + attrs.token + ". Aborting.");
51 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
52 }
53 if (type == TYPE_INPUT_METHOD) {
54 Slog.w(TAG, "Attempted to add input method window with unknown token "
55 + attrs.token + ". Aborting.");
56 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
57 }
58 if (type == TYPE_WALLPAPER) {
59 Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
60 + attrs.token + ". Aborting.");
61 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
62 }
63 if (type == TYPE_DREAM) {
64 Slog.w(TAG, "Attempted to add Dream window with unknown token "
65 + attrs.token + ". Aborting.");
66 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
67 }
68 token = new WindowToken(this, attrs.token, -1, false);
69 addToken = true;
70 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
71 AppWindowToken atoken = token.appWindowToken;
72 if (atoken == null) {
73 Slog.w(TAG, "Attempted to add window with non-application token "
74 + token + ". Aborting.");
75 return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
76 } else if (atoken.removed) {
77 Slog.w(TAG, "Attempted to add window with exiting application token "
78 + token + ". Aborting.");
79 return WindowManagerGlobal.ADD_APP_EXITING;
80 }
81 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
82 // No need for this guy!
83 if (localLOGV) Slog.v(
84 TAG, "**** NO NEED TO START: " + attrs.getTitle());
85 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
86 }
87 } else if (type == TYPE_INPUT_METHOD) {
88 if (token.windowType != TYPE_INPUT_METHOD) {
89 Slog.w(TAG, "Attempted to add input method window with bad token "
90 + attrs.token + ". Aborting.");
91 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
92 }
93 } else if (type == TYPE_WALLPAPER) {
94 if (token.windowType != TYPE_WALLPAPER) {
95 Slog.w(TAG, "Attempted to add wallpaper window with bad token "
96 + attrs.token + ". Aborting.");
97 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
98 }
99 } else if (type == TYPE_DREAM) {
100 if (token.windowType != TYPE_DREAM) {
101 Slog.w(TAG, "Attempted to add Dream window with bad token "
102 + attrs.token + ". Aborting.");
103 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
104 }
105 }
106
107 win = new WindowState(this, session, client, token,
108 attachedWindow, seq, attrs, viewVisibility, displayContent);
109 if (win.mDeathRecipient == null) {
110 // Client has apparently died, so there is no reason to
111 // continue.
112 Slog.w(TAG, "Adding window client " + client.asBinder()
113 + " that is dead, aborting.");
114 return WindowManagerGlobal.ADD_APP_EXITING;
115 }
116
117 mPolicy.adjustWindowParamsLw(win.mAttrs);
118 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
119
120 res = mPolicy.prepareAddWindowLw(win, attrs);
121 if (res != WindowManagerGlobal.ADD_OKAY) {
122 return res;
123 }
124
125 if (outInputChannel != null && (attrs.inputFeatures
126 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
127 String name = win.makeInputChannelName();
128 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
129 win.setInputChannel(inputChannels[0]);
130 inputChannels[1].transferTo(outInputChannel);
131
132 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
133 }
134
135 // From now on, no exceptions or errors allowed!
136
137 res = WindowManagerGlobal.ADD_OKAY;
138
139 origId = Binder.clearCallingIdentity();
140
141 if (addToken) {
142 mTokenMap.put(attrs.token, token);
143 }
144 win.attach();
145 mWindowMap.put(client.asBinder(), win);
146
147 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
148 token.appWindowToken.startingWindow = win;
149 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
150 + " startingWindow=" + win);
151 }
152
153 boolean imMayMove = true;
154
155 if (type == TYPE_INPUT_METHOD) {
156 win.mGivenInsetsPending = true;
157 mInputMethodWindow = win;
158 addInputMethodWindowToListLocked(win);
159 imMayMove = false;
160 } else if (type == TYPE_INPUT_METHOD_DIALOG) {
161 mInputMethodDialogs.add(win);
162 addWindowToListInOrderLocked(win, true);
163 adjustInputMethodDialogsLocked();
164 imMayMove = false;
165 } else {
166 addWindowToListInOrderLocked(win, true);
167 if (type == TYPE_WALLPAPER) {
168 mLastWallpaperTimeoutTime = 0;
169 adjustWallpaperWindowsLocked();
170 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
171 adjustWallpaperWindowsLocked();
172 } else if (mWallpaperTarget != null
173 && mWallpaperTarget.mLayer >= win.mBaseLayer) {
174 // If there is currently a wallpaper being shown, and
175 // the base layer of the new window is below the current
176 // layer of the target window, then adjust the wallpaper.
177 // This is to avoid a new window being placed between the
178 // wallpaper and its target.
179 adjustWallpaperWindowsLocked();
180 }
181 }
182
183 win.mWinAnimator.mEnterAnimationPending = true;
184
185 if (displayContent.isDefaultDisplay) {
186 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
187 } else {
188 outContentInsets.setEmpty();
189 }
190
191 if (mInTouchMode) {
192 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
193 }
194 if (win.mAppToken == null || !win.mAppToken.clientHidden) {
195 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
196 }
197
198 mInputMonitor.setUpdateInputWindowsNeededLw();
199
200 boolean focusChanged = false;
201 if (win.canReceiveKeys()) {
202 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
203 false /*updateInputWindows*/);
204 if (focusChanged) {
205 imMayMove = false;
206 }
207 }
208
209 if (imMayMove) {
210 moveInputMethodWindowsIfNeededLocked(false);
211 }
212
213 assignLayersLocked(displayContent.getWindowList());
214 // Don't do layout here, the window must call
215 // relayout to be displayed, so we'll do it there.
216
217 //dump();
218
219 if (focusChanged) {
220 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
221 }
222 mInputMonitor.updateInputWindowsLw(false /*force*/);
223
224 if (localLOGV) Slog.v(
225 TAG, "New client " + client.asBinder()
226 + ": window=" + win);
227
228 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
229 reportNewConfig = true;
230 }
231 }
232
233 if (reportNewConfig) {
234 sendNewConfiguration();
235 }
236
237 Binder.restoreCallingIdentity(origId);
238
239 return res;
240 }
第15行(WindowManagerService->addWindow)会在mWindowMap上加锁, 保护对mWindowMap的访问. mWindowMap的定义如下:
final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
第20-23行(WindowManagerService->addWindow)会调用getDisplayContentLocked来获得显示设备的信息, 如果得到的DisplayContent为null, 就会抛出一个异常. 关于getDisplayContentLocked函数的详细分析可以参考page11文件.
第25-28行(WindowManagerService->addWindow)会判断是否已经为该Activity创建过WindowState了. 如果已经存在WindowState了, 就会抛出ADD_DUPLICATE_ADD错误
第30-43行(WindowManagerService->addWindow)会发现要add的window是一个attachedWindow的话, 会判断父Window是否存在并且不能也是一个attachedWindow
第46行(WindowManagerService->addWindow)会查找是否已经存在WindowToken, 传入的参数是WindowManager.LayoutParams的token成员.
WindowManager.LayoutParams类的定义如下:
public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable
哇塞, WindowManager.LayoutParams继承了ViewGroup.LayoutParams.
第47-69行(WindowManagerService->addWindow)是发现没有WindowToken的情况下, 会首先在第48-67行(WindowManagerService->addWindow)根据type判断是否是处于一种错误状态, 并返回错误码.如果不是错误的type, 就会在第68行(WindowManagerService->addWindow)构造一个WindowToken对象.
第70-86行(WindowManagerService->addWindow)是处理是AppWindowToken的情况下, 会做一些错误状态的检查.
第87-92行(WindowManagerService->addWindow)是处理类型为输入法的WindowToken
第93-105行(WindowManagerService->addWindow)是处理壁纸和Dream的WindowToken.
第107-108行(WindowManagerService->addWindow)会构造一个WindowState对象, 关于WindowState的创建过程的详细分析可以参考page12文件.
第144行(WindowManagerService->addWindow)会调用WindowState的attach函数, 关于WindowState的attach函数的详细分析可以参考page13文件.
WindowManagerGlobal的getWindowSession函数的定义如下:
1 public static IWindowSession getWindowSession(Looper mainLooper) {
2 synchronized (WindowManagerGlobal.class) {
3 if (sWindowSession == null) {
4 try {
5 InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
6 IWindowManager windowManager = getWindowManagerService();
7 sWindowSession = windowManager.openSession(
8 imm.getClient(), imm.getInputContext());
9 float animatorScale = windowManager.getAnimationScale(2);
10 ValueAnimator.setDurationScale(animatorScale);
11 } catch (RemoteException e) {
12 Log.e(TAG, "Failed to open window session", e);
13 }
14 }
15 return sWindowSession;
16 }
17 }
第2行(WindowManagerGlobal->getWindowSession)会在WindowManagerGlobal上加锁,
sWindowSession是个static的成员变量, 定义如下:
private static IWindowSession sWindowSession;
第6行(WindowManagerGlobal->getWindowSession)会调用getWindowManagerService获得WindowManagerService服务.
第7-8行(WindowManagerGlobal->getWindowSession)会调用WindowManagerService服务的openSession函数, 这也就标志着和WindowManagerService建立了链接.关于WindowManagerService的openSession函数的分析可以参考page7文件.
第9-10行(WindowManagerGlobal->getWindowSession)会得到windowManager的动画放大的参数
page7
WindowManagerService的openSession函数的定义如下:
1 public IWindowSession openSession(IInputMethodClient client,
2 IInputContext inputContext) {
3 if (client == null) throw new IllegalArgumentException("null client");
4 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
5 Session session = new Session(this, client, inputContext);
6 return session;
7 }
第3-4行(WindowManagerService->openSession)判断传入的参数是否为空, 如果为空则会抛出异常.
第5行(WindowManagerService->openSession)会构造一个Session对象, 并返回该对象. 关于Session对象的构造过程可以参考page8文件.
page8
在这篇文章里我们分析一下Session对象的创建过程.
Session类的定义如下:
final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient
Session继承自IWindowSession.Stub,由此可见Session是一个Binder本地对象, 可以利用Binder机制在进程间传输. Session的构造函数的定义如下:
1 public Session(WindowManagerService service, IInputMethodClient client,
2 IInputContext inputContext) {
3 mService = service;
4 mClient = client;
5 mInputContext = inputContext;
6 mUid = Binder.getCallingUid();
7 mPid = Binder.getCallingPid();
8 StringBuilder sb = new StringBuilder();
9 sb.append("Session{");
10 sb.append(Integer.toHexString(System.identityHashCode(this)));
11 sb.append(" ");
12 sb.append(mPid);
13 if (mUid < Process.FIRST_APPLICATION_UID) {
14 sb.append(":");
15 sb.append(mUid);
16 } else {
17 sb.append(":u");
18 sb.append(UserHandle.getUserId(mUid));
19 sb.append('a');
20 sb.append(UserHandle.getAppId(mUid));
21 }
22 sb.append("}");
23 mStringName = sb.toString();
24
25 synchronized (mService.mWindowMap) {
26 if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
27 IBinder b = ServiceManager.getService(
28 Context.INPUT_METHOD_SERVICE);
29 mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
30 }
31 }
32 long ident = Binder.clearCallingIdentity();
33 try {
34 // Note: it is safe to call in to the input method manager
35 // here because we are not holding our lock.
36 if (mService.mInputMethodManager != null) {
37 mService.mInputMethodManager.addClient(client, inputContext,
38 mUid, mPid);
39 } else {
40 client.setUsingInputMethod(false);
41 }
42 client.asBinder().linkToDeath(this, 0);
43 } catch (RemoteException e) {
44 // The caller has died, so we can just forget about this.
45 try {
46 if (mService.mInputMethodManager != null) {
47 mService.mInputMethodManager.removeClient(client);
48 }
49 } catch (RemoteException ee) {
50 }
51 } finally {
52 Binder.restoreCallingIdentity(ident);
53 }
54 }
第25-31行(Session->Session)会确保WindowManagerService中INPUT_METHOD_SERVICE的服务.
第36-41行(Session->Session)会将IInputMethodClient传给mInputMethodManager去
第42行(Session->Session)会加入Binder死亡通知
page9
应用程序进程将一个Activity组件的视图对象设置到与它所关联的一个ViewRoot对象的内部的时候, 就会将一个实现了IWindow接口的Binder本地对象传递给WindowManagerService服务.
这个实现了IWindow接口的Binder本地对象唯一地识别了一个Activity组件, 当WindowManagerService服务接受到这个Binder本地对象之后, 就会为它创建一个WindowState对象, 这样WindowManagerService服务以后就可以通过它来和Activity组件通信, 以便可以要求Activity组件配合来管理系系统中的所有窗口.
在ViewRoot创建的过程中, 会创建一个W类型的对象, 并赋值给ViewRoot的成员变量mWindow.
我们先来看一下W类的创建过程, W类的定义如下, W类是ViewRootImpl类的一个内部类:
static class W extends IWindow.Stub
W类的构造函数的定义如下:
W(ViewRootImpl viewAncestor) {
mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
mWindowSession = viewAncestor.mWindowSession;
}
由此可见, 在W类的内部也拿着WindowSession对象.
我们以ViewRootImpl类的setView函数作为入口来分析Activity组件与WindowManagerService服务的连接过程, 即一个WindowState对象的创建过程.
1 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
2 synchronized (this) {
3 if (mView == null) {
4 mView = view;
5 mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
6 mFallbackEventHandler.setView(view);
7 mWindowAttributes.copyFrom(attrs);
8 attrs = mWindowAttributes;
9 // Keep track of the actual window flags supplied by the client.
10 mClientWindowLayoutFlags = attrs.flags;
11
12 setAccessibilityFocus(null, null);
13
14 if (view instanceof RootViewSurfaceTaker) {
15 mSurfaceHolderCallback =
16 ((RootViewSurfaceTaker)view).willYouTakeTheSurface();
17 if (mSurfaceHolderCallback != null) {
18 mSurfaceHolder = new TakenSurfaceHolder();
19 mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
20 }
21 }
22
23 CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
24 mTranslator = compatibilityInfo.getTranslator();
25
26 // If the application owns the surface, don't enable hardware acceleration
27 if (mSurfaceHolder == null) {
28 enableHardwareAcceleration(mView.getContext(), attrs);
29 }
30
31 boolean restore = false;
32 if (mTranslator != null) {
33 mSurface.setCompatibilityTranslator(mTranslator);
34 restore = true;
35 attrs.backup();
36 mTranslator.translateWindowLayout(attrs);
37 }
38 if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
39
40 if (!compatibilityInfo.supportsScreen()) {
41 attrs.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
42 mLastInCompatMode = true;
43 }
44
45 mSoftInputMode = attrs.softInputMode;
46 mWindowAttributesChanged = true;
47 mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED;
48 mAttachInfo.mRootView = view;
49 mAttachInfo.mScalingRequired = mTranslator != null;
50 mAttachInfo.mApplicationScale =
51 mTranslator == null ? 1.0f : mTranslator.applicationScale;
52 if (panelParentView != null) {
53 mAttachInfo.mPanelParentWindowToken
54 = panelParentView.getApplicationWindowToken();
55 }
56 mAdded = true;
57 int res; /* = WindowManagerImpl.ADD_OKAY; */
58
59 // Schedule the first layout -before- adding to the window
60 // manager, to make sure we do the relayout before receiving
61 // any other events from the system.
62 requestLayout();
63 if ((mWindowAttributes.inputFeatures
64 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
65 mInputChannel = new InputChannel();
66 }
67 try {
68 mOrigWindowType = mWindowAttributes.type;
69 mAttachInfo.mRecomputeGlobalAttributes = true;
70 collectViewAttributes();
71 res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
72 getHostVisibility(), mDisplay.getDisplayId(),
73 mAttachInfo.mContentInsets, mInputChannel);
74 } catch (RemoteException e) {
75 mAdded = false;
76 mView = null;
77 mAttachInfo.mRootView = null;
78 mInputChannel = null;
79 mFallbackEventHandler.setView(null);
80 unscheduleTraversals();
81 setAccessibilityFocus(null, null);
82 throw new RuntimeException("Adding window failed", e);
83 } finally {
84 if (restore) {
85 attrs.restore();
86 }
87 }
88
89 if (mTranslator != null) {
90 mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
91 }
92 mPendingContentInsets.set(mAttachInfo.mContentInsets);
93 mPendingVisibleInsets.set(0, 0, 0, 0);
94 if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow);
95 if (res < WindowManagerGlobal.ADD_OKAY) {
96 mAttachInfo.mRootView = null;
97 mAdded = false;
98 mFallbackEventHandler.setView(null);
99 unscheduleTraversals();
100 setAccessibilityFocus(null, null);
101 switch (res) {
102 case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
103 case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
104 throw new WindowManager.BadTokenException(
105 "Unable to add window -- token " + attrs.token
106 + " is not valid; is your activity running?");
107 case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
108 throw new WindowManager.BadTokenException(
109 "Unable to add window -- token " + attrs.token
110 + " is not for an application");
111 case WindowManagerGlobal.ADD_APP_EXITING:
112 throw new WindowManager.BadTokenException(
113 "Unable to add window -- app for token " + attrs.token
114 + " is exiting");
115 case WindowManagerGlobal.ADD_DUPLICATE_ADD:
116 throw new WindowManager.BadTokenException(
117 "Unable to add window -- window " + mWindow
118 + " has already been added");
119 case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
120 // Silently ignore -- we would have just removed it
121 // right away, anyway.
122 return;
123 case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
124 throw new WindowManager.BadTokenException(
125 "Unable to add window " + mWindow +
126 " -- another window of this type already exists");
127 case WindowManagerGlobal.ADD_PERMISSION_DENIED:
128 throw new WindowManager.BadTokenException(
129 "Unable to add window " + mWindow +
130 " -- permission denied for this window type");
131 case WindowManagerGlobal.ADD_INVALID_DISPLAY:
132 throw new WindowManager.InvalidDisplayException(
133 "Unable to add window " + mWindow +
134 " -- the specified display can not be found");
135 }
136 throw new RuntimeException(
137 "Unable to add window -- unknown error code " + res);
138 }
139
140 if (view instanceof RootViewSurfaceTaker) {
141 mInputQueueCallback =
142 ((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
143 }
144 if (mInputChannel != null) {
145 if (mInputQueueCallback != null) {
146 mInputQueue = new InputQueue(mInputChannel);
147 mInputQueueCallback.onInputQueueCreated(mInputQueue);
148 } else {
149 mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
150 Looper.myLooper());
151 }
152 }
153
154 view.assignParent(this);
155 mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
156 mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;
157
158 if (mAccessibilityManager.isEnabled()) {
159 mAccessibilityInteractionConnectionManager.ensureConnection();
160 }
161
162 if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
163 view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
164 }
165 }
166 }
167 }
第71-73行(ViewRootImpl->setView)会调用Session的addToDisplay函数将参数mWindow传递给WindowManagerService服务, 关于addToDisplay函数的详细分析可以参考page10文件.
page10
我们来看一下Session的addToDisplay函数的实现:
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets,
InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outInputChannel);
}
Session的addToDisplay函数只是简单地调用WindowManagerService的addWindow函数, WindowManagerService的addWindow函数的定义如下:
1 public int addWindow(Session session, IWindow client, int seq,
2 WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
3 Rect outContentInsets, InputChannel outInputChannel) {
4 int res = mPolicy.checkAddPermission(attrs);
5 if (res != WindowManagerGlobal.ADD_OKAY) {
6 return res;
7 }
8
9 boolean reportNewConfig = false;
10 WindowState attachedWindow = null;
11 WindowState win = null;
12 long origId;
13 final int type = attrs.type;
14
15 synchronized(mWindowMap) {
16 if (!mDisplayReady) {
17 throw new IllegalStateException("Display has not been initialialized");
18 }
19
20 final DisplayContent displayContent = getDisplayContentLocked(displayId);
21 if (displayContent == null) {
22 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
23 }
24
25 if (mWindowMap.containsKey(client.asBinder())) {
26 Slog.w(TAG, "Window " + client + " is already added");
27 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
28 }
29
30 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
31 attachedWindow = windowForClientLocked(null, attrs.token, false);
32 if (attachedWindow == null) {
33 Slog.w(TAG, "Attempted to add window with token that is not a window: "
34 + attrs.token + ". Aborting.");
35 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
36 }
37 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
38 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
39 Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
40 + attrs.token + ". Aborting.");
41 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
42 }
43 }
44
45 boolean addToken = false;
46 WindowToken token = mTokenMap.get(attrs.token);
47 if (token == null) {
48 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
49 Slog.w(TAG, "Attempted to add application window with unknown token "
50 + attrs.token + ". Aborting.");
51 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
52 }
53 if (type == TYPE_INPUT_METHOD) {
54 Slog.w(TAG, "Attempted to add input method window with unknown token "
55 + attrs.token + ". Aborting.");
56 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
57 }
58 if (type == TYPE_WALLPAPER) {
59 Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
60 + attrs.token + ". Aborting.");
61 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
62 }
63 if (type == TYPE_DREAM) {
64 Slog.w(TAG, "Attempted to add Dream window with unknown token "
65 + attrs.token + ". Aborting.");
66 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
67 }
68 token = new WindowToken(this, attrs.token, -1, false);
69 addToken = true;
70 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
71 AppWindowToken atoken = token.appWindowToken;
72 if (atoken == null) {
73 Slog.w(TAG, "Attempted to add window with non-application token "
74 + token + ". Aborting.");
75 return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
76 } else if (atoken.removed) {
77 Slog.w(TAG, "Attempted to add window with exiting application token "
78 + token + ". Aborting.");
79 return WindowManagerGlobal.ADD_APP_EXITING;
80 }
81 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
82 // No need for this guy!
83 if (localLOGV) Slog.v(
84 TAG, "**** NO NEED TO START: " + attrs.getTitle());
85 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
86 }
87 } else if (type == TYPE_INPUT_METHOD) {
88 if (token.windowType != TYPE_INPUT_METHOD) {
89 Slog.w(TAG, "Attempted to add input method window with bad token "
90 + attrs.token + ". Aborting.");
91 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
92 }
93 } else if (type == TYPE_WALLPAPER) {
94 if (token.windowType != TYPE_WALLPAPER) {
95 Slog.w(TAG, "Attempted to add wallpaper window with bad token "
96 + attrs.token + ". Aborting.");
97 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
98 }
99 } else if (type == TYPE_DREAM) {
100 if (token.windowType != TYPE_DREAM) {
101 Slog.w(TAG, "Attempted to add Dream window with bad token "
102 + attrs.token + ". Aborting.");
103 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
104 }
105 }
106
107 win = new WindowState(this, session, client, token,
108 attachedWindow, seq, attrs, viewVisibility, displayContent);
109 if (win.mDeathRecipient == null) {
110 // Client has apparently died, so there is no reason to
111 // continue.
112 Slog.w(TAG, "Adding window client " + client.asBinder()
113 + " that is dead, aborting.");
114 return WindowManagerGlobal.ADD_APP_EXITING;
115 }
116
117 mPolicy.adjustWindowParamsLw(win.mAttrs);
118 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
119
120 res = mPolicy.prepareAddWindowLw(win, attrs);
121 if (res != WindowManagerGlobal.ADD_OKAY) {
122 return res;
123 }
124
125 if (outInputChannel != null && (attrs.inputFeatures
126 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
127 String name = win.makeInputChannelName();
128 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
129 win.setInputChannel(inputChannels[0]);
130 inputChannels[1].transferTo(outInputChannel);
131
132 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
133 }
134
135 // From now on, no exceptions or errors allowed!
136
137 res = WindowManagerGlobal.ADD_OKAY;
138
139 origId = Binder.clearCallingIdentity();
140
141 if (addToken) {
142 mTokenMap.put(attrs.token, token);
143 }
144 win.attach();
145 mWindowMap.put(client.asBinder(), win);
146
147 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
148 token.appWindowToken.startingWindow = win;
149 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
150 + " startingWindow=" + win);
151 }
152
153 boolean imMayMove = true;
154
155 if (type == TYPE_INPUT_METHOD) {
156 win.mGivenInsetsPending = true;
157 mInputMethodWindow = win;
158 addInputMethodWindowToListLocked(win);
159 imMayMove = false;
160 } else if (type == TYPE_INPUT_METHOD_DIALOG) {
161 mInputMethodDialogs.add(win);
162 addWindowToListInOrderLocked(win, true);
163 adjustInputMethodDialogsLocked();
164 imMayMove = false;
165 } else {
166 addWindowToListInOrderLocked(win, true);
167 if (type == TYPE_WALLPAPER) {
168 mLastWallpaperTimeoutTime = 0;
169 adjustWallpaperWindowsLocked();
170 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
171 adjustWallpaperWindowsLocked();
172 } else if (mWallpaperTarget != null
173 && mWallpaperTarget.mLayer >= win.mBaseLayer) {
174 // If there is currently a wallpaper being shown, and
175 // the base layer of the new window is below the current
176 // layer of the target window, then adjust the wallpaper.
177 // This is to avoid a new window being placed between the
178 // wallpaper and its target.
179 adjustWallpaperWindowsLocked();
180 }
181 }
182
183 win.mWinAnimator.mEnterAnimationPending = true;
184
185 if (displayContent.isDefaultDisplay) {
186 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
187 } else {
188 outContentInsets.setEmpty();
189 }
190
191 if (mInTouchMode) {
192 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
193 }
194 if (win.mAppToken == null || !win.mAppToken.clientHidden) {
195 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
196 }
197
198 mInputMonitor.setUpdateInputWindowsNeededLw();
199
200 boolean focusChanged = false;
201 if (win.canReceiveKeys()) {
202 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
203 false /*updateInputWindows*/);
204 if (focusChanged) {
205 imMayMove = false;
206 }
207 }
208
209 if (imMayMove) {
210 moveInputMethodWindowsIfNeededLocked(false);
211 }
212
213 assignLayersLocked(displayContent.getWindowList());
214 // Don't do layout here, the window must call
215 // relayout to be displayed, so we'll do it there.
216
217 //dump();
218
219 if (focusChanged) {
220 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
221 }
222 mInputMonitor.updateInputWindowsLw(false /*force*/);
223
224 if (localLOGV) Slog.v(
225 TAG, "New client " + client.asBinder()
226 + ": window=" + win);
227
228 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
229 reportNewConfig = true;
230 }
231 }
232
233 if (reportNewConfig) {
234 sendNewConfiguration();
235 }
236
237 Binder.restoreCallingIdentity(origId);
238
239 return res;
240 }
第15行(WindowManagerService->addWindow)会在mWindowMap上加锁, 保护对mWindowMap的访问. mWindowMap的定义如下:
final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
第20-23行(WindowManagerService->addWindow)会调用getDisplayContentLocked来获得显示设备的信息, 如果得到的DisplayContent为null, 就会抛出一个异常. 关于getDisplayContentLocked函数的详细分析可以参考page11文件.
第25-28行(WindowManagerService->addWindow)会判断是否已经为该Activity创建过WindowState了. 如果已经存在WindowState了, 就会抛出ADD_DUPLICATE_ADD错误
第30-43行(WindowManagerService->addWindow)会发现要add的window是一个attachedWindow的话, 会判断父Window是否存在并且不能也是一个attachedWindow
第46行(WindowManagerService->addWindow)会查找是否已经存在WindowToken, 传入的参数是WindowManager.LayoutParams的token成员.
WindowManager.LayoutParams类的定义如下:
public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable
哇塞, WindowManager.LayoutParams继承了ViewGroup.LayoutParams.
第47-69行(WindowManagerService->addWindow)是发现没有WindowToken的情况下, 会首先在第48-67行(WindowManagerService->addWindow)根据type判断是否是处于一种错误状态, 并返回错误码.如果不是错误的type, 就会在第68行(WindowManagerService->addWindow)构造一个WindowToken对象.
第70-86行(WindowManagerService->addWindow)是处理是AppWindowToken的情况下, 会做一些错误状态的检查.
第87-92行(WindowManagerService->addWindow)是处理类型为输入法的WindowToken
第93-105行(WindowManagerService->addWindow)是处理壁纸和Dream的WindowToken.
第107-108行(WindowManagerService->addWindow)会构造一个WindowState对象, 关于WindowState的创建过程的详细分析可以参考page12文件.
第144行(WindowManagerService->addWindow)会调用WindowState的attach函数, 关于WindowState的attach函数的详细分析可以参考page13文件.
发表评论
-
Activity与WindowManagerService连接的过程(三)
2018-04-16 16:27 623page11 WindowManagerService ... -
Activity与WindowManagerService连接的过程(一)
2018-04-16 16:21 987page1 Activity组件在 ... -
Activity的ViewRoot的创建过程(三)
2017-11-06 14:25 742page7 在这篇文章里, 我们分析一下W类的构造过程. W ... -
Activity的ViewRoot的创建过程(二)
2017-11-06 14:29 942page4 我们看一下ViewRootImpl对象的创 ... -
Activity的ViewRoot的创建过程(一)
2017-11-06 14:27 1080page1 当一个Activity第一次激活的时候会为该Ac ... -
Activity的Window和WindowManager的创建过程(三)
2017-07-05 11:49 1335page9 在这里我们分析一下DisplayManager的 ... -
Activity的Window和WindowManager的创建过程(二)
2017-07-05 11:31 548page5 在这篇文章中, 我们分析一下ContextImp ... -
Activity的Window和WindowManager的创建过程(一)
2017-07-05 11:27 607page1 我们开始分析一下Activity的Window和 ... -
Acitivy创建Context的过程(二)
2017-06-21 14:11 514page4 在这里我们分析一下ContextImpl的ini ... -
Acitivy创建Context的过程(一)
2017-06-21 14:15 639page1 从本篇文章开始,我们分析一下Activity创建 ... -
应用程序进程与SurfaceFlinger的连接过程
2017-06-21 11:49 1063我们从SurfaceComposerClient对象的创建开始 ... -
Android源码之SurfaceFlinger的启动(三)
2017-04-20 11:09 1046page11 我们来看一下SurfaceFlinger ... -
Android源码之SurfaceFlinger的启动(二)
2017-04-18 15:15 883page6 我们看一下Thread的run函数的实现: ... -
Android源码之SurfaceFlinger的启动(一)
2017-04-17 10:07 1000page1 在Android系统中, 显示系统在底层是通过S ... -
Android源码之Zygote
2015-12-15 11:45 519当ActivityManagerService启动一个应用程序 ... -
Android源码之Binder(五)
2015-12-04 09:19 1515Service组件在启动时,需要将自己注册到Service M ... -
Android源码之Binder(四)
2015-12-04 09:18 1952case BINDER_SET_MAX_THREADS: ... -
Android源码之Binder(三)
2015-12-04 09:17 910{ int ret; struct binder_pr ... -
Android源码之Binder(二)
2015-12-04 09:15 550分析完Binder驱动程序的打开和内存分配的过程之后,我们看一 ... -
Android源码之Binder(一)
2015-12-04 09:12 996在Android系统中,进程间通信使用的是Binder机制。B ...
相关推荐
2. **GUI绘制流程**:当Activity与WindowManagerService成功建立连接后,ViewRoot将开始执行GUI的绘制过程。这一过程涉及到多个步骤,包括但不限于更新窗口状态、绘制视图层级以及最终的屏幕渲染。 #### 结论 View...
与WindowManagerService的连接过程是Activity将View添加到屏幕上的关键步骤。WindowManagerService是Android系统的系统服务,它负责管理所有的窗口,并处理窗口的显示和隐藏。 在绘制过程中,Android使用Surface来...
2. **Android服务启动**:SystemServer启动后,会依次启动一系列重要的Android服务,如`ActivityManagerService`、`WindowManagerService`、`PackageManagerService`等。 3. **Home应用启动**:一旦SystemServer及其...
Android的Framework层作为操作系统的核心组成部分,扮演着连接硬件抽象层(HAL)与应用程序之间的桥梁角色,它不仅提供了丰富的API供开发者调用,还负责管理和调度应用程序的生命周期。本章节深入探讨Android ...
- **IWindowManager与WindowManagerService的Binder通信**:了解IWindowManager与WindowManagerService之间的通信机制对于深入理解事件注入的过程至关重要。这两者通过Binder框架实现了跨进程调用,从而使得Monkey...
- **RIL接口:** RIL是连接上层应用与底层硬件的桥梁,Java层如何与RIL交互以完成通话操作。 - **RIL实例:** 通过具体的RIL实例来演示通话流程的具体实现。 **GSMCallTracker:** - **GSM呼叫跟踪:** ...
这个过程通常在Activity的创建过程中完成,通过调用`ViewRootImpl`的`createInputChannel`方法来创建InputChannel,然后将其注册到WMS,这样InputDispatcher就能识别并分发事件给该窗口。 3.1.2 WMS注册 在WMS中,...
2. **WindowManagerService (WMS)**:处理窗口管理,包括屏幕布局、显示和隐藏等操作。 3. **ViewSystem**:Android UI的基础,包含View和 ViewGroup,它们是如何绘制和交互的。 4. **Intent**:Android中应用间通信...
- WindowManagerService (WMS):管理窗口堆栈,负责显示WelcomeLauncher的界面。 - ContentProvider:如果WelcomeLauncher需要访问系统数据,可能会用到ContentProvider来共享数据。 4. **自定义与扩展**: - ...
4. **System Server**:这是一个核心服务进程,负责启动系统级的服务,如ActivityManagerService、WindowManagerService等。 5. **User Applications**:随着系统服务的启动,用户应用程序也开始运行。 #### 层间...
在Android系统的层次结构中,屏幕锁与`ActivityManagerService`、`WindowManagerService`等核心服务协同工作,确保系统在不同状态间的平滑切换。 通过分析`Android 屏幕锁源码`,我们可以学习到Android系统如何处理...
#### 二十二、Android应用框架之Activity - **Activity概述**:这部分内容概述了Activity组件的作用,它是Android应用中用户界面的基本单元。 - **生命周期管理**:详细分析了Activity的生命周期管理机制,包括不同...
**启动系统服务**:如ActivityManagerService、WindowManagerService、PackageManagerService等。 - **Start services:** - **ADBD(Android Debug Bridge Daemon)**:用于开发者通过命令行与设备进行通信,如...
在步骤3,`mWindowSession.addToDisplay()` 被调用,这个方法会将新视图添加到显示列表,并且将之前创建的InputChannel与服务端建立连接。`mWindowSession` 是一个IWindowSession接口的实现,它是由`...
1. 应用组件之间的通信,例如ActivityManagerService在应用程序启动时利用Binder与其他组件交互。 2. 系统服务的IPC通信,例如PackageManagerService、WindowManagerService等。 3. 应用程序和系统服务之间的通信...
Activity是Android应用中最基本的界面单元,也是用户与应用交互的主要界面。应用程序框架允许开发者在不重复编写相同代码的情况下,利用框架提供的服务和组件创建功能丰富的应用程序。 5. 图形显示机制分析:...
ViewRootImpl负责处理View的布局、绘制以及与WindowManagerService的通信。当我们调用Activity的`setContentView`方法时,实际上是通过Window来实现界面的设置。 总的来说,Window是Android UI体系的基础,...
`ViewRootImpl`是连接Android应用程序与系统服务`WindowManagerService`的关键类。每当一个新的View需要添加到Window时,就会创建一个`ViewRootImpl`实例。它负责处理视图的生命周期,包括设置视图、请求布局更新...