SurfaceControl: Add setDropInputMode api

Introduces an API to drop input events on this SurfaceControl. This
policy will be inherited by its children. The caller must hold the
ACCESS_SURFACE_FLINGER permission.

Options include:
ALL: SurfaceControl and its children will not receive any
input regardless of whether it has a valid input channel.

These policies are used to enable features that allow for a less trusted
interaction model between apps. See the bug for more details.

Note: this backport does not include the OBSCURED option since its
not needed for the security fix.

Test: atest libgui_test InputDispatcherDropInputFeatureTest
Bug: 197296414

Merged-In: I443741d5ab51a45d37fb865f11c433c436d96c1e
Change-Id: I443741d5ab51a45d37fb865f11c433c436d96c1e
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h
index 121be6d..e2c9587 100644
--- a/include/input/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -128,6 +128,7 @@
         DISABLE_TOUCH_PAD_GESTURES = 0x00000001,
         NO_INPUT_CHANNEL = 0x00000002,
         DISABLE_USER_ACTIVITY = 0x00000004,
+        INPUT_FEATURE_DROP_INPUT = 0x00000008,
     };
 
     /* These values are filled in by the WM and passed through SurfaceFlinger
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 64203f7..b1c6e3a 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -39,13 +39,20 @@
     min_sdk_version: "29",
 }
 
+// AIDL files that should be exposed to java
+filegroup {
+    name: "guiconstants_aidl",
+    srcs: [
+        "android/gui/DropInputMode.aidl",
+    ],
+}
+
 cc_library_headers {
     name: "libgui_aidl_headers",
     vendor_available: true,
     static_libs: [
         "libgui_aidl_static",
     ],
-
     export_static_lib_headers: [
         "libgui_aidl_static",
     ],
@@ -102,6 +109,7 @@
     ],
 
     srcs: [
+        ":guiconstants_aidl",
         ":framework_native_aidl",
         ":inputconstants_aidl",
         ":libgui_bufferqueue_sources",
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 076c90d..2f31fbb 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -65,6 +65,7 @@
         frameNumber(0),
         autoRefresh(false),
         isTrustedOverlay(false),
+        dropInputMode(gui::DropInputMode::NONE),
         bufferCrop(Rect::INVALID_RECT),
         destinationFrame(Rect::INVALID_RECT),
         releaseBufferListener(nullptr) {
@@ -172,7 +173,7 @@
     SAFE_PARCEL(output.write, bufferCrop);
     SAFE_PARCEL(output.write, destinationFrame);
     SAFE_PARCEL(output.writeBool, isTrustedOverlay);
-
+    output.writeUint32(static_cast<uint32_t>(dropInputMode));
     return NO_ERROR;
 }
 
@@ -304,6 +305,9 @@
     SAFE_PARCEL(input.read, destinationFrame);
     SAFE_PARCEL(input.readBool, &isTrustedOverlay);
 
+    uint32_t mode;
+    mode = input.readUint32();
+    dropInputMode = static_cast<gui::DropInputMode>(mode);
     return NO_ERROR;
 }
 
@@ -539,6 +543,10 @@
         what |= eTrustedOverlayChanged;
         isTrustedOverlay = other.isTrustedOverlay;
     }
+    if (other.what & eDropInputModeChanged) {
+        what |= eDropInputModeChanged;
+        dropInputMode = other.dropInputMode;
+    }
     if (other.what & eReleaseBufferListenerChanged) {
         if (releaseBufferListener) {
             ALOGW("Overriding releaseBufferListener");
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 96da8ef..6ffd25d 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1669,6 +1669,21 @@
     return *this;
 }
 
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDropInputMode(
+        const sp<SurfaceControl>& sc, gui::DropInputMode mode) {
+    layer_state_t* s = getLayerState(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
+
+    s->what |= layer_state_t::eDropInputModeChanged;
+    s->dropInputMode = mode;
+
+    registerSurfaceControlForCallback(sc);
+    return *this;
+}
+
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApplyToken(
         const sp<IBinder>& applyToken) {
     mApplyToken = applyToken;
diff --git a/libs/gui/android/gui/DropInputMode.aidl b/libs/gui/android/gui/DropInputMode.aidl
new file mode 100644
index 0000000..2949436
--- /dev/null
+++ b/libs/gui/android/gui/DropInputMode.aidl
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.gui;
+
+
+/**
+  * Input event drop modes: Input event drop options for windows and its children.
+  *
+  * @hide
+  */
+@Backing(type="int")
+enum DropInputMode {
+    /**
+      * Default mode, input events are sent to the target as usual.
+      */
+    NONE,
+
+    /**
+      * Window and its children will not receive any input even if it has a valid input channel.
+      * Touches and keys will be dropped. If a window is focused, it will remain focused but will
+      * not receive any keys. If the window has a touchable region and is the target of an input
+      * event, the event will be dropped and will not go to the window behind. ref: b/197296414
+      */
+    ALL,
+}
+
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 3e57ff6..feef343 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -26,6 +26,7 @@
 #include <gui/ITransactionCompletedListener.h>
 #include <math/mat4.h>
 
