一、强制设置方向

1.Activity

如果要强制设置一个Activity的横竖屏可以通过Manifest去设置,跟Activity相关的信息都会保存在ActivityInfo当中。

  1. android:screenOrientation=["unspecified" | "user" | "behind" |
  2. "landscape" | "portrait" |
  3. "reverseLandscape" | "reversePortrait" |
  4. "sensorLandscape" | "sensorPortrait" |
  5. "sensor" | "fullSensor" | "nosensor"]

2.Window

如果是要强制设置一个Window的横竖屏可以通过 LayoutParams.screenOrientation来设置。在通过WindowManager.addView的时候把对应的LayoutParams传递给WMS。

WindowManager.LayoutParams.screenOrientation

二、屏幕转屏

2.1 Activity -- 启动一个有设置screenOrientation的Activity

在ActivityStack.startActivityLocked中,AMS会把ActivityRecord相关的Token加到WMS中,有且仅在这个方法中。这时候会把screenOrientation传递过去。

atoken.requestedOrientation = requestedOrientation; 这个AppToken会在WMS获取相关App Orientation的时候其作用。

  1. mService.mWindowManager.addAppToken(addPos, r.userId, r.appToken,
  2. r.task.taskId, r.info.screenOrientation, r.fullscreen,
  3. (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
  1. public void addAppToken(int addPos, int userId, IApplicationToken token,
  2. int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) {
  3. ... ...
  4. synchronized(mWindowMap) {
  5. AppWindowToken atoken = findAppWindowToken(token.asBinder());
  6. if (atoken != null) {
  7. Slog.w(TAG, "Attempted to add existing app token: " + token);
  8. return;
  9. }
  10. atoken = new AppWindowToken(this, userId, token);
  11. atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
  12. atoken.groupId = groupId;
  13. atoken.appFullscreen = fullscreen;
  14. atoken.showWhenLocked = showWhenLocked;
  15. atoken.requestedOrientation = requestedOrientation;//方向赋值
  16. if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
  17. + " at " + addPos);
  18. mAppTokens.add(addPos, atoken);
  19. addAppTokenToAnimating(addPos, atoken);
  20. mTokenMap.put(token.asBinder(), atoken);
  21.  
  22. // Application tokens start out hidden.
  23. atoken.hidden = true;
  24. atoken.hiddenRequested = true;
  25.  
  26. //dump();
  27. }
  28. }

2.2 在启动Activity之前去获取当前WMS中的Orientation的Config

在resumeTopActivityLocked和realStartActivityLocked中回去获取最新的Orientation的config

1. 通过mWindowManager.updateOrientationFromAppTokens去更新当前WMS中的Orientation值,把WMS中的config返回给AMS ,这个我们在之前http://blog.csdn.net/kc58236582/article/details/53741445博客分析过了

2. 通过updateConfigurationLocked去更新AMS中的config,发给每一个ActiviytThread。(会调用每个ActivityThread的onConfigurationChanged函数)

  1. synchronized (mService) {
  2. Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
  3. mService.mConfiguration,
  4. next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
  5. if (config != null) {
  6. next.frozenBeforeDestroy = true;
  7. }
  8. updated = mService.updateConfigurationLocked(config, next, false, false);
  9. }

WMS.updateOrientationFroemAppTokens 会直接去调updateOrientationFromAppTokensLocked

1. 去调用updateOrientationFromAppTokensLocked(false) 做真正的update Orientation的工作,如果返回是true,说明方向发生了变化,就需要去做app的转屏动作。

2. 如果freezeThisOneIfNeed不为null,说明要做屏幕的转屏操做,就会把当前的atoken freeze掉。

3. computeNewConfigurationLocked()  计算当前的Configuration,然后返回给AMS。

  1. private Configuration updateOrientationFromAppTokensLocked(
  2. Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
  3. Configuration config = null;
  4.  
  5. if (updateOrientationFromAppTokensLocked(false)) {
  6. if (freezeThisOneIfNeeded != null) {
  7. AppWindowToken atoken = findAppWindowToken(
  8. freezeThisOneIfNeeded);
  9. if (atoken != null) {
  10. startAppFreezingScreenLocked(atoken,
  11. ActivityInfo.CONFIG_ORIENTATION);
  12. }
  13. }
  14. config = computeNewConfigurationLocked();
  15.  
  16. } else if (currentConfig != null) {
  17. // No obvious action we need to take, but if our current
  18. // state mismatches the activity manager's, update it,
  19. // disregarding font scale, which should remain set to
  20. // the value of the previous configuration.
  21. mTempConfiguration.setToDefaults();
  22. mTempConfiguration.fontScale = currentConfig.fontScale;
  23. if (computeScreenConfigurationLocked(mTempConfiguration)) {
  24. if (currentConfig.diff(mTempConfiguration) != 0) {
  25. mWaitingForConfig = true;
  26. getDefaultDisplayContentLocked().layoutNeeded = true;
  27. startFreezingDisplayLocked(false, 0, 0);
  28. config = new Configuration(mTempConfiguration);
  29. }
  30. }
  31. }
  32.  
  33. return config;
  34. }

updateOrientationFromAppTokensLocked 会查找出当前是否有需要强制Orientation的App或者Window
         1. computeForcedAppOrientationLocked  //goto 3.2.1.1.1

2. 如果ForcedAppOrientation发生了变化, 就会去通知WindowPolicy去设置当前的Sensor的状态。//goto 3.2.1.1.2

3. updateRotationUncheckedLocked(inTransaction),由于Orientation可能发生变化,所以需要去重新获取一下Rotation;具体就可以参照前一节了。

如果Rotation发生了变化就返回true。跟configuration相关的东西,大多都在这个函数中进行。

  1. boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
  2. long ident = Binder.clearCallingIdentity();
  3. try {
  4. int req = computeForcedAppOrientationLocked();
  5.  
  6. if (req != mForcedAppOrientation) {
  7. mForcedAppOrientation = req;
  8. //send a message to Policy indicating orientation change to take
  9. //action like disabling/enabling sensors etc.,
  10. mPolicy.setCurrentOrientationLw(req);
  11. if (updateRotationUncheckedLocked(inTransaction)) {
  12. // changed
  13. return true;
  14. }
  15. }
  16.  
  17. return false;
  18. } finally {
  19. Binder.restoreCallingIdentity(ident);
  20. }
  21. }

