Merge "Place mirrored layers offscreen instead of at root." into sc-dev am: 707e8136ea

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/15340011

Change-Id: I678921b6e7a54bcc069379d7fb657653c81e47d8
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d21d1f1..7541510 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3357,7 +3357,7 @@
 status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
                                         const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
                                         const sp<IBinder>& parentHandle,
-                                        const sp<Layer>& parentLayer, bool addToCurrentState,
+                                        const sp<Layer>& parentLayer, bool addToRoot,
                                         uint32_t* outTransformHint) {
     if (mNumLayers >= ISurfaceComposer::MAX_LAYERS) {
         ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
@@ -3369,7 +3369,7 @@
     if (gbc != nullptr) {
         initialProducer = IInterface::asBinder(gbc);
     }
-    setLayerCreatedState(handle, lbc, parentHandle, parentLayer, initialProducer);
+    setLayerCreatedState(handle, lbc, parentHandle, parentLayer, initialProducer, addToRoot);
 
     // Create a transaction includes the initial parent and producer.
     Vector<ComposerState> states;
@@ -3899,7 +3899,7 @@
     sp<Layer> layer = nullptr;
     if (s.surface) {
         if (what & layer_state_t::eLayerCreated) {
-            layer = handleLayerCreatedLocked(s.surface, privileged);
+            layer = handleLayerCreatedLocked(s.surface);
             if (layer) {
                 // put the created layer into mLayersByLocalBinderToken.
                 mLayersByLocalBinderToken.emplace(s.surface->localBinder(), layer);
@@ -4309,9 +4309,9 @@
         return result;
     }
 
-    bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
-    result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,
-                            addToCurrentState, outTransformHint);
+    bool addToRoot = callingThreadHasUnscopedSurfaceFlingerAccess();
+    result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer, addToRoot,
+                            outTransformHint);
     if (result != NO_ERROR) {
         return result;
     }
@@ -6854,10 +6854,10 @@
 
 void SurfaceFlinger::setLayerCreatedState(const sp<IBinder>& handle, const wp<Layer>& layer,
                                           const wp<IBinder>& parent, const wp<Layer> parentLayer,
-                                          const wp<IBinder>& producer) {
+                                          const wp<IBinder>& producer, bool addToRoot) {
     Mutex::Autolock lock(mCreatedLayersLock);
     mCreatedLayers[handle->localBinder()] =
-            std::make_unique<LayerCreatedState>(layer, parent, parentLayer, producer);
+            std::make_unique<LayerCreatedState>(layer, parent, parentLayer, producer, addToRoot);
 }
 
 auto SurfaceFlinger::getLayerCreatedState(const sp<IBinder>& handle) {
@@ -6882,7 +6882,7 @@
     return state;
 }
 
-sp<Layer> SurfaceFlinger::handleLayerCreatedLocked(const sp<IBinder>& handle, bool privileged) {
+sp<Layer> SurfaceFlinger::handleLayerCreatedLocked(const sp<IBinder>& handle) {
     const auto& state = getLayerCreatedState(handle);
     if (!state) {
         return nullptr;
@@ -6895,7 +6895,7 @@
     }
 
     sp<Layer> parent;
-    bool allowAddRoot = privileged;
+    bool allowAddRoot = state->addToRoot;
     if (state->initialParent != nullptr) {
         parent = fromHandleLocked(state->initialParent.promote()).promote();
         if (parent == nullptr) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b9aefc3..2f46e1f 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -901,7 +901,7 @@
     status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
                             const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
                             const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer,
-                            bool addToCurrentState, uint32_t* outTransformHint);
+                            bool addToRoot, uint32_t* outTransformHint);
 
     // Traverse through all the layers and compute and cache its bounds.
     void computeLayerBounds();
@@ -1453,11 +1453,12 @@
     mutable Mutex mCreatedLayersLock;
     struct LayerCreatedState {
         LayerCreatedState(const wp<Layer>& layer, const wp<IBinder>& parent,
-                          const wp<Layer> parentLayer, const wp<IBinder>& producer)
+                          const wp<Layer> parentLayer, const wp<IBinder>& producer, bool addToRoot)
               : layer(layer),
                 initialParent(parent),
                 initialParentLayer(parentLayer),
-                initialProducer(producer) {}
+                initialProducer(producer),
+                addToRoot(addToRoot) {}
         wp<Layer> layer;
         // Indicates the initial parent of the created layer, only used for creating layer in
         // SurfaceFlinger. If nullptr, it may add the created layer into the current root layers.
@@ -1466,6 +1467,10 @@
         // Indicates the initial graphic buffer producer of the created layer, only used for
         // creating layer in SurfaceFlinger.
         wp<IBinder> initialProducer;
+        // Indicates whether the layer getting created should be added at root if there's no parent
+        // and has permission ACCESS_SURFACE_FLINGER. If set to false and no parent, the layer will
+        // be added offscreen.
+        bool addToRoot;
     };
 
     // A temporay pool that store the created layers and will be added to current state in main
@@ -1473,10 +1478,9 @@
     std::unordered_map<BBinder*, std::unique_ptr<LayerCreatedState>> mCreatedLayers;
     void setLayerCreatedState(const sp<IBinder>& handle, const wp<Layer>& layer,
                               const wp<IBinder>& parent, const wp<Layer> parentLayer,
-                              const wp<IBinder>& producer);
+                              const wp<IBinder>& producer, bool addToRoot);
     auto getLayerCreatedState(const sp<IBinder>& handle);
-    sp<Layer> handleLayerCreatedLocked(const sp<IBinder>& handle, bool privileged)
-            REQUIRES(mStateLock);
+    sp<Layer> handleLayerCreatedLocked(const sp<IBinder>& handle) REQUIRES(mStateLock);
 
     std::atomic<ui::Transform::RotationFlags> mDefaultDisplayTransformHint;
 
diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp
index ccf434d..d027865 100644
--- a/services/surfaceflinger/tests/MirrorLayer_test.cpp
+++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp
@@ -18,7 +18,9 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wconversion"
 
+#include <private/android_filesystem_config.h>
 #include "LayerTransactionTest.h"
+#include "utils/TransactionUtils.h"
 
 namespace android {
 
@@ -227,6 +229,50 @@
     }
 }
 
