Rounded corners

Test: visual
Test: /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test
Fixes: 111514493
Change-Id: Ie8f400bbcea3e9653295ea7b75c7eef568fd76c4
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index b862278..fd40f6c 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -641,15 +641,21 @@
     texCoords[2] = vec2(right, 1.0f - bottom);
     texCoords[3] = vec2(right, 1.0f - top);
 
+    const auto roundedCornerState = getRoundedCornerState();
+    const auto cropRect = roundedCornerState.cropRect;
+    setupRoundedCornersCropCoordinates(win, cropRect);
+
     auto& engine(mFlinger->getRenderEngine());
     engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */,
-                              getColor());
+                              getColor(), roundedCornerState.radius);
     engine.setSourceDataSpace(mCurrentDataSpace);
 
     if (isHdrY410()) {
         engine.setSourceY410BT2020(true);
     }
 
+    engine.setupCornerRadiusCropSize(cropRect.getWidth(), cropRect.getHeight());
+
     engine.drawMesh(getBE().mMesh);
     engine.disableBlending();
 
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 9c34308..f27f6aa 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -45,9 +45,18 @@
         renderengine::Mesh mesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2);
         computeGeometry(renderArea, mesh, useIdentityTransform);
         auto& engine(mFlinger->getRenderEngine());
+
+        Rect win{computeBounds()};
+
+        const auto roundedCornerState = getRoundedCornerState();
+        const auto cropRect = roundedCornerState.cropRect;
+        setupRoundedCornersCropCoordinates(win, cropRect);
+
         engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */,
-                                  true /* disableTexture */, color);
+                                  true /* disableTexture */, color, roundedCornerState.radius);
+
         engine.setSourceDataSpace(mCurrentDataSpace);
+        engine.setupCornerRadiusCropSize(cropRect.getWidth(), cropRect.getHeight());
         engine.drawMesh(mesh);
         engine.disableBlending();
     }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 81456df..4080f12 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -101,6 +101,7 @@
     mCurrentState.dataspace = ui::Dataspace::UNKNOWN;
     mCurrentState.hdrMetadata.validTypes = 0;
     mCurrentState.surfaceDamageRegion.clear();
+    mCurrentState.cornerRadius = 0.0f;
     mCurrentState.api = -1;
     mCurrentState.hasColorTransform = false;
 
@@ -400,6 +401,23 @@
     return activeCrop;
 }
 
+void Layer::setupRoundedCornersCropCoordinates(Rect win,
+                                               const FloatRect& roundedCornersCrop) const {
+    // Translate win by the rounded corners rect coordinates, to have all values in
+    // layer coordinate space.
+    win.left -= roundedCornersCrop.left;
+    win.right -= roundedCornersCrop.left;
+    win.top -= roundedCornersCrop.top;
+    win.bottom -= roundedCornersCrop.top;
+
+    renderengine::Mesh::VertexArray<vec2> cropCoords(getBE().mMesh.getCropCoordArray<vec2>());
+    cropCoords[0] = vec2(win.left, win.top);
+    cropCoords[1] = vec2(win.left, win.top + win.getHeight());
+    cropCoords[2] = vec2(win.right, win.top + win.getHeight());
+    cropCoords[3] = vec2(win.right, win.top);
+    cropCoords[3] = vec2(win.right, win.top);
+}
+
 FloatRect Layer::computeCrop(const sp<const DisplayDevice>& display) const {
     // the content crop is the area of the content that gets scaled to the
     // layer's size. This is in buffer space.
@@ -1220,6 +1238,17 @@
     return true;
 }
 
+bool Layer::setCornerRadius(float cornerRadius) {
+    if (mCurrentState.cornerRadius == cornerRadius)
+        return false;
+
+    mCurrentState.sequence++;
+    mCurrentState.cornerRadius = cornerRadius;
+    mCurrentState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+
 bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix,
         bool allowNonRectPreservingTransforms) {
     ui::Transform t;
@@ -1918,6 +1947,26 @@
     return half4(color.r, color.g, color.b, getAlpha());
 }
 