+#include <android/gui/DropInputMode.h>
 #ifndef NO_INPUT
 #include <android/FocusRequest.h>
 #include <input/InputWindow.h>
@@ -116,6 +117,7 @@
         eFixedTransformHintChanged = 0x200'00000000,
         eFrameNumberChanged = 0x400'00000000,
         eBlurRegionsChanged = 0x800'00000000,
+        eDropInputModeChanged = 0x8000'00000000,
         eAutoRefreshChanged = 0x1000'00000000,
         eStretchChanged = 0x2000'00000000,
         eTrustedOverlayChanged = 0x4000'00000000,
@@ -233,6 +235,9 @@
     // Stretch effect to be applied to this layer
     StretchEffect stretchEffect;
 
+    // Force inputflinger to drop all input events for the layer and its children.
+    gui::DropInputMode dropInputMode;
+
     Rect bufferCrop;
     Rect destinationFrame;
 
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index baa0567..6e17212 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -540,6 +540,8 @@
         // Sets that this surface control and its children are trusted overlays for input
         Transaction& setTrustedOverlay(const sp<SurfaceControl>& sc, bool isTrustedOverlay);
 
+        Transaction& setDropInputMode(const sp<SurfaceControl>& sc, gui::DropInputMode mode);
+
         // Queues up transactions using this token in SurfaceFlinger.  By default, all transactions
         // from a client are placed on the same queue. This can be used to prevent multiple
         // transactions from blocking each other.
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index e4a777f..1e9847d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -133,6 +133,7 @@
     mDrawingState.fixedTransformHint = ui::Transform::ROT_INVALID;
     mDrawingState.frameTimelineInfo = {};
     mDrawingState.postTime = -1;
+    mDrawingState.dropInputMode = gui::DropInputMode::NONE;
     mDrawingState.destinationFrame.makeInvalid();
 
     if (args.flags & ISurfaceComposerClient::eNoColorFill) {
@@ -2533,6 +2534,17 @@
     }
 }
 
+bool Layer::setDropInputMode(gui::DropInputMode mode) {
+    if (mDrawingState.dropInputMode == mode) {
+        return false;
+    }
+    mDrawingState.dropInputMode = mode;
+    mDrawingState.modified = true;
+    mFlinger->mInputInfoChanged = true;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+
 scheduler::Seamlessness Layer::FrameRate::convertChangeFrameRateStrategy(int8_t strategy) {
     switch (strategy) {
         case ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS:
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 59f5b0d..c49a4b4 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -17,6 +17,7 @@
 
 #pragma once
 
+#include <android/gui/DropInputMode.h>
 #include <compositionengine/LayerFE.h>
 #include <gui/BufferQueue.h>
 #include <gui/ISurfaceComposerClient.h>
@@ -279,6 +280,7 @@
         bool isTrustedOverlay;
 
         Rect bufferCrop;
+        gui::DropInputMode dropInputMode;
         Rect destinationFrame;
     };
 
@@ -439,6 +441,8 @@
     virtual bool setFrameRateSelectionPriority(int32_t priority);
     virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint);
     virtual void setAutoRefresh(bool /* autoRefresh */) {}
+    bool setDropInputMode(gui::DropInputMode);
+
     //  If the variable is not set on the layer, it traverses up the tree to inherit the frame
     //  rate priority from its parent.
     virtual int32_t getFrameRateSelectionPriority() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 230810c..16b714d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4178,6 +4178,15 @@
             ALOGE("Attempt to set trusted overlay without permission ACCESS_SURFACE_FLINGER");
         }
     }
+    if (what & layer_state_t::eDropInputModeChanged) {
+        if (privileged) {
+            if (layer->setDropInputMode(s.dropInputMode)) {
+                flags |= eTraversalNeeded;
+            }
+        } else {
+            ALOGE("Attempt to update InputPolicyFlags without permission ACCESS_SURFACE_FLINGER");
+        }
+    }
     if (what & layer_state_t::eStretchChanged) {
         if (layer->setStretchEffect(s.stretchEffect)) {
             flags |= eTraversalNeeded;