computeForcedAppOrientationLocked

这个函数的作用就是去查询当前即将要显示的Activity或者Window有没有需要强制Orientation的

1. 先通过 getOrientationFromWindowsLocked去遍历WMS中的WindowList。

1)如果在最上面的Window是一个AppWindow就直接返回mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED

2)如果不是AppWindow,判断这个Window是否可见,如果不可见就continue

3)最后如果这个Window既不是AppWindow又要是可见的,并且他是有指定ScreenOrientation的,就返回这个window的orientatin。mLastWindowForcedOrientation=req

2. 如果getOrientationFromWindowsLocked找到的是一个AppWindow或者当前没有指定Orientation的Window,就会走到getOrientationFromAppTokensLocked();

1)这个函数会去遍历AppWindowToken List去查找需要强制Orientation的Token,这个时候就是根据我们之前在AMS中传递进来的atoken.requestedOrientation;来进行判断,如果设置了就返回回去给req。

  1. int computeForcedAppOrientationLocked() {
  2. int req = getOrientationFromWindowsLocked();
  3. if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
  4. req = getOrientationFromAppTokensLocked();
  5. }
  6. if (mForceLandScape &&
  7. req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
  8. req = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
  9. }
  10. return req;
  11. }

PhoneWindowManager.setCurrentOrientationLw()

1. 用mCurrentAppOrientation保存当前新的Orientation.

2. updateOrientationListenerLp,通过名字就知道他只是去管理是否启动Sensor Listener的。

  1. public void setCurrentOrientationLw(int newOrientation) {
  2. synchronized (mLock) {
  3. if (newOrientation != mCurrentAppOrientation) {
  4. mCurrentAppOrientation = newOrientation;
  5. updateOrientationListenerLp();
  6. }
  7. }
  8. }

WMS. computeNewConfiguration()