+Layer::RoundedCornerState Layer::getRoundedCornerState() const {
+    const auto& p = mDrawingParent.promote();
+    if (p != nullptr) {
+        RoundedCornerState parentState = p->getRoundedCornerState();
+        if (parentState.radius > 0) {
+            ui::Transform t = getActiveTransform(getDrawingState());
+            t = t.inverse();
+            parentState.cropRect = t.transform(parentState.cropRect);
+            // The rounded corners shader only accepts 1 corner radius for performance reasons,
+            // but a transform matrix can define horizontal and vertical scales.
+            // Let's take the average between both of them and pass into the shader, practically we
+            // never do this type of transformation on windows anyway.
+            parentState.radius *= (t[0][0] + t[1][1]) / 2.0f;
+            return parentState;
+        }
+    }
+    const float radius = getDrawingState().cornerRadius;
+    return radius > 0 ? RoundedCornerState(computeBounds(), radius) : RoundedCornerState();
+}
+
 void Layer::commitChildList() {
     for (size_t i = 0; i < mCurrentChildren.size(); i++) {
         const auto& child = mCurrentChildren[i];
@@ -1978,6 +2027,7 @@
     size->set_h(state.active_legacy.h);
 
     LayerProtoHelper::writeToProto(state.crop_legacy, layerInfo->mutable_crop());
+    layerInfo->set_corner_radius(getRoundedCornerState().radius);
 
     layerInfo->set_is_opaque(isOpaque(state));
     layerInfo->set_invalidate(contentDirty);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a4f9c93..687fc0a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -125,6 +125,17 @@
         inline bool operator!=(const Geometry& rhs) const { return !operator==(rhs); }
     };
 
+    struct RoundedCornerState {
+        RoundedCornerState() = default;
+        RoundedCornerState(FloatRect cropRect, float radius)
+              : cropRect(cropRect), radius(radius) {}
+
+        // Rounded rectangle in local layer coordinate space.
+        FloatRect cropRect = FloatRect();
+        // Radius of the rounded rectangle.
+        float radius = 0.0f;
+    };
+
     struct State {
         Geometry active_legacy;
         Geometry requested_legacy;
@@ -167,6 +178,7 @@
         SortedVector<wp<Layer>> zOrderRelatives;
 
         half4 color;
+        float cornerRadius;
 
         bool inputInfoChanged;
         InputWindowInfo inputInfo;
@@ -255,6 +267,13 @@
 
     virtual bool setAlpha(float alpha);
     virtual bool setColor(const half3& color);
+
+    // Set rounded corner radius for this layer and its children.
+    //
+    // We only support 1 radius per layer in the hierarchy, where parent layers have precedence.
+    // The shape of the rounded corner rectangle is specified by the crop rectangle of the layer
+    // from which we inferred the rounded corner radius.
+    virtual bool setCornerRadius(float cornerRadius);
     virtual bool setTransparentRegionHint(const Region& transparent);
     virtual bool setFlags(uint8_t flags, uint8_t mask);
     virtual bool setLayerStack(uint32_t layerStack);
@@ -573,6 +592,13 @@
     half getAlpha() const;
     half4 getColor() const;
 
+    // Returns how rounded corners should be drawn for this layer.
+    // This will traverse the hierarchy until it reaches its root, finding topmost rounded
+    // corner definition and converting it into current layer's coordinates.
+    // As of now, only 1 corner radius per display list is supported. Subsequent ones will be
+    // ignored.
+    RoundedCornerState getRoundedCornerState() const;
+
     void traverseInReverseZOrder(LayerVector::StateSet stateSet,
                                  const LayerVector::Visitor& visitor);
     void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor);
@@ -645,11 +671,15 @@
     // IGraphicBufferProducer client, as that should not affect child clipping.
     // Returns in screen space.
     Rect computeInitialCrop(const sp<const DisplayDevice>& display) const;
+    /**
+     * Setup rounded corners coordinates of this layer, taking into account the layer bounds and
+     * crop coordinates, transforming them into layer space.
+     */
+    void setupRoundedCornersCropCoordinates(Rect win, const FloatRect& roundedCornersCrop) const;
 
     // drawing
     void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b,
                          float alpha) const;
-
     void setParent(const sp<Layer>& layer);
 
     LayerVector makeTraversalList(LayerVector::StateSet stateSet, bool* outSkipRelativeZUsers);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3e5920f..5b3c477 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1687,6 +1687,10 @@
                 layer->forceClientComposition(*displayId);
             }
 
