`
zzu_007
  • 浏览: 23750 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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文件.

分享到:
评论

相关推荐

    联想 viewroot简介

    2. **GUI绘制流程**:当Activity与WindowManagerService成功建立连接后,ViewRoot将开始执行GUI的绘制过程。这一过程涉及到多个步骤,包括但不限于更新窗口状态、绘制视图层级以及最终的屏幕渲染。 #### 结论 View...

    Android应用程序窗口(Activity) · 老罗的Android之旅(总结) · 看云1

    与WindowManagerService的连接过程是Activity将View添加到屏幕上的关键步骤。WindowManagerService是Android系统的系统服务,它负责管理所有的窗口,并处理窗口的显示和隐藏。 在绘制过程中,Android使用Surface来...

    Android 启动过程详解

    2. **Android服务启动**:SystemServer启动后,会依次启动一系列重要的Android服务,如`ActivityManagerService`、`WindowManagerService`、`PackageManagerService`等。 3. **Home应用启动**:一旦SystemServer及其...

    Android核心剖析之Framework概述

    Android的Framework层作为操作系统的核心组成部分,扮演着连接硬件抽象层(HAL)与应用程序之间的桥梁角色,它不仅提供了丰富的API供开发者调用,还负责管理和调度应用程序的生命周期。本章节深入探讨Android ...

    Monkey源码分析

    - **IWindowManager与WindowManagerService的Binder通信**:了解IWindowManager与WindowManagerService之间的通信机制对于深入理解事件注入的过程至关重要。这两者通过Binder框架实现了跨进程调用,从而使得Monkey...

    Android核心分析(pdf)

    - **RIL接口:** RIL是连接上层应用与底层硬件的桥梁,Java层如何与RIL交互以完成通话操作。 - **RIL实例:** 通过具体的RIL实例来演示通话流程的具体实现。 **GSMCallTracker:** - **GSM呼叫跟踪:** ...

    android 客户进程的注册(2)

    这个过程通常在Activity的创建过程中完成,通过调用`ViewRootImpl`的`createInputChannel`方法来创建InputChannel,然后将其注册到WMS,这样InputDispatcher就能识别并分发事件给该窗口。 3.1.2 WMS注册 在WMS中,...

    本人自学Android技术

    2. **WindowManagerService (WMS)**:处理窗口管理,包括屏幕布局、显示和隐藏等操作。 3. **ViewSystem**:Android UI的基础,包含View和 ViewGroup,它们是如何绘制和交互的。 4. **Intent**:Android中应用间通信...

    安卓Android源码——WelcomeLauncher.rar

    - WindowManagerService (WMS):管理窗口堆栈,负责显示WelcomeLauncher的界面。 - ContentProvider:如果WelcomeLauncher需要访问系统数据,可能会用到ContentProvider来共享数据。 4. **自定义与扩展**: - ...

    Google Android Internal

    4. **System Server**:这是一个核心服务进程,负责启动系统级的服务,如ActivityManagerService、WindowManagerService等。 5. **User Applications**:随着系统服务的启动,用户应用程序也开始运行。 #### 层间...

    Android 屏幕锁源码

    在Android系统的层次结构中,屏幕锁与`ActivityManagerService`、`WindowManagerService`等核心服务协同工作,确保系统在不同状态间的平滑切换。 通过分析`Android 屏幕锁源码`,我们可以学习到Android系统如何处理...

    Android中级教程

    #### 二十二、Android应用框架之Activity - **Activity概述**:这部分内容概述了Activity组件的作用,它是Android应用中用户界面的基本单元。 - **生命周期管理**:详细分析了Activity的生命周期管理机制,包括不同...

    Android初始化流程简要分析.do

    **启动系统服务**:如ActivityManagerService、WindowManagerService、PackageManagerService等。 - **Start services:** - **ADBD(Android Debug Bridge Daemon)**:用于开发者通过命令行与设备进行通信,如...

    Android之Input子系统事件分发流程 - CSDN博客1

    在步骤3,`mWindowSession.addToDisplay()` 被调用,这个方法会将新视图添加到显示列表,并且将之前创建的InputChannel与服务端建立连接。`mWindowSession` 是一个IWindowSession接口的实现,它是由`...

    android binder架构

    1. 应用组件之间的通信,例如ActivityManagerService在应用程序启动时利用Binder与其他组件交互。 2. 系统服务的IPC通信,例如PackageManagerService、WindowManagerService等。 3. 应用程序和系统服务之间的通信...

    Android主要机制深入分析.pdf

    Activity是Android应用中最基本的界面单元,也是用户与应用交互的主要界面。应用程序框架允许开发者在不重复编写相同代码的情况下,利用框架提供的服务和组件创建功能丰富的应用程序。 5. 图形显示机制分析:...

    深入理解Android中的Window和WindowManager

    ViewRootImpl负责处理View的布局、绘制以及与WindowManagerService的通信。当我们调用Activity的`setContentView`方法时,实际上是通过Window来实现界面的设置。 总的来说,Window是Android UI体系的基础,...

    window和windowManager1

    `ViewRootImpl`是连接Android应用程序与系统服务`WindowManagerService`的关键类。每当一个新的View需要添加到Window时,就会创建一个`ViewRootImpl`实例。它负责处理视图的生命周期,包括设置视图、请求布局更新...

Global site tag (gtag.js) - Google Analytics