通过computeNewConfigurationLocked() 计算出一个新的configuration.随后就会在AMS中调用ActivityThread把这个数据最后传到应用进程

  1. public Configuration computeNewConfiguration() {
  2. synchronized (mWindowMap) {
  3. Configuration config = computeNewConfigurationLocked();
  4. if (config == null && mWaitingForConfig) {
  5. // Nothing changed but we are waiting for something... stop that!
  6. mWaitingForConfig = false;
  7. performLayoutAndPlaceSurfacesLocked();
  8. }
  9. return config;
  10. }
  11. }

2.3 AMS端的工作完成之后,就到ActivityThread和ViewRootImpl的工作了

2.3.1 在ActivityThread的handleResume的时候会把Activity对应的DectorView加到WMS中,在WMS中会调用addWindow.

如果我们自己添加一个Window的话也是走到这边。 在AddWindow的时候有可能对Orietation和Configuration, 前提是这个win的isVisibleOrAdding的条件。不过一般都不会满足这个条件。

sendNewConfiguration最后会到AMS的updateConfiguration函数然后调用updateConfigurationLocked函数之前博客分析过了。

  1. if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
  2. reportNewConfig = true;
  3. }
  4. }
  5.  
  6. if (reportNewConfig) {
  7. sendNewConfiguration();
  8. }

2.3.2 当addWindow完成之后,ViewRootImpl就会去requestLayout,而requestLayout实际上就是去做scheduleTraversals

1. 在performTraversals中会先去做一次measureHierarchy计算一下View所需的大小。

2. 然后会调用relayoutWindow去请求WMS帮助实际计算当前Window的布局,创建一个Surface,并且返回对应的Frame。

2.3.4 WMS.relayoutWindow()

1. 根据传进来的requestWidth和requestHeight 或者attrChange的变化来决定是不是真的要relayout,并且把win.mLayoutNeeded设置为true。在performLayoutAndPlaceSurfacesLocked的会根据这个值做判断。

2. 如果当前的WindowState还没有Surface就调用 winAnimator.createSurfaceLocked();去创建一个Surface会带回给ViewRootImpl

3. 如果focus window发生变化了就updateFocusedWindowLocked

如果Layer变化了就调用assignLayersLocked

4.
再次调用updateOrientationFromAppTokensLocked去判断当前的Orietation是不是发生变化了。//在这个调用中如果有Orientation发生了变化,如果有变化就会调用computeNewConfigurationLocked()去更新DisplayContent相关的信息并且计算出一个新的Configuration

5. 调用performLayoutAndPlaceSurfacesLocked