+            if (layer->getRoundedCornerState().radius > 0.0f) {
+                layer->forceClientComposition(*displayId);
+            }
+
             if (layer->getForceClientComposition(*displayId)) {
                 ALOGV("[%s] Requesting Client composition", layer->getName().string());
                 layer->setCompositionType(*displayId, HWC2::Composition::Client);
@@ -2876,6 +2880,7 @@
                 // compute the opaque region
                 const int32_t layerOrientation = tr.getOrientation();
                 if (layer->getAlpha() == 1.0f && !translucent &&
+                        layer->getRoundedCornerState().radius == 0.0f &&
                         ((layerOrientation & ui::Transform::ROT_INVALID) == false)) {
                     // the opaque region is the layer's footprint
                     opaqueRegion = visibleRegion;
@@ -3166,7 +3171,7 @@
                     const Layer::State& state(layer->getDrawingState());
                     if (layer->getClearClientTarget(*displayId) && !firstLayer &&
                         layer->isOpaque(state) && (layer->getAlpha() == 1.0f) &&
-                        hasClientComposition) {
+                        layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) {
                         // never clear the very first layer since we're
                         // guaranteed the FB is already cleared
                         layer->clearWithOpenGL(renderArea);
@@ -3586,6 +3591,10 @@
         if (layer->setCrop_legacy(s.crop_legacy, !geometryAppliesWithResize))
             flags |= eTraversalNeeded;
     }
+    if (what & layer_state_t::eCornerRadiusChanged) {
+        if (layer->setCornerRadius(s.cornerRadius))
+            flags |= eTraversalNeeded;
+    }
     if (what & layer_state_t::eLayerStackChanged) {
         ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
         // We only allow setting layer stacks for top level layers,
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 55cfa4b..7bfe033 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -109,6 +109,7 @@
                                layer->mCurrentState.activeTransparentRegion_legacy);
     addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack);
     addCropLocked(transaction, layerId, layer->mCurrentState.crop_legacy);
+    addCornerRadiusLocked(transaction, layerId, layer->mCurrentState.cornerRadius);
     if (layer->mCurrentState.barrierLayer_legacy != nullptr) {
         addDeferTransactionLocked(transaction, layerId,
                                   layer->mCurrentState.barrierLayer_legacy.promote(),
@@ -289,6 +290,14 @@
     setProtoRectLocked(protoRect, rect);
 }
 
+void SurfaceInterceptor::addCornerRadiusLocked(Transaction* transaction, int32_t layerId,
+                                       float cornerRadius)
+{
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+    CornerRadiusChange* cornerRadiusChange(change->mutable_corner_radius());
+    cornerRadiusChange->set_corner_radius(cornerRadius);
+}
+
 void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
         const sp<const Layer>& layer, uint64_t frameNumber)
 {
@@ -350,6 +359,9 @@
     if (state.what & layer_state_t::eCropChanged_legacy) {
         addCropLocked(transaction, layerId, state.crop_legacy);
     }
+    if (state.what & layer_state_t::eCornerRadiusChanged) {
+        addCornerRadiusLocked(transaction, layerId, state.cornerRadius);
+    }
     if (state.what & layer_state_t::eDeferTransaction_legacy) {
         sp<Layer> otherLayer = nullptr;
         if (state.barrierHandle_legacy != nullptr) {
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 394b99b..563a44c 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -144,6 +144,7 @@
     void addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags);
     void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack);
     void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
+    void addCornerRadiusLocked(Transaction* transaction, int32_t layerId, float cornerRadius);
     void addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
             const sp<const Layer>& layer, uint64_t frameNumber);
     void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId,
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index 1d7fb67..d020a39 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -121,6 +121,7 @@
     layer.appId = layerProto.app_id();
     layer.hwcCompositionType = layerProto.hwc_composition_type();
     layer.isProtected = layerProto.is_protected();
+    layer.cornerRadius = layerProto.corner_radius();
 
     return layer;
 }
@@ -294,6 +295,7 @@
                   size.y);
 
     StringAppendF(&result, "crop=%s, ", crop.to_string().c_str());
+    StringAppendF(&result, "cornerRadius=%f, ", cornerRadius);
     StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate);
     StringAppendF(&result, "dataspace=%s, ", dataspace.c_str());
     StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str());
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index 6b3b497..a794ca5 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -114,6 +114,7 @@
         int32_t appId;
         int32_t hwcCompositionType;
         bool isProtected;
