MyException - 我的异常网
当前位置:我的异常网» 移动开发 » Activity与WindowManagerService连接的进程(二)

Activity与WindowManagerService连接的进程(二)

www.MyException.Cn  网友分享于:2018-04-18  浏览:0次
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<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文件.

文章评论

漫画:程序员的工作
漫画:程序员的工作
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
程序员的鄙视链
程序员的鄙视链
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
鲜为人知的编程真相
鲜为人知的编程真相
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
每天工作4小时的程序员
每天工作4小时的程序员
旅行,写作,编程
旅行,写作,编程
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
我是如何打败拖延症的
我是如何打败拖延症的
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
代码女神横空出世
代码女神横空出世
我的丈夫是个程序员
我的丈夫是个程序员
程序员和编码员之间的区别
程序员和编码员之间的区别
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
 程序员的样子
程序员的样子
那些争议最大的编程观点
那些争议最大的编程观点
老程序员的下场
老程序员的下场
为什么程序员都是夜猫子
为什么程序员都是夜猫子
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
程序员都该阅读的书
程序员都该阅读的书
编程语言是女人
编程语言是女人
如何成为一名黑客
如何成为一名黑客
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
程序员应该关注的一些事儿
程序员应该关注的一些事儿
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
10个调试和排错的小建议
10个调试和排错的小建议
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
一个程序员的时间管理
一个程序员的时间管理
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
程序员必看的十大电影
程序员必看的十大电影
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有