6. 把WindowState中的三个Frame返回给Client端。

  1. public int relayoutWindow(Session session, IWindow client, int seq,
  2. WindowManager.LayoutParams attrs, int requestedWidth,
  3. int requestedHeight, int viewVisibility, int flags,
  4. Rect outFrame, Rect outContentInsets,
  5. Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
  6. boolean toBeDisplayed = false;
  7. boolean inTouchMode;
  8. boolean configChanged;
  9. boolean surfaceChanged = false;
  10. boolean animating;
  11. ... ...
  12. synchronized(mWindowMap) {
  13. // TODO(cmautner): synchronize on mAnimator or win.mWinAnimator.
  14. WindowState win = windowForClientLocked(session, client, false);
  15. ... ...
  16. WindowStateAnimator winAnimator = win.mWinAnimator;
  17. if (win.mRequestedWidth != requestedWidth
  18. || win.mRequestedHeight != requestedHeight) {
  19. win.mLayoutNeeded = true;
  20. win.mRequestedWidth = requestedWidth;
  21. win.mRequestedHeight = requestedHeight;
  22. }
  23. if (attrs != null && seq == win.mSeq) {
  24. win.mSystemUiVisibility = systemUiVisibility;
  25. }
  26.  
  27. if (attrs != null) {
  28. mPolicy.adjustWindowParamsLw(attrs);
  29. }
  30.  
  31. winAnimator.mSurfaceDestroyDeferred =
  32. (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
  33.  
  34. int attrChanges = 0;
  35. int flagChanges = 0;
  36. if (attrs != null) {
  37.  
  38. flagChanges = win.mAttrs.flags ^= attrs.flags;
  39. attrChanges = win.mAttrs.copyFrom(attrs);
  40. if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
  41. | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
  42. win.mLayoutNeeded = true;
  43. }
  44. }
  45. ... ...
  46. if (viewVisibility == View.VISIBLE &&
  47. (win.mAppToken == null || !win.mAppToken.clientHidden)) {
  48. toBeDisplayed = !win.isVisibleLw();
  49.  
  50.  
  51. if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
  52. // To change the format, we need to re-build the surface.
  53. winAnimator.destroySurfaceLocked(false);
  54. toBeDisplayed = true;
  55. surfaceChanged = true;
  56. }
  57. try {
  58. if (!win.mHasSurface) {
  59. surfaceChanged = true;
  60. }
  61. Surface surface = winAnimator.createSurfaceLocked();
  62. if (surface != null) {
  63. outSurface.copyFrom(surface);
  64. if (SHOW_TRANSACTIONS) Slog.i(TAG,
  65. " OUT SURFACE " + outSurface + ": copied");
  66. } else {
  67. // For some reason there isn't a surface. Clear the
  68. // caller's object so they see the same state.
  69. outSurface.release();
  70. }
  71. } catch (Exception e) {
  72.  
  73. }
  74. if (toBeDisplayed) {
  75. focusMayChange = isDefaultDisplay;
  76. }
  77. if (win.mAttrs.type == TYPE_INPUT_METHOD
  78. && mInputMethodWindow == null) {
  79. mInputMethodWindow = win;
  80. imMayMove = true;
  81. }
  82. if (win.mAttrs.type == TYPE_BASE_APPLICATION
  83. && win.mAppToken != null
  84. && win.mAppToken.startingWindow != null) {
  85. // Special handling of starting window over the base
  86. // window of the app: propagate lock screen flags to it,
  87. // to provide the correct semantics while starting.
  88. final int mask =
  89. WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
  90. | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
  91. | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
  92. WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
  93. sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
  94. }
  95. } else {
  96. winAnimator.mEnterAnimationPending = false;
  97. if (winAnimator.mSurface != null) {
  98. if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
  99. + ": mExiting=" + win.mExiting);
  100. // If we are not currently running the exit animation, we
  101. // need to see about starting one.
  102. if (!win.mExiting) {
  103. surfaceChanged = true;
  104. // Try starting an animation; if there isn't one, we
  105. // can destroy the surface right away.
  106. int transit = WindowManagerPolicy.TRANSIT_EXIT;
  107. if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
  108. transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
  109. }
  110. if (win.isWinVisibleLw() &&
  111. winAnimator.applyAnimationLocked(transit, false)) {
  112. focusMayChange = isDefaultDisplay;
  113. win.mExiting = true;
  114. } else if (win.mWinAnimator.isAnimating()) {
  115. // Currently in a hide animation... turn this into
  116. // an exit.
  117. win.mExiting = true;
  118. } else if (win == mWallpaperTarget) {
  119. // If the wallpaper is currently behind this
  120. // window, we need to change both of them inside
  121. // of a transaction to avoid artifacts.
  122. win.mExiting = true;
  123. win.mWinAnimator.mAnimating = true;
  124. } else {
  125. if (mInputMethodWindow == win) {
  126. mInputMethodWindow = null;
  127. }
  128. winAnimator.destroySurfaceLocked(false);
  129. }
  130. scheduleNotifyWindowTranstionIfNeededLocked(win, transit);
  131. }
  132. }
  133.  
  134. outSurface.release();
  135. if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
  136. }
  137.  
  138. if (focusMayChange) {
  139. //System.out.println("Focus may change: " + win.mAttrs.getTitle());
  140. if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
  141. false /*updateInputWindows*/)) {
  142. imMayMove = false;
  143. }
  144. //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
  145. }
  146.  
  147. // updateFocusedWindowLocked() already assigned layers so we only need to
  148. // reassign them at this point if the IM window state gets shuffled
  149. boolean assignLayers = false;
  150. ... ...
  151. if (assignLayers) {
  152. assignLayersLocked(win.getWindowList());
  153. }
  154. configChanged = updateOrientationFromAppTokensLocked(false);
  155. performLayoutAndPlaceSurfacesLocked();
  156. if (toBeDisplayed && win.mIsWallpaper) {
  157. DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
  158. updateWallpaperOffsetLocked(win,
  159. displayInfo.appWidth, displayInfo.appHeight, false);
  160. }
  161. if (win.mAppToken != null) {
  162. win.mAppToken.updateReportedVisibilityLocked();
  163. }
  164. outFrame.set(win.mCompatFrame);
  165. outContentInsets.set(win.mContentInsets);
  166. outVisibleInsets.set(win.mVisibleInsets);
  167. ... ...
  168.  
  169. mInputMonitor.updateInputWindowsLw(true /*force*/);
  170.  
  171. }
  172.  
  173. if (configChanged) {
  174. sendNewConfiguration();
  175. }