+// Test that the mirror layer is initially offscreen.
+TEST_F(MirrorLayerTest, InitialMirrorState) {
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
+    ui::DisplayMode mode;
+    SurfaceComposerClient::getActiveDisplayMode(display, &mode);
+    const ui::Size& size = mode.resolution;
+
+    sp<SurfaceControl> mirrorLayer = nullptr;
+    {
+        // Run as system to get the ACCESS_SURFACE_FLINGER permission when mirroring
+        UIDFaker f(AID_SYSTEM);
+        // Mirror mChildLayer
+        mirrorLayer = mClient->mirrorSurface(mChildLayer.get());
+        ASSERT_NE(mirrorLayer, nullptr);
+    }
+
+    // Show the mirror layer, but don't reparent to a layer on screen.
+    Transaction()
+            .setPosition(mirrorLayer, 500, 500)
+            .show(mirrorLayer)
+            .setLayer(mirrorLayer, INT32_MAX - 1)
+            .apply();
+
+    {
+        SCOPED_TRACE("Offscreen Mirror");
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, size.getWidth(), 50), Color::RED);
+        shot->expectColor(Rect(0, 0, 50, size.getHeight()), Color::RED);
+        shot->expectColor(Rect(450, 0, size.getWidth(), size.getHeight()), Color::RED);
+        shot->expectColor(Rect(0, 450, size.getWidth(), size.getHeight()), Color::RED);
+        shot->expectColor(Rect(50, 50, 450, 450), Color::GREEN);
+    }
+
+    // Add mirrorLayer as child of mParentLayer so it's shown on the display
+    Transaction().reparent(mirrorLayer, mParentLayer).apply();
+
+    {
+        SCOPED_TRACE("On Screen Mirror");
+        auto shot = screenshot();
+        // Child mirror
+        shot->expectColor(Rect(550, 550, 950, 950), Color::GREEN);
+    }
+}
+
 } // namespace android
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues