More optimization while dragging docked divider

- Make sure mPendingBackdropFrame gets also set when if the window
triggers a relayout on it's own, so it doesn't call into window manager
all the time.
- Set the insets of the docked divider to empty so we don't trigger a
layout when we are just moving it - it doesn't need it in any case.
- Send a window move message to the divider when it moved
- Update attach info in all move cases, update light center

The whole resize operation now only takes around 4ms per frame, and
leaves a lot more resources for the apps to do configuration changes.

Bug: 25015474
Change-Id: Ica48129570a0fc858a89c21f46abf3442efb0224
This commit is contained in:
Jorim Jaggi
2016-01-14 17:36:55 -08:00
parent 844e1712df
commit 2e95a488e0
8 changed files with 80 additions and 51 deletions

View File

@@ -167,6 +167,7 @@ public abstract class WallpaperService extends Service {
final Rect mDispatchedOutsets = new Rect();
final Rect mFinalSystemInsets = new Rect();
final Rect mFinalStableInsets = new Rect();
final Rect mBackdropFrame = new Rect();
final Configuration mConfiguration = new Configuration();
final WindowManager.LayoutParams mLayout
@@ -675,8 +676,8 @@ public abstract class WallpaperService extends Service {
final int relayoutResult = mSession.relayout(
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets,
mVisibleInsets, mStableInsets, mOutsets, mConfiguration,
mSurfaceHolder.mSurface);
mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame,
mConfiguration, mSurfaceHolder.mSurface);
if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
+ ", frame=" + mWinFrame);

View File