WMS.performLayoutAndPlaceSurfacesLockedLoop()

performLayoutAndPlaceSurfacesLocked直接去调performLayoutAndPlaceSurfacesLockedLoop, 在performLayoutAndPlaceSurfacesLockedLoop里面做两个最主要的操作。

1. performLayoutAndPlaceSurfacesLockedInner();

2. requestTraversalLocked();

  1. private final void performLayoutAndPlaceSurfacesLockedLoop() {
  2. ... ...
  3.  
  4. mInLayout = true;
  5. boolean recoveringMemory = false;
  6. ... ...
  7. try {
  8. performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
  9.  
  10. mInLayout = false;
  11.  
  12. if (needsLayout()) {
  13. if (++mLayoutRepeatCount < 6) {
  14. requestTraversalLocked();
  15. } else {
  16. Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
  17. mLayoutRepeatCount = 0;
  18. }
  19. } else {
  20. mLayoutRepeatCount = 0;
  21. }
  22.  
  23. if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
  24. mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
  25. mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE));
  26. }
  27. } catch (RuntimeException e) {
  28. mInLayout = false;
  29. Log.wtf(TAG, "Unhandled exception while laying out windows", e);
  30. }
  31.  
  32. Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
  33. }

WMS.performLayoutAndPlaceSurfacesLockedInner(false)

1.
首先会获取当前的一个DsiplayContent,由于这个DisplayContent在updateOrientationFromAppTokensLocked的时候已经根据最新的window状态进行跟新过,所以现在的DsiplayContent应该是最新的值。

2. performLayoutLockedInner; 这个函数回去遍历每一个Window,然后根据当前的DisplayContent去更新Layout.

这个方法会根据最新的DisplayContent去判断所有的window是否需要重新layout

第一步,通过mPolicy.beginLayoutLw去给policy设置一个标准把当前的Content信息设置进去

第二步, mPolicy.layoutWindowLw(win, win.mAttrs, null); 给win做真正的layout,layout主要做了什么?有几个重要的变量?

在layoutWindow中会通过computeFrameLw去计算WindowState的中的Frame,有三个Frame;

3. updateResizingWindows(w);

如果WindowState其中的w.mContentInsetsChanged ||
w.mVisibleInsetsChanged  || winAnimator.mSurfaceResized|| configChanged
任意的一个发生变化了就会加入到mResizingWindows数组中。并且把对应的Window Freezing。

4. 遍历mResizingWindows, 调用win.mClient.resized通过IPC告诉Clinet端要做resize

最终ViewRootImpl就会发送一个MSG_RESIZED去处理,WMS会把里面的三个Frame和Configuration发回给Clinet。ViewRoot会保存最新的三个Frame和updateConfiguration,最后 requestLayout();

    1. private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
    2. ... ...
    3. Surface.openTransaction();
    4. try {
    5.  
    6. boolean focusDisplayed = false;
    7. boolean updateAllDrawn = false;
    8.  
    9. DisplayContentsIterator iterator = new DisplayContentsIterator();
    10. while (iterator.hasNext()) {
    11. final DisplayContent displayContent = iterator.next();
    12. WindowList windows = displayContent.getWindowList();
    13. DisplayInfo displayInfo = displayContent.getDisplayInfo();
    14. final int displayId = displayContent.getDisplayId();
    15. final int dw = displayInfo.logicalWidth;
    16. final int dh = displayInfo.logicalHeight;
    17. final int innerDw = displayInfo.appWidth;
    18. final int innerDh = displayInfo.appHeight;
    19. final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
    20.  
    21. // Reset for each display unless we are forcing mirroring.
    22. if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) {
    23. mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
    24. }
    25. ... ...
    26. int repeats = 0;
    27. do {
    28. repeats++;
    29. ... ...
    30. // FIRST LOOP: Perform a layout, if needed.
    31. if (repeats < 4) {
    32. performLayoutLockedInner(displayContent, repeats == 1,
    33. false /*updateInputWindows*/);
    34. } else {
    35. Slog.w(TAG, "Layout repeat skipped after too many iterations");
    36. }
    37. ... ...
    38. } while (displayContent.pendingLayoutChanges != 0);
    39.  
    40. // Only used if default window
    41. final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
    42.  
    43. final int N = windows.size();
    44. for (i=N-1; i>=0; i--) {
    45. WindowState w = windows.get(i);
    46. ... ...
    47.  
    48. //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
    49. w.mContentChanged = false;
    50.  
    51. // Moved from updateWindowsAndWallpaperLocked().
    52. if (w.mHasSurface) {
    53. // Take care of the window being ready to display.
    54. ... ...
    55. }
    56. ... ...
    57. }
    58. }
    59.  
    60. if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
    61. && w.isDisplayedLw()) {
    62. focusDisplayed = true;
    63. }
    64.  
    65. updateResizingWindows(w);
    66. }
    67.  
    68. ... ...
    69.  
    70. for (i = mResizingWindows.size() - 1; i >= 0; i--) {
    71. WindowState win = mResizingWindows.get(i);
    72. if (win.mAppFreezing) {
    73. // Don't remove this window until rotation has completed.
    74. continue;
    75. }
    76. final WindowStateAnimator winAnimator = win.mWinAnimator;
    77. try {
    78. if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
    79. "Reporting new frame to " + win + ": " + win.mCompatFrame);
    80. int diff = 0;
    81. boolean configChanged = win.isConfigChanged();
    82. if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
    83. && configChanged) {
    84. Slog.i(TAG, "Sending new config to window " + win + ": "
    85. + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
    86. + " / " + mCurConfiguration + " / 0x"
    87. + Integer.toHexString(diff));
    88. }
    89. win.setConfiguration(mCurConfiguration);
    90. if (DEBUG_ORIENTATION &&
    91. winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
    92. TAG, "Resizing " + win + " WITH DRAW PENDING");
    93. win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets,
    94. winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING,
    95. configChanged ? win.mConfiguration : null);
    96. win.mContentInsetsChanged = false;
    97. win.mVisibleInsetsChanged = false;
    98. winAnimator.mSurfaceResized = false;
    99. } catch (RemoteException e) {
    100. win.mOrientationChanging = false;
    101. }
    102. mResizingWindows.remove(i);
    103. }
    104.  
    105. ... ...
    106.  
    107. // Finally update all input windows now that the window changes have stabilized.
    108. mInputMonitor.updateInputWindowsLw(true /*force*/);
    109. ... ...
    110. }
    111.  
    112. // Check to see if we are now in a state where the screen should
    113. // be enabled, because the window obscured flags have changed.
    114. enableScreenIfNeededLocked();
    115.  
    116. updateLayoutToAnimationLocked();
    117. ... ...
    118. }

