Update hole punch logic in HWUI

--Updated HWUI holepunch logic for SurfaceView to
also apply the stretch to the hole punch
--Updated RenderNode callbacks to also include
an offset from the ancestor RenderNode that also
has a stretch configured on it
--Added new test activity to verify hole punch
logic

Bug: 179047472
Test: manual
Change-Id: Ibbaf8248a31839ba9dc352ecb9fef54e1276918e
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index 0bf9480..94fe243 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -197,6 +197,27 @@
     }
 }
 
+static void computeTransformImpl(const DirtyStack* frame, const DirtyStack* end,
+                                 Matrix4* outMatrix) {
+  while (frame != end) {
+    switch (frame->type) {
+        case TransformRenderNode:
+            frame->renderNode->applyViewPropertyTransforms(*outMatrix);
+            break;
+        case TransformMatrix4:
+            outMatrix->multiply(*frame->matrix4);
+            break;
+        case TransformNone:
+            // nothing to be done
+            break;
+        default:
+            LOG_ALWAYS_FATAL("Tried to compute transform with an invalid type: %d",
+                             frame->type);
+    }
+    frame = frame->prev;
+  }
+}
+
 void DamageAccumulator::applyRenderNodeTransform(DirtyStack* frame) {
     if (frame->pendingDirty.isEmpty()) {
         return;
@@ -249,19 +270,38 @@
     mHead->pendingDirty.setEmpty();
 }
 
-const StretchEffect* DamageAccumulator::findNearestStretchEffect() const {
+DamageAccumulator::StretchResult DamageAccumulator::findNearestStretchEffect() const {
     DirtyStack* frame = mHead;
     while (frame->prev != frame) {
-        frame = frame->prev;
         if (frame->type == TransformRenderNode) {
+            const auto& renderNode = frame->renderNode;
+            const auto& frameRenderNodeProperties = renderNode->properties();
             const auto& effect =
-                    frame->renderNode->properties().layerProperties().getStretchEffect();
+                    frameRenderNodeProperties.layerProperties().getStretchEffect();
+            const float width = (float) renderNode->getWidth();
+            const float height = (float) renderNode->getHeight();
             if (!effect.isEmpty()) {
-                return &effect;
+                Matrix4 stretchMatrix;
+                computeTransformImpl(mHead, frame, &stretchMatrix);
+                Rect stretchRect = Rect(0.f, 0.f, width, height);
+                stretchMatrix.mapRect(stretchRect);
+
+                return StretchResult{
+                    .stretchEffect = &effect,
+                    .childRelativeBounds = SkRect::MakeLTRB(
+                        stretchRect.left,
+                        stretchRect.top,
+                        stretchRect.right,
+                        stretchRect.bottom
+                    ),
+                    .width = width,
+                    .height = height
+                };
             }
         }
+        frame = frame->prev;
     }
-    return nullptr;
+    return StretchResult{};
 }
 
 } /* namespace uirenderer */