SurfaceFlinger: Drop input for blacked out layers

If the window will be blacked out on a display because
the display does not have the secure flag and the layer
has the secure flag set, then drop input.

Test: atest libgui_test
Fixes: 200842159
Change-Id: Idfe245b0f0091e0cafc15c83b25a9d0fd7364174
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 78a8b42..16208a7 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -220,7 +220,7 @@
         t.apply(true);
     }
 
-    void requestFocus() {
+    void requestFocus(int displayId = ADISPLAY_ID_DEFAULT) {
         SurfaceComposerClient::Transaction t;
         FocusRequest request;
         request.token = mInputInfo.token;
@@ -228,7 +228,7 @@
         request.focusedToken = nullptr;
         request.focusedWindowName = "";
         request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
-        request.displayId = 0;
+        request.displayId = displayId;
         t.setFocusedWindow(request);
         t.apply(true);
     }
@@ -255,11 +255,6 @@
 
         mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height));
 
-        // TODO: Fill in from SF?
-        mInputInfo.ownerPid = 11111;
-        mInputInfo.ownerUid = 11111;
-        mInputInfo.displayId = 0;
-
         InputApplicationInfo aInfo;
         aInfo.token = new BBinder();
         aInfo.name = "Test app info";
@@ -373,21 +368,31 @@
     int32_t mBufferPostDelay;
 };
 
-void injectTap(int x, int y) {
-    char *buf1, *buf2;
+void injectTapOnDisplay(int x, int y, int displayId) {
+    char *buf1, *buf2, *bufDisplayId;
     asprintf(&buf1, "%d", x);
     asprintf(&buf2, "%d", y);
+    asprintf(&bufDisplayId, "%d", displayId);
     if (fork() == 0) {
-        execlp("input", "input", "tap", buf1, buf2, NULL);
+        execlp("input", "input", "-d", bufDisplayId, "tap", buf1, buf2, NULL);
+    }
+}
+
+void injectTap(int x, int y) {
+    injectTapOnDisplay(x, y, ADISPLAY_ID_DEFAULT);
+}
+
+void injectKeyOnDisplay(uint32_t keycode, int displayId) {
+    char *buf1, *bufDisplayId;
+    asprintf(&buf1, "%d", keycode);
+    asprintf(&bufDisplayId, "%d", displayId);
+    if (fork() == 0) {
+        execlp("input", "input", "-d", bufDisplayId, "keyevent", buf1, NULL);
     }
 }
 
 void injectKey(uint32_t keycode) {
-    char *buf1;
-    asprintf(&buf1, "%d", keycode);
-    if (fork() == 0) {
-        execlp("input", "input", "keyevent", buf1, NULL);
-    }
+    injectKeyOnDisplay(keycode, ADISPLAY_ID_NONE);
 }
 
 TEST_F(InputSurfacesTest, can_receive_input) {
@@ -946,4 +951,74 @@
     injectKey(AKEYCODE_V);
     EXPECT_EQ(surface->consumeEvent(100), nullptr);
 }
+
+class MultiDisplayTests : public InputSurfacesTest {
+public:
+    MultiDisplayTests() : InputSurfacesTest() { ProcessState::self()->startThreadPool(); }
+    void TearDown() {
+        if (mVirtualDisplay) {
+            SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
+        }
+        InputSurfacesTest::TearDown();
+    }
+
+    void createDisplay(int32_t width, int32_t height, bool isSecure, ui::LayerStack layerStack) {
+        sp<IGraphicBufferConsumer> consumer;
+        BufferQueue::createBufferQueue(&mProducer, &consumer);
+        consumer->setConsumerName(String8("Virtual disp consumer"));
+        consumer->setDefaultBufferSize(width, height);
+
+        mVirtualDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), isSecure);
+        SurfaceComposerClient::Transaction t;
+        t.setDisplaySurface(mVirtualDisplay, mProducer);
+        t.setDisplayFlags(mVirtualDisplay, 0x01 /* DisplayDevice::eReceivesInput */);
+        t.setDisplayLayerStack(mVirtualDisplay, layerStack);
+        t.apply(true);
+    }
+
+    sp<IBinder> mVirtualDisplay;
+    sp<IGraphicBufferProducer> mProducer;
+};
+
+TEST_F(MultiDisplayTests, drop_input_for_secure_layer_on_nonsecure_display) {
+    ui::LayerStack layerStack = ui::LayerStack::fromValue(42);
+    createDisplay(1000, 1000, false /*isSecure*/, layerStack);
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+    surface->doTransaction([&](auto &t, auto &sc) {
+        t.setFlags(sc, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure);
+        t.setLayerStack(sc, layerStack);
+    });
+    surface->showAt(100, 100);
+
+    injectTap(101, 101);
+
+    EXPECT_EQ(surface->consumeEvent(100), nullptr);
+
+    surface->requestFocus(layerStack.id);
+    surface->assertFocusChange(true);
+    injectKeyOnDisplay(AKEYCODE_V, layerStack.id);
+    EXPECT_EQ(surface->consumeEvent(100), nullptr);
+}
+
+TEST_F(MultiDisplayTests, dont_drop_input_for_secure_layer_on_secure_display) {
+    ui::LayerStack layerStack = ui::LayerStack::fromValue(42);
+    createDisplay(1000, 1000, true /*isSecure*/, layerStack);
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+    surface->doTransaction([&](auto &t, auto &sc) {
+        t.setFlags(sc, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure);
+        t.setLayerStack(sc, layerStack);
+    });
+    surface->showAt(100, 100);
+
+    injectTapOnDisplay(101, 101, layerStack.id);
+    EXPECT_NE(surface->consumeEvent(), nullptr);
+    EXPECT_NE(surface->consumeEvent(), nullptr);
+
+    surface->requestFocus(layerStack.id);
+    surface->assertFocusChange(true);
+    injectKeyOnDisplay(AKEYCODE_V, layerStack.id);
+
+    surface->expectKey(AKEYCODE_V);
+}
+
 } // namespace android::test
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 10391a2b..87afa22 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2154,7 +2154,7 @@
     if (traceFlags & SurfaceTracing::TRACE_INPUT) {
         WindowInfo info;
         if (useDrawing) {
-            info = fillInputInfo(ui::Transform());
+            info = fillInputInfo(ui::Transform(), /* displayIsSecure */ true);
         } else {
             info = state.inputInfo;
         }
@@ -2356,7 +2356,7 @@
     }
 }
 
-WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform) {
+WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform, bool displayIsSecure) {
     if (!hasInputInfo()) {
         mDrawingState.inputInfo.name = getName();
         mDrawingState.inputInfo.ownerUid = mOwnerUid;
@@ -2385,6 +2385,12 @@
     fillTouchOcclusionMode(info);
     handleDropInputMode(info);
 
+    // If the window will be blacked out on a display because the display does not have the secure
+    // flag and the layer has the secure flag set, then drop input.
+    if (!displayIsSecure && isSecure()) {
+        info.inputFeatures |= WindowInfo::Feature::DROP_INPUT;
+    }
+
     auto cropLayer = mDrawingState.touchableRegionCrop.promote();
     if (info.replaceTouchableRegionWithCrop) {
         const Rect bounds(cropLayer ? cropLayer->mScreenBounds : mScreenBounds);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 7b9303f..8c281d5 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -854,7 +854,7 @@
     bool getPremultipledAlpha() const;
     void setInputInfo(const gui::WindowInfo& info);
 
-    gui::WindowInfo fillInputInfo(const ui::Transform& displayTransform);
+    gui::WindowInfo fillInputInfo(const ui::Transform& displayTransform, bool displayIsSecure);
 
     /**
      * Returns whether this layer has an explicitly set input-info.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d4db33c..88715e3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3089,16 +3089,19 @@
     mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
         if (!layer->needsInputInfo()) return;
 
-        const DisplayDevice* display = nullptr;
-        if (enablePerWindowInputRotation()) {
-            display = ON_MAIN_THREAD(getDisplayWithInputByLayer(layer)).get();
-        }
+        const DisplayDevice* display = ON_MAIN_THREAD(getDisplayWithInputByLayer(layer)).get();
+        ui::Transform displayTransform = ui::Transform();
 
-        // When calculating the screen bounds we ignore the transparent region since it may
-        // result in an unwanted offset.
-        const auto it = displayTransforms.find(display);
-        windowInfos.push_back(
-                layer->fillInputInfo(it != displayTransforms.end() ? it->second : ui::Transform()));
+        if (enablePerWindowInputRotation()) {
+            // When calculating the screen bounds we ignore the transparent region since it may
+            // result in an unwanted offset.
+            const auto it = displayTransforms.find(display);
+            if (it != displayTransforms.end()) {
+                displayTransform = it->second;
+            }
+        }
+        const bool displayIsSecure = !display || display->isSecure();
+        windowInfos.push_back(layer->fillInputInfo(displayTransform, displayIsSecure));
     });
     mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos,
                                                     mInputWindowCommands.syncInputWindows);