@@ -81,6 +81,8 @@ interface IWindowSession {
* so complex relayout of the window should not happen based on them.
* @param outOutsets Rect in which is placed the dead area of the screen that we would like to
* treat as real display. Example of such area is a chin in some models of wearable devices.
* @param outBackdropFrame Rect which is used draw the resizing background during a resize
* operation.
* @param outConfiguration New configuration of window, if it is now
* becoming visible and the global configuration has changed since it
* was last displayed.
@@ -93,7 +95,8 @@ interface IWindowSession {
int requestedWidth, int requestedHeight, int viewVisibility,
int flags, out Rect outFrame, out Rect outOverscanInsets,
out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
out Rect outOutsets, out Configuration outConfig, out Surface outSurface);
out Rect outOutsets, out Rect outBackdropFrame, out Configuration outConfig,
out Surface outSurface);
/**
* Position a window relative to it's parent (attached) window without triggering

View File

@@ -107,6 +107,7 @@ public class SurfaceView extends View {
final Rect mContentInsets = new Rect();
final Rect mStableInsets = new Rect();
final Rect mOutsets = new Rect();
final Rect mBackdropFrame = new Rect();
final Configuration mConfiguration = new Configuration();
static final int KEEP_SCREEN_ON_MSG = 1;
@@ -529,8 +530,8 @@ public class SurfaceView extends View {
visible ? VISIBLE : GONE,
WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
mWinFrame, mOverscanInsets, mContentInsets,
mVisibleInsets, mStableInsets, mOutsets, mConfiguration,
mNewSurface);
mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame,
mConfiguration, mNewSurface);
if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
reportDrawNeeded = true;
}

View File

@@ -17,6 +17,7 @@
package android.view;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
@@ -1953,29 +1954,7 @@ public final class ViewRootImpl implements ViewParent,
// in the attach info. We translate only the window frame since on window move
// the window manager tells us only for the new frame but the insets are the
// same and we do not want to translate them more than once.
// TODO: Well, we are checking whether the frame has changed similarly
// to how this is done for the insets. This is however incorrect since
// the insets and the frame are translated. For example, the old frame
// was (1, 1 - 1, 1) and was translated to say (2, 2 - 2, 2), now the new
// reported frame is (2, 2 - 2, 2) which implies no change but this is not
// true since we are comparing a not translated value to a translated one.
// This scenario is rare but we may want to fix that.
final boolean windowMoved = (mAttachInfo.mWindowLeft != frame.left
|| mAttachInfo.mWindowTop != frame.top);
if (windowMoved) {
if (mTranslator != null) {
mTranslator.translateRectInScreenToAppWinFrame(frame);
}
mAttachInfo.mWindowLeft = frame.left;
mAttachInfo.mWindowTop = frame.top;
// Update the light position for the new window offsets.
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.setLightCenter(mAttachInfo);
}
}
maybeHandleWindowMove(frame);
}
final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
@@ -2140,6 +2119,31 @@ public final class ViewRootImpl implements ViewParent,
mIsInTraversal = false;
}
private void maybeHandleWindowMove(Rect frame) {
// TODO: Well, we are checking whether the frame has changed similarly
// to how this is done for the insets. This is however incorrect since
// the insets and the frame are translated. For example, the old frame
// was (1, 1 - 1, 1) and was translated to say (2, 2 - 2, 2), now the new
// reported frame is (2, 2 - 2, 2) which implies no change but this is not
// true since we are comparing a not translated value to a translated one.
// This scenario is rare but we may want to fix that.
final boolean windowMoved = mAttachInfo.mWindowLeft != frame.left
|| mAttachInfo.mWindowTop != frame.top;
if (windowMoved) {
if (mTranslator != null) {
mTranslator.translateRectInScreenToAppWinFrame(frame);
}
mAttachInfo.mWindowLeft = frame.left;
mAttachInfo.mWindowTop = frame.top;
// Update the light position for the new window offsets.
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.setLightCenter(mAttachInfo);
}
}
}
private void handleOutOfResourcesException(Surface.OutOfResourcesException e) {
Log.e(mTag, "OutOfResourcesException initializing HW surface", e);
try {
@@ -3403,12 +3407,16 @@ public final class ViewRootImpl implements ViewParent,
// Suppress layouts during resizing - a correct layout will happen when resizing
// is done, and this just increases system load.
boolean suppress = mDragResizing && mResizeMode == RESIZE_MODE_DOCKED_DIVIDER;
boolean isDockedDivider = mWindowAttributes.type == TYPE_DOCK_DIVIDER;
boolean suppress = (mDragResizing && mResizeMode == RESIZE_MODE_DOCKED_DIVIDER)
|| isDockedDivider;
if (!suppress) {
if (mView != null) {
forceLayout(mView);
}
requestLayout();
} else {
maybeHandleWindowMove(mWinFrame);
}
}
break;
@@ -5522,7 +5530,8 @@ public final class ViewRootImpl implements ViewParent,
(int) (mView.getMeasuredHeight() * appScale + 0.5f),
viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface);
mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration,
mSurface);
//Log.d(mTag, "<<<<<< BACK FROM relayout");
if (restore) {
params.restore();

View File

@@ -26,6 +26,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
/**
@@ -50,6 +51,7 @@ public class DividerWindowManager {
| FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH | FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
mLp.setTitle(WINDOW_TITLE);
mLp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

View File

@@ -203,15 +203,14 @@ final class Session extends IWindowSession.Stub
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags,
int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Configuration
outConfig,
Surface outSurface) {
Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
Configuration outConfig, Surface outSurface) {
if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
+ Binder.getCallingPid());
int res = mService.relayoutWindow(this, window, seq, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
outStableInsets, outsets, outConfig, outSurface);
outStableInsets, outsets, outBackdropFrame, outConfig, outSurface);
if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
+ Binder.getCallingPid());
return res;

View File

@@ -2561,8 +2561,8 @@ public class WindowManagerService extends IWindowManager.Stub
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, int flags,
Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Configuration outConfig,
Surface outSurface) {
Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
Configuration outConfig, Surface outSurface) {
int result = 0;
boolean configChanged;
boolean hasStatusBarPermission =
@@ -2749,6 +2749,7 @@ public class WindowManagerService extends IWindowManager.Stub
outVisibleInsets.set(win.mVisibleInsets);
outStableInsets.set(win.mStableInsets);
outOutsets.set(win.mOutsets);
outBackdropFrame.set(win.getBackdropFrame(win.mFrame));
if (localLOGV) Slog.v(
TAG_WM, "Relayout given client " + client.asBinder()
+ ", requestedWidth=" + requestedWidth

View File

@@ -729,6 +729,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// will return the correct value to the renderer.
mDisplayContent.getDockedDividerController().positionDockedStackedDivider(mFrame);
mContentFrame.set(mFrame);
if (!mFrame.equals(mLastFrame)) {
mMovedByResize = true;
}
}
} else {
mContentFrame.set(Math.max(mContentFrame.left, frame.left),
@@ -752,15 +755,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
Math.max(frame.right - mOverscanFrame.right, 0),
Math.max(frame.bottom - mOverscanFrame.bottom, 0));
mContentInsets.set(mContentFrame.left - frame.left,
mContentFrame.top - frame.top,
frame.right - mContentFrame.right,
frame.bottom - mContentFrame.bottom);
mVisibleInsets.set(mVisibleFrame.left - frame.left,
mVisibleFrame.top - frame.top,
frame.right - mVisibleFrame.right,
frame.bottom - mVisibleFrame.bottom);
if (mAttrs.type == TYPE_DOCK_DIVIDER) {
@@ -770,7 +765,22 @@ final class WindowState implements WindowManagerPolicy.WindowState {
Math.max(mStableFrame.top - mDisplayFrame.top, 0),
Math.max(mDisplayFrame.right - mStableFrame.right, 0),
Math.max(mDisplayFrame.bottom - mStableFrame.bottom, 0));
// The divider doesn't care about insets in any case, so set it to empty so we don't
// trigger a relayout when moving it.
mContentInsets.setEmpty();
mVisibleInsets.setEmpty();
} else {
mContentInsets.set(mContentFrame.left - frame.left,
mContentFrame.top - frame.top,
frame.right - mContentFrame.right,
frame.bottom - mContentFrame.bottom);
mVisibleInsets.set(mVisibleFrame.left - frame.left,
mVisibleFrame.top - frame.top,
frame.right - mVisibleFrame.right,
frame.bottom - mVisibleFrame.bottom);
mStableInsets.set(Math.max(mStableFrame.left - frame.left, 0),
Math.max(mStableFrame.top - frame.top, 0),
Math.max(frame.right - mStableFrame.right, 0),
@@ -1993,21 +2003,24 @@ final class WindowState implements WindowManagerPolicy.WindowState {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
Configuration newConfig) throws RemoteException {
DisplayInfo displayInfo = getDisplayInfo();
mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
Rect getBackdropFrame(Rect frame) {
// When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
// start even if we haven't received the relayout window, so that the client requests
// the relayout sooner. When dragging stops, backDropFrame needs to stay fullscreen
// until the window to small size, otherwise the multithread renderer will shift last
// one or more frame to wrong offset. So here we send fullscreen backdrop if either
// isDragResizing() or isDragResizeChanged() is true.
DisplayInfo displayInfo = getDisplayInfo();
mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
boolean resizing = isDragResizing() || isDragResizeChanged();
final Rect backDropFrame = (inFreeformWorkspace() || !resizing) ? frame : mTmpRect;
return (inFreeformWorkspace() || !resizing) ? frame : mTmpRect;
}
private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
Configuration newConfig) throws RemoteException {
mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets,
reportDraw, newConfig, backDropFrame);
reportDraw, newConfig, getBackdropFrame(frame));
}
public void registerFocusObserver(IWindowFocusObserver observer) {