+        float cornerRadius;
 
         std::string to_string() const;
     };
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index c141ee3..b100438 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -87,6 +87,8 @@
   // If active_buffer is not null, record its transform.
   optional TransformProto buffer_transform = 39;
   optional int32 effective_scaling_mode = 40;
+  // Layer's corner radius.
+  optional float corner_radius = 41;
 }
 
 message PositionProto {
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 740d2fa..e506757 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -44,6 +44,7 @@
 constexpr uint32_t STACK_UPDATE = 1;
 constexpr uint64_t DEFERRED_UPDATE = 0;
 constexpr float ALPHA_UPDATE = 0.29f;
+constexpr float CORNER_RADIUS_UPDATE = 0.2f;
 constexpr float POSITION_UPDATE = 121;
 const Rect CROP_UPDATE(16, 16, 32, 32);
 
@@ -167,6 +168,7 @@
     bool alphaUpdateFound(const SurfaceChange& change, bool foundAlpha);
     bool layerUpdateFound(const SurfaceChange& change, bool foundLayer);
     bool cropUpdateFound(const SurfaceChange& change, bool foundCrop);
+    bool cornerRadiusUpdateFound(const SurfaceChange& change, bool foundCornerRadius);
     bool matrixUpdateFound(const SurfaceChange& change, bool foundMatrix);
     bool scalingModeUpdateFound(const SurfaceChange& change, bool foundScalingMode);
     bool transparentRegionHintUpdateFound(const SurfaceChange& change, bool foundTransparentRegion);
@@ -198,6 +200,7 @@
     void alphaUpdate(Transaction&);
     void layerUpdate(Transaction&);
     void cropUpdate(Transaction&);
+    void cornerRadiusUpdate(Transaction&);
     void matrixUpdate(Transaction&);
     void overrideScalingModeUpdate(Transaction&);
     void transparentRegionHintUpdate(Transaction&);
@@ -313,6 +316,10 @@
     t.setAlpha(mBGSurfaceControl, ALPHA_UPDATE);
 }
 
+void SurfaceInterceptorTest::cornerRadiusUpdate(Transaction& t) {
+    t.setCornerRadius(mBGSurfaceControl, CORNER_RADIUS_UPDATE);
+}
+
 void SurfaceInterceptorTest::layerUpdate(Transaction& t) {
     t.setLayer(mBGSurfaceControl, LAYER_UPDATE);
 }
@@ -369,6 +376,7 @@
     runInTransaction(&SurfaceInterceptorTest::positionUpdate);
     runInTransaction(&SurfaceInterceptorTest::sizeUpdate);
     runInTransaction(&SurfaceInterceptorTest::alphaUpdate);
+    runInTransaction(&SurfaceInterceptorTest::cornerRadiusUpdate);
     runInTransaction(&SurfaceInterceptorTest::layerUpdate);
     runInTransaction(&SurfaceInterceptorTest::cropUpdate);
     runInTransaction(&SurfaceInterceptorTest::matrixUpdate);
@@ -430,6 +438,17 @@
     return foundAlpha;
 }
 
+bool SurfaceInterceptorTest::cornerRadiusUpdateFound(const SurfaceChange &change,
+                                                     bool foundCornerRadius) {
+    bool hasCornerRadius(change.corner_radius().corner_radius() == CORNER_RADIUS_UPDATE);
+    if (hasCornerRadius && !foundCornerRadius) {
+        foundCornerRadius = true;
+    } else if (hasCornerRadius && foundCornerRadius) {
+        [] () { FAIL(); }();
+    }
+    return foundCornerRadius;
+}
+
 bool SurfaceInterceptorTest::layerUpdateFound(const SurfaceChange& change, bool foundLayer) {
     bool hasLayer(change.layer().layer() == LAYER_UPDATE);
     if (hasLayer && !foundLayer) {
@@ -572,6 +591,9 @@
                         case SurfaceChange::SurfaceChangeCase::kCrop:
                             foundUpdate = cropUpdateFound(change, foundUpdate);
                             break;
+                        case SurfaceChange::SurfaceChangeCase::kCornerRadius:
+                            foundUpdate = cornerRadiusUpdateFound(change, foundUpdate);
+                            break;
                         case SurfaceChange::SurfaceChangeCase::kMatrix:
                             foundUpdate = matrixUpdateFound(change, foundUpdate);
                             break;
@@ -730,6 +752,11 @@
     captureTest(&SurfaceInterceptorTest::cropUpdate, SurfaceChange::SurfaceChangeCase::kCrop);
 }
 
+TEST_F(SurfaceInterceptorTest, InterceptCornerRadiusUpdateWorks) {
+    captureTest(&SurfaceInterceptorTest::cornerRadiusUpdate,
+            SurfaceChange::SurfaceChangeCase::kCornerRadius);
+}
+
 TEST_F(SurfaceInterceptorTest, InterceptMatrixUpdateWorks) {
     captureTest(&SurfaceInterceptorTest::matrixUpdate, SurfaceChange::SurfaceChangeCase::kMatrix);
 }
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 7e95d99..e414991 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -1225,6 +1225,28 @@
     }
 }
 
