Add border API to surface control

See go/sf-box-shadows-api for more details

Bug: b/367464660
Flag: com.android.window.flags.enable_border_settings
Test: atest SurfaceFlinger_test
Change-Id: I1190edb97693004d9f46058fd0165451470a65b3
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index f9b84fa..39182aa 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -52,6 +52,7 @@
         "libtonemap",
         "libsurfaceflinger_common",
         "libsurfaceflingerflags",
+        "libgui_window_info_static",
     ],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
@@ -122,7 +123,13 @@
         "skia_renderengine_deps",
         "libsurfaceflinger_common_deps",
     ],
-    static_libs: ["libskia_renderengine"],
+    static_libs: [
+        "libgui_window_info_static",
+        "libskia_renderengine",
+    ],
+    shared_libs: [
+        "libbinder",
+    ],
 }
 
 // Note: if compilation fails when adding librenderengine as a dependency, try adding
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index ecb16b2..3523497 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <android/gui/BorderSettings.h>
 #include <gui/DisplayLuts.h>
 #include <math/mat4.h>
 #include <math/vec3.h>
@@ -71,6 +72,10 @@
     // Boundaries of the layer.
     FloatRect boundaries = FloatRect();
 
+    // Boundaries of the layer before transparent region hint is subtracted.
+    // Effects like shadows and outline ignore the transparent region hint.
+    FloatRect originalBounds = FloatRect();
+
     // Transform matrix to apply to mesh coordinates.
     mat4 positionTransform = mat4();
 
@@ -127,6 +132,8 @@
 
     ShadowSettings shadow;
 
+    gui::BorderSettings borderSettings;
+
     int backgroundBlurRadius = 0;
 
     std::vector<BlurRegion> blurRegions;
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index 9e1c226..5b6edb4 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -986,6 +986,30 @@
             drawShadow(canvas, rrect, layer.shadow);
         }
 
+        // Similar to shadows, do the rendering before the clip is applied because even when the
+        // layer is occluded it should have an outline.
+        if (layer.borderSettings.strokeWidth > 0) {
+            // TODO(b/367464660): Move this code to the parent scope and
+            // update shadow rendering above to use these bounds since they should be
+            // identical.
+            SkRRect originalBounds, originalClip;
+            std::tie(originalBounds, originalClip) =
+                    getBoundsAndClip(layer.geometry.boundaries, layer.geometry.roundedCornersCrop,
+                                     layer.geometry.roundedCornersRadius);
+            const SkRRect& preferredOriginalBounds =
+                    originalBounds.isRect() && !originalClip.isEmpty() ? originalClip
+                                                                       : originalBounds;
+
+            SkRRect outlineRect = preferredOriginalBounds;
+            outlineRect.outset(layer.borderSettings.strokeWidth, layer.borderSettings.strokeWidth);
+
+            SkPaint paint;
+            paint.setAntiAlias(true);
+            paint.setColor(layer.borderSettings.color);
+            paint.setStyle(SkPaint::kFill_Style);
+            canvas->drawDRRect(outlineRect, preferredOriginalBounds, paint);
+        }
+
         const float layerDimmingRatio = layer.whitePointNits <= 0.f
                 ? displayDimmingRatio
                 : (layer.whitePointNits / maxLayerWhitePoint) * displayDimmingRatio;