diff options
| author | 2018-08-20 10:36:25 +0800 | |
|---|---|---|
| committer | 2018-08-22 09:43:55 +0800 | |
| commit | 0042e4516ffcea66cb209d8c2dad7aeaa53b50fb (patch) | |
| tree | eca184b0eabb5bbf9fa76a233032a3fd6ba186aa | |
| parent | a2e28a4b86409415e84d36fcc072e6c3c2f0e561 (diff) | |
Prevent ViewRootImpl.mDisplay become null.
For some timing cases client side may not get desired display with old
displayId.
For this issue, client side has just received configuration change and
handle it in ActivityThread#handleActivityConfigurationChanged. At the
same time, DisplayManagerService was about to destory display. When
ViewRootImpl want to update display with new DisplayAdjustments, it got
null because the old displayId was removed.
For this scenario, fallback to use default display. Usually there should
be other displayId change event comes from server side to ask client update.
Change-Id: Ifb843f82b753761cb6306e7482b38a0ffd89498d
Fix: 73558361
Test: atest CtsWindowManagerDeviceTestCases
Test: atest CtsActivityManagerDeviceTestCases
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 23fc4d5045a9..1351f6f1ef26 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -16,6 +16,7 @@ package android.view; +import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.View.PFLAG_DRAW_ANIMATION; import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER; @@ -1212,13 +1213,30 @@ public final class ViewRootImpl implements ViewParent, // Get new instance of display based on current display adjustments. It may be updated later // if moving between the displays also involved a configuration change. - mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(displayId, - mView.getResources()); + updateInternalDisplay(displayId, mView.getResources()); mAttachInfo.mDisplayState = mDisplay.getState(); // Internal state updated, now notify the view hierarchy. mView.dispatchMovedToDisplay(mDisplay, config); } + /** + * Updates {@link #mDisplay} to the display object corresponding to {@param displayId}. + * Uses DEFAULT_DISPLAY if there isn't a display object in the system corresponding + * to {@param displayId}. + */ + private void updateInternalDisplay(int displayId, Resources resources) { + final Display preferredDisplay = + ResourcesManager.getInstance().getAdjustedDisplay(displayId, resources); + if (preferredDisplay == null) { + // Fallback to use default display. + Slog.w(TAG, "Cannot get desired display with Id: " + displayId); + mDisplay = ResourcesManager.getInstance() + .getAdjustedDisplay(DEFAULT_DISPLAY, resources); + } else { + mDisplay = preferredDisplay; + } + } + void pokeDrawLockIfNeeded() { final int displayState = mAttachInfo.mDisplayState; if (mView != null && mAdded && mTraversalScheduled @@ -3944,8 +3962,7 @@ public final class ViewRootImpl implements ViewParent, // Handle configuration change. if (mForceNextConfigUpdate || mLastConfigurationFromResources.diff(config) != 0) { // Update the display with new DisplayAdjustments. - mDisplay = ResourcesManager.getInstance().getAdjustedDisplay( - mDisplay.getDisplayId(), localResources); + updateInternalDisplay(mDisplay.getDisplayId(), localResources); final int lastLayoutDirection = mLastConfigurationFromResources.getLayoutDirection(); final int currentLayoutDirection = config.getLayoutDirection(); |