Merge "Surface: Use buffer id to synchronize slots" into oc-dev
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 43d0780..68cb0d7 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -64,6 +64,25 @@
namespace android {
namespace installd {
+// Check expected values for dexopt flags. If you need to change this:
+//
+// RUN AN A/B OTA TO MAKE SURE THINGS STILL WORK!
+//
+// You most likely need to increase the protocol version and all that entails!
+
+static_assert(DEXOPT_PUBLIC == 1 << 1, "DEXOPT_PUBLIC unexpected.");
+static_assert(DEXOPT_DEBUGGABLE == 1 << 2, "DEXOPT_DEBUGGABLE unexpected.");
+static_assert(DEXOPT_BOOTCOMPLETE == 1 << 3, "DEXOPT_BOOTCOMPLETE unexpected.");
+static_assert(DEXOPT_PROFILE_GUIDED == 1 << 4, "DEXOPT_PROFILE_GUIDED unexpected.");
+static_assert(DEXOPT_SECONDARY_DEX == 1 << 5, "DEXOPT_SECONDARY_DEX unexpected.");
+static_assert(DEXOPT_FORCE == 1 << 6, "DEXOPT_FORCE unexpected.");
+static_assert(DEXOPT_STORAGE_CE == 1 << 7, "DEXOPT_STORAGE_CE unexpected.");
+static_assert(DEXOPT_STORAGE_DE == 1 << 8, "DEXOPT_STORAGE_DE unexpected.");
+
+static_assert(DEXOPT_MASK == 0x1fe, "DEXOPT_MASK unexpected.");
+
+
+
template<typename T>
static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index fe16b76..d5498ed 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -103,7 +103,7 @@
mLastFrameNumberReceived(0),
mUpdateTexImageFailed(false),
mAutoRefresh(false),
- mFreezePositionUpdates(false)
+ mFreezeGeometryUpdates(false)
{
#ifdef USE_HWC2
ALOGV("Creating Layer %s", name.string());
@@ -131,6 +131,8 @@
mCurrentState.active.transform.set(0, 0);
mCurrentState.crop.makeInvalid();
mCurrentState.finalCrop.makeInvalid();
+ mCurrentState.requestedFinalCrop = mCurrentState.finalCrop;
+ mCurrentState.requestedCrop = mCurrentState.crop;
mCurrentState.z = 0;
#ifdef USE_HWC2
mCurrentState.alpha = 1.0f;
@@ -1641,12 +1643,25 @@
}
}
- // always set active to requested, unless we're asked not to
- // this is used by Layer, which special cases resizes.
- if (flags & eDontUpdateGeometryState) {
- } else {
+ // Here we apply various requested geometry states, depending on our
+ // latching configuration. See Layer.h for a detailed discussion of
+ // how geometry latching is controlled.
+ if (!(flags & eDontUpdateGeometryState)) {
Layer::State& editCurrentState(getCurrentState());
- if (mFreezePositionUpdates) {
+
+ // If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize
+ // mode, which causes attributes which normally latch regardless of scaling mode,
+ // to be delayed. We copy the requested state to the active state making sure
+ // to respect these rules (again see Layer.h for a detailed discussion).
+ //
+ // There is an awkward asymmetry in the handling of the crop states in the position
+ // states, as can be seen below. Largely this arises from position and transform
+ // being stored in the same data structure while having different latching rules.
+ // b/38182305
+ //
+ // Careful that "c" and editCurrentState may not begin as equivalent due to
+ // applyPendingStates in the presence of deferred transactions.
+ if (mFreezeGeometryUpdates) {
float tx = c.active.transform.tx();
float ty = c.active.transform.ty();
c.active = c.requested;
@@ -1707,10 +1722,14 @@
// we want to apply the position portion of the transform matrix immediately,
// but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
mCurrentState.requested.transform.set(x, y);
- if (immediate && !mFreezePositionUpdates) {
+ if (immediate && !mFreezeGeometryUpdates) {
+ // Here we directly update the active state
+ // unlike other setters, because we store it within
+ // the transform, but use different latching rules.
+ // b/38182305
mCurrentState.active.transform.set(x, y);
}
- mFreezePositionUpdates = mFreezePositionUpdates || !immediate;
+ mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -1833,26 +1852,30 @@
}
bool Layer::setCrop(const Rect& crop, bool immediate) {
- if (mCurrentState.crop == crop)
+ if (mCurrentState.requestedCrop == crop)
return false;
mCurrentState.sequence++;
mCurrentState.requestedCrop = crop;
- if (immediate) {
+ if (immediate && !mFreezeGeometryUpdates) {
mCurrentState.crop = crop;
}
+ mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
+
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
bool Layer::setFinalCrop(const Rect& crop, bool immediate) {
- if (mCurrentState.finalCrop == crop)
+ if (mCurrentState.requestedFinalCrop == crop)
return false;
mCurrentState.sequence++;
mCurrentState.requestedFinalCrop = crop;
- if (immediate) {
+ if (immediate && !mFreezeGeometryUpdates) {
mCurrentState.finalCrop = crop;
}
+ mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
+
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
@@ -2142,7 +2165,7 @@
bool queuedBuffer = false;
LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
getProducerStickyTransform() != 0, mName.string(),
- mOverrideScalingMode, mFreezePositionUpdates);
+ mOverrideScalingMode, mFreezeGeometryUpdates);
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
mLastFrameNumberReceived);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9f45435..05c367d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -169,25 +169,64 @@
// the this layer's size and format
status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
- // modify current state
+ // ------------------------------------------------------------------------
+ // Geometry setting functions.
+ //
+ // The following group of functions are used to specify the layers
+ // bounds, and the mapping of the texture on to those bounds. According
+ // to various settings changes to them may apply immediately, or be delayed until
+ // a pending resize is completed by the producer submitting a buffer. For example
+ // if we were to change the buffer size, and update the matrix ahead of the
+ // new buffer arriving, then we would be stretching the buffer to a different
+ // aspect before and after the buffer arriving, which probably isn't what we wanted.
+ //
+ // The first set of geometry functions are controlled by the scaling mode, described
+ // in window.h. The scaling mode may be set by the client, as it submits buffers.
+ // This value may be overriden through SurfaceControl, with setOverrideScalingMode.
+ //
+ // Put simply, if our scaling mode is SCALING_MODE_FREEZE, then
+ // matrix updates will not be applied while a resize is pending
+ // and the size and transform will remain in their previous state
+ // until a new buffer is submitted. If the scaling mode is another value
+ // then the old-buffer will immediately be scaled to the pending size
+ // and the new matrix will be immediately applied following this scaling
+ // transformation.
- // These members of state (position, crop, and finalCrop)
- // may be updated immediately or have the update delayed
- // until a pending surface resize completes (if applicable).
+ // Set the default buffer size for the assosciated Producer, in pixels. This is
+ // also the rendered size of the layer prior to any transformations. Parent
+ // or local matrix transformations will not affect the size of the buffer,
+ // but may affect it's on-screen size or clipping.
+ bool setSize(uint32_t w, uint32_t h);
+ // Set a 2x2 transformation matrix on the layer. This transform
+ // will be applied after parent transforms, but before any final
+ // producer specified transform.
+ bool setMatrix(const layer_state_t::matrix22_t& matrix);
+
+ // This second set of geometry attributes are controlled by
+ // setGeometryAppliesWithResize, and their default mode is to be
+ // immediate. If setGeometryAppliesWithResize is specified
+ // while a resize is pending, then update of these attributes will
+ // be delayed until the resize completes.
+
+ // setPosition operates in parent buffer space (pre parent-transform) or display
+ // space for top-level layers.
bool setPosition(float x, float y, bool immediate);
+ // Buffer space
bool setCrop(const Rect& crop, bool immediate);
+ // Parent buffer space/display space
bool setFinalCrop(const Rect& crop, bool immediate);
+ // TODO(b/38182121): Could we eliminate the various latching modes by
+ // using the layer hierarchy?
+ // -----------------------------------------------------------------------
bool setLayer(int32_t z);
bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
- bool setSize(uint32_t w, uint32_t h);
#ifdef USE_HWC2
bool setAlpha(float alpha);
#else
bool setAlpha(uint8_t alpha);
#endif
- bool setMatrix(const layer_state_t::matrix22_t& matrix);
bool setTransparentRegionHint(const Region& transparent);
bool setFlags(uint8_t flags, uint8_t mask);
bool setLayerStack(uint32_t layerStack);
@@ -754,7 +793,7 @@
bool mUpdateTexImageFailed; // This is only accessed on the main thread.
bool mAutoRefresh;
- bool mFreezePositionUpdates;
+ bool mFreezeGeometryUpdates;
// Child list about to be committed/used for editing.
LayerVector mCurrentChildren;
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index 0b302eb..6e37b45 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -37,7 +37,7 @@
mStickyTransformSet(stickySet),
mName(name),
mOverrideScalingMode(overrideScalingMode),
- mFreezePositionUpdates(freezePositionUpdates) {}
+ mFreezeGeometryUpdates(freezePositionUpdates) {}
bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
if (buf == NULL) {
@@ -73,6 +73,19 @@
// recompute visible region
mRecomputeVisibleRegions = true;
+
+ mFreezeGeometryUpdates = false;
+
+ if (mFront.crop != mFront.requestedCrop) {
+ mFront.crop = mFront.requestedCrop;
+ mCurrent.crop = mFront.requestedCrop;
+ mRecomputeVisibleRegions = true;
+ }
+ if (mFront.finalCrop != mFront.requestedFinalCrop) {
+ mFront.finalCrop = mFront.requestedFinalCrop;
+ mCurrent.finalCrop = mFront.requestedFinalCrop;
+ mRecomputeVisibleRegions = true;
+ }
}
ALOGD_IF(DEBUG_RESIZE,
@@ -100,6 +113,10 @@
// conservative, but that's fine, worst case we're doing
// a bit of extra work), we latch the new one and we
// trigger a visible-region recompute.
+ //
+ // We latch the transparent region here, instead of above where we latch
+ // the rest of the geometry because it is only content but not necessarily
+ // resize dependent.
if (!mFront.activeTransparentRegion.isTriviallyEqual(mFront.requestedTransparentRegion)) {
mFront.activeTransparentRegion = mFront.requestedTransparentRegion;
@@ -115,18 +132,6 @@
mRecomputeVisibleRegions = true;
}
- if (mFront.crop != mFront.requestedCrop) {
- mFront.crop = mFront.requestedCrop;
- mCurrent.crop = mFront.requestedCrop;
- mRecomputeVisibleRegions = true;
- }
- if (mFront.finalCrop != mFront.requestedFinalCrop) {
- mFront.finalCrop = mFront.requestedFinalCrop;
- mCurrent.finalCrop = mFront.requestedFinalCrop;
- mRecomputeVisibleRegions = true;
- }
- mFreezePositionUpdates = false;
-
return false;
}
diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h
index c2a9483..828cd8b 100644
--- a/services/surfaceflinger/LayerRejecter.h
+++ b/services/surfaceflinger/LayerRejecter.h
@@ -40,8 +40,8 @@
bool mStickyTransformSet;
const char *mName;
int32_t mOverrideScalingMode;
- bool &mFreezePositionUpdates;
+ bool &mFreezeGeometryUpdates;
};
} // namespace android
-#endif // ANDROID_LAYER_REJECTER_H
\ No newline at end of file
+#endif // ANDROID_LAYER_REJECTER_H
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 1b17e55..68519a1 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -33,7 +33,7 @@
// Fill an RGBA_8888 formatted surface with a single color.
static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc,
- uint8_t r, uint8_t g, uint8_t b) {
+ uint8_t r, uint8_t g, uint8_t b, bool unlock=true) {
ANativeWindow_Buffer outBuffer;
sp<Surface> s = sc->getSurface();
ASSERT_TRUE(s != NULL);
@@ -48,7 +48,9 @@
pixel[3] = 255;
}
}
- ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+ if (unlock) {
+ ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+ }
}
// A ScreenCapture is a screenshot from SurfaceFlinger that can be used to check
@@ -479,6 +481,17 @@
sc->expectFGColor(127, 127);
sc->expectBGColor(128, 128);
}
+
+ void lockAndFillFGBuffer() {
+ fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false);
+ }
+
+ void unlockFGBuffer() {
+ sp<Surface> s = mFGSurfaceControl->getSurface();
+ ASSERT_EQ(NO_ERROR, s->unlockAndPost());
+ waitForPostedBuffers();
+ }
+
void completeFGResize() {
fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
waitForPostedBuffers();
@@ -605,6 +618,65 @@
EXPECT_CROPPED_STATE("after the resize finishes");
}
+// In this test we ensure that setGeometryAppliesWithResize actually demands
+// a buffer of the new size, and not just any size.
+TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) {
+ EXPECT_INITIAL_STATE("before anything");
+ // Normally the crop applies immediately even while a resize is pending.
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setSize(128, 128);
+ mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
+
+ restoreInitialState();
+
+ // In order to prepare to submit a buffer at the wrong size, we acquire it prior to
+ // initiating the resize.
+ lockAndFillFGBuffer();
+
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setSize(128, 128);
+ mFGSurfaceControl->setGeometryAppliesWithResize();
+ mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
+
+ // We now submit our old buffer, at the old size, and ensure it doesn't
+ // trigger geometry latching.
+ unlockFGBuffer();
+
+ EXPECT_INITIAL_STATE("after unlocking FG buffer (with geometryAppliesWithResize)");
+
+ completeFGResize();
+
+ EXPECT_CROPPED_STATE("after the resize finishes");
+}
+
+TEST_F(CropLatchingTest, FinalCropLatchingRegressionForb37531386) {
+ EXPECT_INITIAL_STATE("before anything");
+ // In this scenario, we attempt to set the final crop a second time while the resize
+ // is still pending, and ensure we are successful. Success meaning the second crop
+ // is the one which eventually latches and not the first.
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setSize(128, 128);
+ mFGSurfaceControl->setGeometryAppliesWithResize();
+ mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ SurfaceComposerClient::openGlobalTransaction();
+ mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+ EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize");
+
+ completeFGResize();
+
+ EXPECT_INITIAL_STATE("after the resize finishes");
+}
+
TEST_F(LayerUpdateTest, DeferredTransactionTest) {
sp<ScreenCapture> sc;
{