Android6.0 旋转屏幕(五)WMS启动应用流程(屏幕方向相关)的更多相关文章

  1. [Android6.0][RK3399] 双屏异显代码实现流程分析(一)【转】

    本文转载自:http://blog.csdn.net/dearsq/article/details/55049182 Platform: RK3399 OS: Android 6.0 Version: ...

  2. [Android6.0][RK3399] 双屏异显代码实现流程分析(二)【转】

    本文转载自:http://blog.csdn.net/dearsq/article/details/55050125 Patch Code dtsi rk3399-androiddtsi rk3399 ...

  3. 【Unity游戏开发】Android6.0以上的动态权限申请问题

    一.引子 最近公司的游戏在做安全性测试,期间也暴露出了不少安全上的问题.虽然我们今天要说的权限申请和安全性相关不大,但是也会影响到游戏的使用体验等,所以本篇博客中马三就想和大家谈谈Android6.0 ...

  4. WMS—启动过程

    基于Android 6.0源码, 分析WMS的启动过程. 一. 概述 Surface:代表画布 WMS: 添加window的过程主要功能是添加Surface,管理所有的Surface布局,以及Z轴排序 ...

  5. android6.0、7.0、8.0新特性总结之开发应用时加以考虑的一些主要变更。

    android6.0 参考一:简书Android 6.0 新特性详解 参考二:关于Android6.0以上系统的权限问题 参考三:值得你关注的Android6.0上的重要变化(一) 参考四:值得你关注 ...

  6. Android6.0系统添加那些新特性

        北京时间9月30日凌晨在美国旧金山举行2015年秋季新品公布会.在公布会上代号为"Marshmallow(棉花糖)"的安卓6.0系统正式推出.新系统的总体设计风格依旧保持扁 ...

  7. Android6.0 init 深入分析

    之前写过一篇关于android5.0 init的介绍,这篇博客是介绍android6.0init,之前有的代码介绍不详细.而且分析 解析init.rc那块代码也没有结合init.rc介绍. 一. ma ...

  8. Android6.0中PowerManagerService分析

    转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=30510400&id=5569393 概述 一直以来,电源管理是 ...

  9. (原创)android6.0系统 PowerManager深入分析(很具体)

    概述 一直以来,电源管理是电子产品设计中很重要的环节.也是不论什么电子设备中最为重要的系统模块之中的一个,优秀的电源管理方案.可以提供持久的续航能力,良好的用户体验.更能提升电子产品的竞争力. 移动设 ...

随机推荐

  1. 解释一下Windows dos中的符号

    容许我放一段Windows的批处理: sc <server> [command] [service name] <option1> <option2>... < ...

  2. Linux ps 命令查看进程启动及运行时间

    引言 同事问我怎样看一个进程的启动时间和运行时间,我第一反应当然是说用 ps 命令啦.ps aux或ps -ef不就可以看时间吗? ps aux选项及输出说明 我们来重新复习下ps aux的选项,这是 ...

  3. Flume-1-7-0用户手册

    介绍 概述 Apache Flume是为有效收集聚合和移动大量来自不同源到中心数据存储而设计的可分布,可靠的,可用的系统. Apache Flume的用途不仅限于日志数据聚合.由于数据源是可定制的,F ...

  4. Android中经常使用的bitmap处理方法

    收集了非常多bitmap相关的处理方法,差点儿所有应用在项目中,所以特记录下! package com.tmacsky.utils; import java.io.ByteArrayOutputStr ...

  5. SpringBoot启动流程分析(二):SpringApplication的run方法

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  6. anaconda2下面安装opencv2.4.13.4完成----解决默认安装的问题----Thefunction is not implemented. Rebuild the library with Windows, GTK+ 2.x orCarbon support. If you are on Ubuntu or Debian, install libgtk2.0‑dev and pkg

    转载自:http://blog.csdn.net/qingyanyichen/article/details/73550924 本人下载编译安装了opencv2.4.9,oppencv2.4.10,o ...

  7. linux 跟踪工具

    strace工具,进程诊断.排错.跟踪系统调用和信号量 每行输出都是一个系统调用,包括函数和返回值. strace是Linux环境下的一款程序调试工具,用来监察一个应用程序所使用的系统调用及它所接收的 ...

  8. CocoaPods Podfile详解与使用

    1.为什么需要CocoaPods 在进行iOS开发的时候,总免不了使用第三方的开源库,比如SBJson.AFNetworking.Reachability等等.使用这些库的时候通常需要: 下载开源库的 ...

  9. Android OkHttp的Cookie自己主动化管理

    Android中在使用OkHttp这个库的时候.有时候须要持久化Cookie,那么怎么实现呢.OkHttp的内部源代码过于复杂,不进行深究.这里仅仅看当中的HttpEngineer里面的部分源代码,在 ...

  10. gdb ../sysdeps/i386/elf/start.S: No such file or directory

    使用 gdb 调试的时候 输入 l 之后出现下列信息 (gdb) l 1 ../sysdeps/i386/elf/start.S: No such file or directory. in ../s ...