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:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user