Activity与WindowManagerService连接的过程(二)

阅读更多
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(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 mWindowMap = new HashMap();
    第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文件.

你可能感兴趣的:(Android)