+TEST_P(LayerTypeTransactionTest, SetCornerRadius) {
+    sp<SurfaceControl> layer;
+    const uint8_t size = 64;
+    const uint8_t testArea = 4;
+    const float cornerRadius = 16.0f;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size));
+    ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size));
+
+    Transaction()
+            .setCornerRadius(layer, cornerRadius)
+            .apply();
+    {
+        auto shot = screenshot();
+        // Transparent corners
+        shot->expectColor(Rect(0, 0, testArea, testArea), Color::BLACK);
+        shot->expectColor(Rect(0, size - testArea, testArea, testArea), Color::BLACK);
+        shot->expectColor(Rect(size - testArea, 0, testArea, testArea), Color::BLACK);
+        shot->expectColor(Rect(size - testArea, size - testArea, testArea, testArea),
+            Color::BLACK);
+    }
+}
+
 TEST_F(LayerTransactionTest, SetColorBasic) {
     sp<SurfaceControl> bufferLayer;
     sp<SurfaceControl> colorLayer;
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index cfaf495..5a6aa92 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -580,7 +580,8 @@
         EXPECT_CALL(*test->mRenderEngine,
                     setupLayerBlending(true, false, false,
                                        half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
-                                             LayerProperties::COLOR[2], LayerProperties::COLOR[3])))
+                                             LayerProperties::COLOR[2], LayerProperties::COLOR[3]),
+                                       0.0f))
                 .Times(1);
 
         EXPECT_CALL(*test->mRenderEngine, createImage())
@@ -626,7 +627,8 @@
         EXPECT_CALL(*test->mRenderEngine,
                     setupLayerBlending(true, false, true,
                                        half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
-                                             LayerProperties::COLOR[2], LayerProperties::COLOR[3])))
+                                             LayerProperties::COLOR[2], LayerProperties::COLOR[3]),
+                                       0.0f))
                 .Times(1);
         EXPECT_CALL(*test->mRenderEngine, drawMesh(_)).Times(1);
         EXPECT_CALL(*test->mRenderEngine, disableBlending()).Times(1);
@@ -690,7 +692,7 @@
         EXPECT_CALL(*test->mRenderEngine,
                     setupLayerBlending(true, false, false,
                                        half4(Base::COLOR[0], Base::COLOR[1], Base::COLOR[2],
-                                             Base::COLOR[3])))
+                                             Base::COLOR[3]), 0.0f))
                 .Times(1);
         EXPECT_CALL(*test->mRenderEngine, setSourceDataSpace(ui::Dataspace::UNKNOWN)).Times(1);
         EXPECT_CALL(*test->mRenderEngine, drawMesh(_)).Times(1);
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index 90c3c20..a416808 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -56,10 +56,11 @@
     MOCK_CONST_METHOD0(checkErrors, void());
     MOCK_METHOD4(setViewportAndProjection,
                  void(size_t, size_t, Rect, ui::Transform::orientation_flags));
-    MOCK_METHOD4(setupLayerBlending, void(bool, bool, bool, const half4&));
+    MOCK_METHOD5(setupLayerBlending, void(bool, bool, bool, const half4&, float));
     MOCK_METHOD1(setupLayerTexturing, void(const Texture&));
     MOCK_METHOD0(setupLayerBlackedOut, void());
     MOCK_METHOD4(setupFillWithColor, void(float, float, float, float));
+    MOCK_METHOD2(setupCornerRadiusCropSize, void(float, float));
     MOCK_METHOD1(setColorTransform, void(const mat4&));
     MOCK_METHOD1(setSaturationMatrix, void(const mat4&));
     MOCK_METHOD0(disableTexturing, void());