publicvoidaddView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { // 检查参数有无错误,如果是子 window 的话要调整一些参数 if (view == null) { thrownewIllegalArgumentException("view must not be null"); } if (display == null) { thrownewIllegalArgumentException("display must not be null"); } if (!(params instanceof WindowManager.LayoutParams)) { thrownewIllegalArgumentException("Params must be WindowManager.LayoutParams"); }
final WindowManager.LayoutParamswparams= (WindowManager.LayoutParams) params; if (parentWindow != null) { parentWindow.adjustLayoutParamsForSubWindow(wparams); } else { // If there's no parent, then hardware acceleration for this view is // set from the application's hardware acceleration setting. finalContextcontext= view.getContext(); if (context != null && (context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) { wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; } }
ViewRootImpl root; ViewpanelParentView=null;
synchronized (mLock) { // Start watching for system property changes. if (mSystemPropertyUpdater == null) { mSystemPropertyUpdater = newRunnable() { @Overridepublicvoidrun() { synchronized (mLock) { for (inti= mRoots.size() - 1; i >= 0; --i) { mRoots.get(i).loadSystemProperties(); } } } }; SystemProperties.addChangeCallback(mSystemPropertyUpdater); }
intindex= findViewLocked(view, false); if (index >= 0) { if (mDyingViews.contains(view)) { // Don't wait for MSG_DIE to make it's way through root's queue. mRoots.get(index).doDie(); } else { thrownewIllegalStateException("View " + view + " has already been added to the window manager."); } // The previous removeView() had not completed executing. Now it has. }
// If this is a panel window, then find the window it is being // attached to for future reference. if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { finalintcount= mViews.size(); for (inti=0; i < count; i++) { if (mRoots.get(i).mWindow.asBinder() == wparams.token) { panelParentView = mViews.get(i); } } } // 创建新的 viewrootimpl root = newViewRootImpl(view.getContext(), display);
// 检查 IPC 的结果,若不是 ADD_OKAY ,就说明添加 window 失败 if (res < WindowManagerGlobal.ADD_OKAY) { mAttachInfo.mRootView = null; mAdded = false; mFallbackEventHandler.setView(null); unscheduleTraversals(); setAccessibilityFocus(null, null); switch (res) { case WindowManagerGlobal.ADD_BAD_APP_TOKEN: case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN: thrownewWindowManager.BadTokenException( "Unable to add window -- token " + attrs.token + " is not valid; is your activity running?"); case WindowManagerGlobal.ADD_NOT_APP_TOKEN: thrownewWindowManager.BadTokenException( "Unable to add window -- token " + attrs.token + " is not for an application"); case WindowManagerGlobal.ADD_APP_EXITING: thrownewWindowManager.BadTokenException( "Unable to add window -- app for token " + attrs.token + " is exiting"); case WindowManagerGlobal.ADD_DUPLICATE_ADD: thrownewWindowManager.BadTokenException( "Unable to add window -- window " + mWindow + " has already been added"); case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED: // Silently ignore -- we would have just removed it // right away, anyway. return; case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON: thrownewWindowManager.BadTokenException("Unable to add window " + mWindow + " -- another window of type " + mWindowAttributes.type + " already exists"); case WindowManagerGlobal.ADD_PERMISSION_DENIED: thrownewWindowManager.BadTokenException("Unable to add window " + mWindow + " -- permission denied for window type " + mWindowAttributes.type); case WindowManagerGlobal.ADD_INVALID_DISPLAY: thrownewWindowManager.InvalidDisplayException("Unable to add window " + mWindow + " -- the specified display can not be found"); case WindowManagerGlobal.ADD_INVALID_TYPE: thrownewWindowManager.InvalidDisplayException("Unable to add window " + mWindow + " -- the specified window type " + mWindowAttributes.type + " is not valid"); } thrownewRuntimeException( "Unable to add window -- unknown error code " + res); }
在添加完成后,根据返回值 res 来判断添加 window 是否成功。若不是 WindowManagerGlobal.ADD_OKAY 则说明添加失败了,抛出对应的异常。
Session
addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel)
1 2 3 4 5 6 7
@Override publicintaddToDisplay(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); }
addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel)
// 校验 token 有效性, 如果 token 为空或不正确的话,那么直接返回 ADD_BAD_APP_TOKEN 等异常 if (token == null) { ... }elseif (...) { ... } elseif (token.appWindowToken != null) { Slog.w(TAG_WM, "Non-null appWindowToken for system window of type=" + type); // It is not valid to use an app token with other system types; we will // instead make a new token for it (as if null had been passed in for the token). attrs.token = null; token = newWindowToken(this, null, -1, false); addToken = true; }
res = mPolicy.prepareAddWindowLw(win, attrs); if (res != WindowManagerGlobal.ADD_OKAY) { return res; }
...
if (type == TYPE_INPUT_METHOD) { win.mGivenInsetsPending = true; mInputMethodWindow = win; addInputMethodWindowToListLocked(win); imMayMove = false; } elseif (type == TYPE_INPUT_METHOD_DIALOG) { mInputMethodDialogs.add(win); // 将新的 WindowState 按显示次序插入到当前 DisplayContent 的 mWindows 列表中 addWindowToListInOrderLocked(win, true); moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); imMayMove = false; } else { // 将新的 WindowState 按显示次序插入到当前 DisplayContent 的 mWindows 列表中 addWindowToListInOrderLocked(win, true); if (type == TYPE_WALLPAPER) { mWallpaperControllerLocked.clearLastWallpaperTimeoutTime(); displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; } elseif ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; } elseif (mWallpaperControllerLocked.isBelowWallpaperTarget(win)) { // If there is currently a wallpaper being shown, and // the base layer of the new window is below the current // layer of the target window, then adjust the wallpaper. // This is to avoid a new window being placed between the // wallpaper and its target. displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; } }