Merge "Revert "ScreenDecorations: Fix stuck / delayed rotations""

This commit is contained in:
TreeHugger Robot
2018-08-13 17:40:21 +00:00
committed by Android (Google) Code Review
4 changed files with 46 additions and 197 deletions

View File

@@ -43,12 +43,9 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemProperties;
import android.provider.Settings.Secure;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
@@ -63,7 +60,6 @@ import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.android.internal.util.Preconditions;
import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
@@ -83,9 +79,6 @@ import androidx.annotation.VisibleForTesting;
* for antialiasing and emulation purposes.
*/
public class ScreenDecorations extends SystemUI implements Tunable {
private static final boolean DEBUG = false;
private static final String TAG = "ScreenDecorations";
public static final String SIZE = "sysui_rounded_size";
public static final String PADDING = "sysui_rounded_content_padding";
private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
@@ -106,23 +99,9 @@ public class ScreenDecorations extends SystemUI implements Tunable {
private DisplayCutoutView mCutoutBottom;
private SecureSetting mColorInversionSetting;
private boolean mPendingRotationChange;
private Handler mHandler;
@Override
public void start() {
mHandler = startHandlerThread();
mHandler.post(this::startOnScreenDecorationsThread);
setupStatusBarPaddingIfNeeded();
}
@VisibleForTesting
Handler startHandlerThread() {
HandlerThread thread = new HandlerThread("ScreenDecorations");
thread.start();
return thread.getThreadHandler();
}
private void startOnScreenDecorationsThread() {
mWindowManager = mContext.getSystemService(WindowManager.class);
mRoundedDefault = mContext.getResources().getDimensionPixelSize(
R.dimen.rounded_corner_radius);
@@ -134,6 +113,12 @@ public class ScreenDecorations extends SystemUI implements Tunable {
setupDecorations();
}
int padding = mContext.getResources().getDimensionPixelSize(
R.dimen.rounded_corner_content_padding);
if (padding != 0) {
setupPadding(padding);
}
mDisplayListener = new DisplayManager.DisplayListener() {
@Override
public void onDisplayAdded(int displayId) {
@@ -147,8 +132,8 @@ public class ScreenDecorations extends SystemUI implements Tunable {
@Override
public void onDisplayChanged(int displayId) {
final int newRotation = RotationUtils.getExactRotation(mContext);
if (mOverlay != null && mBottomOverlay != null && mRotation != newRotation) {
if ((hasRoundedCorners() || shouldDrawCutout()) &&
mRotation != RotationUtils.getExactRotation(mContext)) {
// We cannot immediately update the orientation. Otherwise
// WindowManager is still deferring layout until it has finished dispatching
// the config changes, which may cause divergence between what we draw
@@ -157,15 +142,10 @@ public class ScreenDecorations extends SystemUI implements Tunable {
// - we are trying to redraw. This because WM resized our window and told us to.
// - the config change has been dispatched, so WM is no longer deferring layout.
mPendingRotationChange = true;
if (DEBUG) {
Log.i(TAG, "Rotation changed, deferring " + newRotation + ", staying at "
+ mRotation);
}
mOverlay.getViewTreeObserver().addOnPreDrawListener(
new RestartingPreDrawListener(mOverlay, newRotation));
new RestartingPreDrawListener(mOverlay));
mBottomOverlay.getViewTreeObserver().addOnPreDrawListener(
new RestartingPreDrawListener(mBottomOverlay, newRotation));
new RestartingPreDrawListener(mBottomOverlay));
}
updateOrientation();
}
@@ -174,7 +154,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
mRotation = -1;
mDisplayManager = (DisplayManager) mContext.getSystemService(
Context.DISPLAY_SERVICE);
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
mDisplayManager.registerDisplayListener(mDisplayListener, null);
}
private void setupDecorations() {
@@ -204,11 +184,10 @@ public class ScreenDecorations extends SystemUI implements Tunable {
mWindowManager.getDefaultDisplay().getMetrics(metrics);
mDensity = metrics.density;
Dependency.get(Dependency.MAIN_HANDLER).post(
() -> Dependency.get(TunerService.class).addTunable(this, SIZE));
Dependency.get(TunerService.class).addTunable(this, SIZE);
// Watch color inversion and invert the overlay as needed.
mColorInversionSetting = new SecureSetting(mContext, mHandler,
mColorInversionSetting = new SecureSetting(mContext, Dependency.get(Dependency.MAIN_HANDLER),
Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
@Override
protected void handleValueChanged(int value, boolean observedChange) {
@@ -220,7 +199,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(mIntentReceiver, filter, null /* permission */, mHandler);
mContext.registerReceiver(mIntentReceiver, filter);
mOverlay.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
@@ -238,11 +217,6 @@ public class ScreenDecorations extends SystemUI implements Tunable {
.start();
}
});
mOverlay.getViewTreeObserver().addOnPreDrawListener(
new ValidatingPreDrawListener(mOverlay));
mBottomOverlay.getViewTreeObserver().addOnPreDrawListener(
new ValidatingPreDrawListener(mBottomOverlay));
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -272,28 +246,14 @@ public class ScreenDecorations extends SystemUI implements Tunable {
@Override
protected void onConfigurationChanged(Configuration newConfig) {
mHandler.post(() -> {
int oldRotation = mRotation;
mPendingRotationChange = false;
updateOrientation();
if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
if (shouldDrawCutout() && mOverlay == null) {
setupDecorations();
}
if (mOverlay != null) {
// Updating the layout params ensures that ViewRootImpl will call relayoutWindow(),
// which ensures that the forced seamless rotation will end, even if we updated
// the rotation before window manager was ready (and was still waiting for sending
// the updated rotation).
updateLayoutParams();
}
});
mPendingRotationChange = false;
updateOrientation();
if (shouldDrawCutout() && mOverlay == null) {
setupDecorations();
}
}
private void updateOrientation() {
Preconditions.checkState(mHandler.getLooper().getThread() == Thread.currentThread(),
"must call on " + mHandler.getLooper().getThread()
+ ", but was " + Thread.currentThread());
protected void updateOrientation() {
if (mPendingRotationChange) {
return;
}
@@ -373,19 +333,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout);
}
private void setupStatusBarPaddingIfNeeded() {
// TODO: This should be moved to a more appropriate place, as it is not related to the
// screen decorations overlay.
int padding = mContext.getResources().getDimensionPixelSize(
R.dimen.rounded_corner_content_padding);
if (padding != 0) {
setupStatusBarPadding(padding);
}
}
private void setupStatusBarPadding(int padding) {
private void setupPadding(int padding) {
// Add some padding to all the content near the edge of the screen.
StatusBar sb = getComponent(StatusBar.class);
View statusBar = (sb != null ? sb.getStatusBarWindow() : null);
@@ -454,32 +402,30 @@ public class ScreenDecorations extends SystemUI implements Tunable {
@Override
public void onTuningChanged(String key, String newValue) {
mHandler.post(() -> {
if (mOverlay == null) return;
if (SIZE.equals(key)) {
int size = mRoundedDefault;
int sizeTop = mRoundedDefaultTop;
int sizeBottom = mRoundedDefaultBottom;
if (newValue != null) {
try {
size = (int) (Integer.parseInt(newValue) * mDensity);
} catch (Exception e) {
}
if (mOverlay == null) return;
if (SIZE.equals(key)) {
int size = mRoundedDefault;
int sizeTop = mRoundedDefaultTop;
int sizeBottom = mRoundedDefaultBottom;
if (newValue != null) {
try {
size = (int) (Integer.parseInt(newValue) * mDensity);
} catch (Exception e) {
}
if (sizeTop == 0) {
sizeTop = size;
}
if (sizeBottom == 0) {
sizeBottom = size;
}
setSize(mOverlay.findViewById(R.id.left), sizeTop);
setSize(mOverlay.findViewById(R.id.right), sizeTop);
setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom);
setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom);
}
});
if (sizeTop == 0) {
sizeTop = size;
}
if (sizeBottom == 0) {
sizeBottom = size;
}
setSize(mOverlay.findViewById(R.id.left), sizeTop);
setSize(mOverlay.findViewById(R.id.right), sizeTop);
setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom);
setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom);
}
}
private void setSize(View view, int pixelSize) {
@@ -538,11 +484,6 @@ public class ScreenDecorations extends SystemUI implements Tunable {
mVisibilityChangedListener = visibilityChangedListener;
mDecorations = decorations;
setId(R.id.display_cutout);
if (DEBUG) {
getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG,
(mInitialStart ? "OverlayTop" : "OverlayBottom")
+ " drawn in rot " + mRotation));
}
}
public void setColor(int color) {
@@ -778,66 +719,20 @@ public class ScreenDecorations extends SystemUI implements Tunable {
private class RestartingPreDrawListener implements ViewTreeObserver.OnPreDrawListener {
private final View mView;
private final int mTargetRotation;
private RestartingPreDrawListener(View view, int targetRotation) {
private RestartingPreDrawListener(View view) {
mView = view;
mTargetRotation = targetRotation;
}
@Override
public boolean onPreDraw() {
mView.getViewTreeObserver().removeOnPreDrawListener(this);
if (mTargetRotation == mRotation) {
if (DEBUG) {
Log.i(TAG, (mView == mOverlay ? "OverlayTop" : "OverlayBottom")
+ " already in target rot "
+ mTargetRotation + ", allow draw without restarting it");
}
return true;
}
mPendingRotationChange = false;
mView.getViewTreeObserver().removeOnPreDrawListener(this);
// This changes the window attributes - we need to restart the traversal for them to
// take effect.
updateOrientation();
if (DEBUG) {
Log.i(TAG, (mView == mOverlay ? "OverlayTop" : "OverlayBottom")
+ " restarting listener fired, restarting draw for rot " + mRotation);
}
mView.invalidate();
return false;
}
}
/**
* A pre-draw listener, that validates that the rotation we draw in matches the displays
* rotation before continuing the draw.
*
* This is to prevent a race condition, where we have not received the display changed event
* yet, and would thus draw in an old orientation.
*/
private class ValidatingPreDrawListener implements ViewTreeObserver.OnPreDrawListener {
private final View mView;
public ValidatingPreDrawListener(View view) {
mView = view;
}
@Override
public boolean onPreDraw() {
final int displayRotation = RotationUtils.getExactRotation(mContext);
if (displayRotation != mRotation && !mPendingRotationChange) {
if (DEBUG) {
Log.i(TAG, "Drawing rot " + mRotation + ", but display is at rot "
+ displayRotation + ". Restarting draw");
}
mView.invalidate();
return false;
}
return true;
}
}
}

View File

@@ -34,10 +34,8 @@ import static org.mockito.Mockito.when;
import android.app.Fragment;
import android.content.res.Configuration;
import android.os.Handler;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.view.Display;
import android.view.View;
@@ -62,7 +60,6 @@ import org.junit.runner.RunWith;
@SmallTest
public class ScreenDecorationsTest extends SysuiTestCase {
private TestableLooper mTestableLooper;
private ScreenDecorations mScreenDecorations;
private StatusBar mStatusBar;
private WindowManager mWindowManager;
@@ -74,10 +71,6 @@ public class ScreenDecorationsTest extends SysuiTestCase {
@Before
public void setup() {
mTestableLooper = TestableLooper.get(this);
mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
new Handler(mTestableLooper.getLooper()));
mStatusBar = mock(StatusBar.class);
mWindowManager = mock(WindowManager.class);
mView = spy(new StatusBarWindowView(mContext, null));
@@ -95,31 +88,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
mTunerService = mDependency.injectMockDependency(TunerService.class);
mScreenDecorations = new ScreenDecorations() {
@Override
public void start() {
super.start();
mTestableLooper.processAllMessages();
}
@Override
Handler startHandlerThread() {
return new Handler(mTestableLooper.getLooper());
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mTestableLooper.processAllMessages();
}
@Override
public void onTuningChanged(String key, String newValue) {
super.onTuningChanged(key, newValue);
mTestableLooper.processAllMessages();
}
};
mScreenDecorations = new ScreenDecorations();
mScreenDecorations.mContext = mContext;
mScreenDecorations.mComponents = mContext.getComponents();

View File

@@ -21,7 +21,6 @@ import static android.view.Surface.ROTATION_90;
import android.graphics.Matrix;
import android.view.DisplayInfo;
import android.view.Surface.Rotation;
import com.android.server.wm.utils.CoordinateTransforms;
@@ -66,16 +65,6 @@ public class ForcedSeamlessRotator {
token.getPendingTransaction().setMatrix(token.getSurfaceControl(), mTransform, mFloat9);
}
/**
* Returns the rotation of the display before it started rotating.
*
* @return the old rotation of the display
*/
@Rotation
public int getOldRotation() {
return mOldRotation;
}
/**
* Removes the transform to the window token's surface that undoes the effect of the global
* display rotation.

View File

@@ -634,10 +634,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void forceSeamlesslyRotateIfAllowed(int oldRotation, int rotation) {
if (mForceSeamlesslyRotate) {
if (mPendingForcedSeamlessRotate != null) {
oldRotation = mPendingForcedSeamlessRotate.getOldRotation();
}
mPendingForcedSeamlessRotate = new ForcedSeamlessRotator(
oldRotation, rotation, getDisplayInfo());
mPendingForcedSeamlessRotate.unrotate(this.mToken);