Merge "InputDispatcher: Do not drop ongoing gesture if a window is no longer a spy" into tm-dev
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 4b64203..260ee8d 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -67,5 +67,66 @@
         }
       ]
     }
+  ],
+  "hwasan-postsubmit": [
+    {
+      "name": "SurfaceFlinger_test",
+      "options": [
+        {
+          "include-filter": "*CredentialsTest.*"
+        },
+        {
+          "include-filter": "*SurfaceFlingerStress.*"
+        },
+        {
+          "include-filter": "*SurfaceInterceptorTest.*"
+        },
+        {
+          "include-filter": "*LayerTransactionTest.*"
+        },
+        {
+          "include-filter": "*LayerTypeTransactionTest.*"
+        },
+        {
+          "include-filter": "*LayerUpdateTest.*"
+        },
+        {
+          "include-filter": "*GeometryLatchingTest.*"
+        },
+        {
+          "include-filter": "*CropLatchingTest.*"
+        },
+        {
+          "include-filter": "*ChildLayerTest.*"
+        },
+        {
+          "include-filter": "*ScreenCaptureTest.*"
+        },
+        {
+          "include-filter": "*ScreenCaptureChildOnlyTest.*"
+        },
+        {
+          "include-filter": "*DereferenceSurfaceControlTest.*"
+        },
+        {
+          "include-filter": "*BoundlessLayerTest.*"
+        },
+        {
+          "include-filter": "*MultiDisplayLayerBoundsTest.*"
+        },
+        {
+          "include-filter": "*InvalidHandleTest.*"
+        },
+        {
+          "include-filter": "*VirtualDisplayTest.*"
+        },
+        {
+          "include-filter": "*RelativeZTest.*"
+        },
+        {
+          "include-filter": "*RefreshRateOverlayTest.*"
+        }
+      ]
+    }
   ]
 }
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 7bad351..741b264 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -55,6 +55,7 @@
 #include <cutils/fs.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
+#include <linux/quota.h>
 #include <log/log.h>               // TODO: Move everything to base/logging.
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
@@ -457,15 +458,37 @@
     free(after);
     return res;
 }
+static bool internal_storage_has_project_id() {
+    // The following path is populated in setFirstBoot, so if this file is present
+    // then project ids can be used.
 
-static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid, gid_t gid) {
+    auto using_project_ids =
+            StringPrintf("%smisc/installd/using_project_ids", android_data_dir.c_str());
+    return access(using_project_ids.c_str(), F_OK) == 0;
+}
+
+static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid, gid_t gid,
+                           long project_id) {
     if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, gid) != 0) {
         PLOG(ERROR) << "Failed to prepare " << path;
         return -1;
     }
+    if (internal_storage_has_project_id()) {
+        return set_quota_project_id(path, project_id, true);
+    }
     return 0;
 }
 
+static int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode,
+                                 uid_t uid, gid_t gid, long project_id) {
+    auto path = StringPrintf("%s/%s", parent.c_str(), name);
+    int ret = prepare_app_cache_dir(parent, name, target_mode, uid, gid);
+    if (ret == 0 && internal_storage_has_project_id()) {
+        return set_quota_project_id(path, project_id, true);
+    }
+    return ret;
+}
+
 static bool prepare_app_profile_dir(const std::string& packageName, int32_t appId, int32_t userId) {
     if (!property_get_bool("dalvik.vm.usejitprofiles", false)) {
         return true;
@@ -625,9 +648,11 @@
     }
 
     // Prepare only the parent app directory
-    if (prepare_app_dir(path, targetMode, uid, gid) ||
-        prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
-        prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
+    long project_id_app = get_project_id(uid, PROJECT_ID_APP_START);
+    long project_id_cache_app = get_project_id(uid, PROJECT_ID_APP_CACHE_START);
+    if (prepare_app_dir(path, targetMode, uid, gid, project_id_app) ||
+        prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid, project_id_cache_app) ||
+        prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid, project_id_cache_app)) {
         return error("Failed to prepare " + path);
     }
 
@@ -771,7 +796,7 @@
         LOG(DEBUG) << "Creating app-level sdk data directory: " << packagePath;
 #endif
 
-        if (prepare_app_dir(packagePath, 0751, AID_SYSTEM, AID_SYSTEM)) {
+        if (prepare_app_dir(packagePath, 0751, AID_SYSTEM, AID_SYSTEM, 0)) {
             return error("Failed to prepare " + packagePath);
         }
     }
@@ -2088,26 +2113,70 @@
 }
 #endif
 
+// On devices without sdcardfs, if internal and external are on
+// the same volume, a uid such as u0_a123 is used for both
+// internal and external storage; therefore, subtract that
+// amount from internal to make sure we don't count it double.
+// This needs to happen for data, cache and OBB
+static void deductDoubleSpaceIfNeeded(stats* stats, int64_t doubleSpaceToBeDeleted, uid_t uid,
+                                      const std::string& uuid) {
+    if (!supports_sdcardfs()) {
+        stats->dataSize -= doubleSpaceToBeDeleted;
+        long obbProjectId = get_project_id(uid, PROJECT_ID_EXT_OBB_START);
+        int64_t appObbSize = GetOccupiedSpaceForProjectId(uuid, obbProjectId);
+        stats->dataSize -= appObbSize;
+    }
+}
+
 static void collectQuotaStats(const std::string& uuid, int32_t userId,
         int32_t appId, struct stats* stats, struct stats* extStats) {
-    int64_t space;
+    int64_t space, doubleSpaceToBeDeleted = 0;
     uid_t uid = multiuser_get_uid(userId, appId);
-    if (stats != nullptr) {
-        if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
-            stats->dataSize += space;
+    static const bool supportsProjectId = internal_storage_has_project_id();
+
+    if (extStats != nullptr) {
+        space = get_occupied_app_space_external(uuid, userId, appId);
+
+        if (space != -1) {
+            extStats->dataSize += space;
+            doubleSpaceToBeDeleted += space;
         }
 
-        int sdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
-        if (sdkSandboxUid != -1) {
-            if ((space = GetOccupiedSpaceForUid(uuid, sdkSandboxUid)) != -1) {
+        space = get_occupied_app_cache_space_external(uuid, userId, appId);
+        if (space != -1) {
+            extStats->dataSize += space; // cache counts for "data"
+            extStats->cacheSize += space;
+            doubleSpaceToBeDeleted += space;
+        }
+    }
+
+    if (stats != nullptr) {
+        if (!supportsProjectId) {
+            if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
                 stats->dataSize += space;
             }
-        }
-
-        int cacheGid = multiuser_get_cache_gid(userId, appId);
-        if (cacheGid != -1) {
-            if ((space = GetOccupiedSpaceForGid(uuid, cacheGid)) != -1) {
+            deductDoubleSpaceIfNeeded(stats, doubleSpaceToBeDeleted, uid, uuid);
+            int sdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
+            if (sdkSandboxUid != -1) {
+                if ((space = GetOccupiedSpaceForUid(uuid, sdkSandboxUid)) != -1) {
+                    stats->dataSize += space;
+                }
+            }
+            int cacheGid = multiuser_get_cache_gid(userId, appId);
+            if (cacheGid != -1) {
+                if ((space = GetOccupiedSpaceForGid(uuid, cacheGid)) != -1) {
+                    stats->cacheSize += space;
+                }
+            }
+        } else {
+            long projectId = get_project_id(uid, PROJECT_ID_APP_START);
+            if ((space = GetOccupiedSpaceForProjectId(uuid, projectId)) != -1) {
+                stats->dataSize += space;
+            }
+            projectId = get_project_id(uid, PROJECT_ID_APP_CACHE_START);
+            if ((space = GetOccupiedSpaceForProjectId(uuid, projectId)) != -1) {
                 stats->cacheSize += space;
+                stats->dataSize += space;
             }
         }
 
@@ -2118,47 +2187,6 @@
             }
         }
     }
-
-    if (extStats != nullptr) {
-        static const bool supportsSdCardFs = supports_sdcardfs();
-        space = get_occupied_app_space_external(uuid, userId, appId);
-
-        if (space != -1) {
-            extStats->dataSize += space;
-            if (!supportsSdCardFs && stats != nullptr) {
-                // On devices without sdcardfs, if internal and external are on
-                // the same volume, a uid such as u0_a123 is used for
-                // application dirs on both internal and external storage;
-                // therefore, substract that amount from internal to make sure
-                // we don't count it double.
-                stats->dataSize -= space;
-            }
-        }
-
-        space = get_occupied_app_cache_space_external(uuid, userId, appId);
-        if (space != -1) {
-            extStats->dataSize += space; // cache counts for "data"
-            extStats->cacheSize += space;
-            if (!supportsSdCardFs && stats != nullptr) {
-                // On devices without sdcardfs, if internal and external are on
-                // the same volume, a uid such as u0_a123 is used for both
-                // internal and external storage; therefore, substract that
-                // amount from internal to make sure we don't count it double.
-                stats->dataSize -= space;
-            }
-        }
-
-        if (!supportsSdCardFs && stats != nullptr) {
-            // On devices without sdcardfs, the UID of OBBs on external storage
-            // matches the regular app UID (eg u0_a123); therefore, to avoid
-            // OBBs being include in stats->dataSize, compute the OBB size for
-            // this app, and substract it from the size reported on internal
-            // storage
-            long obbProjectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START;
-            int64_t appObbSize = GetOccupiedSpaceForProjectId(uuid, obbProjectId);
-            stats->dataSize -= appObbSize;
-        }
-    }
 }
 
 static void collectManualStats(const std::string& path, struct stats* stats) {
@@ -2293,6 +2321,12 @@
     fts_close(fts);
 }
 static bool ownsExternalStorage(int32_t appId) {
+    // if project id calculation is supported then, there is no need to
+    // calculate in a different way and project_id based calculation can work
+    if (internal_storage_has_project_id()) {
+        return false;
+    }
+
     //  Fetch external storage owner appid  and check if it is the same as the
     //  current appId whose size is calculated
     struct stat s;
@@ -3356,6 +3390,38 @@
         dexPath, packageName, uid, volumeUuid, storageFlag, _aidl_return);
     return result ? ok() : error();
 }
+/**
+ * Returns true if ioctl feature (F2FS_IOC_FS{GET,SET}XATTR) is supported as
+ * these were introduced in Linux 4.14, so kernel versions before that will fail
+ * while setting project id attributes. Only when these features are enabled,
+ * storage calculation using project_id is enabled
+ */
+bool check_if_ioctl_feature_is_supported() {
+    bool result = false;
+    auto temp_path = StringPrintf("%smisc/installd/ioctl_check", android_data_dir.c_str());
+    if (access(temp_path.c_str(), F_OK) != 0) {
+        int fd = open(temp_path.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0644);
+        result = set_quota_project_id(temp_path, 0, true) == 0;
+        close(fd);
+        // delete the temp file
+        remove(temp_path.c_str());
+    }
+    return result;
+}
+
+binder::Status InstalldNativeService::setFirstBoot() {
+    ENFORCE_UID(AID_SYSTEM);
+    std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+    std::string uuid;
+    if (GetOccupiedSpaceForProjectId(uuid, 0) != -1 && check_if_ioctl_feature_is_supported()) {
+        auto first_boot_path =
+                StringPrintf("%smisc/installd/using_project_ids", android_data_dir.c_str());
+        if (access(first_boot_path.c_str(), F_OK) != 0) {
+            close(open(first_boot_path.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0644));
+        }
+    }
+    return ok();
+}
 
 binder::Status InstalldNativeService::invalidateMounts() {
     ENFORCE_UID(AID_SYSTEM);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index e6be5d8..87a9206 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -168,6 +168,7 @@
         int32_t storageFlag, std::vector<uint8_t>* _aidl_return);
 
     binder::Status invalidateMounts();
+    binder::Status setFirstBoot();
     binder::Status isQuotaSupported(const std::optional<std::string>& volumeUuid,
             bool* _aidl_return);
     binder::Status tryMountDataMirror(const std::optional<std::string>& volumeUuid);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 2b5a35e..79c02e8 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -20,7 +20,7 @@
 interface IInstalld {
     void createUserData(@nullable @utf8InCpp String uuid, int userId, int userSerial, int flags);
     void destroyUserData(@nullable @utf8InCpp String uuid, int userId, int flags);
-
+    void setFirstBoot();
     android.os.CreateAppDataResult createAppData(in android.os.CreateAppDataArgs args);
     android.os.CreateAppDataResult[] createAppDataBatched(in android.os.CreateAppDataArgs[] args);
 
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 123e3d4..9801a9b 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -37,6 +37,7 @@
 #include <android-base/unique_fd.h>
 #include <cutils/fs.h>
 #include <cutils/properties.h>
+#include <linux/fs.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_projectid_config.h>
@@ -424,6 +425,45 @@
     return users;
 }
 
+long get_project_id(uid_t uid, long start_project_id_range) {
+    return uid - AID_APP_START + start_project_id_range;
+}
+
+int set_quota_project_id(const std::string& path, long project_id, bool set_inherit) {
+    struct fsxattr fsx;
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
+    if (fd == -1) {
+        PLOG(ERROR) << "Failed to open " << path << " to set project id.";
+        return -1;
+    }
+
+    if (ioctl(fd, FS_IOC_FSGETXATTR, &fsx) == -1) {
+        PLOG(ERROR) << "Failed to get extended attributes for " << path << " to get project id.";
+        return -1;
+    }
+
+    fsx.fsx_projid = project_id;
+    if (ioctl(fd, FS_IOC_FSSETXATTR, &fsx) == -1) {
+        PLOG(ERROR) << "Failed to set project id on " << path;
+        return -1;
+    }
+    if (set_inherit) {
+        unsigned int flags;
+        if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1) {
+            PLOG(ERROR) << "Failed to get flags for " << path << " to set project id inheritance.";
+            return -1;
+        }
+
+        flags |= FS_PROJINHERIT_FL;
+
+        if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == -1) {
+            PLOG(ERROR) << "Failed to set flags for " << path << " to set project id inheritance.";
+            return -1;
+        }
+    }
+    return 0;
+}
+
 int calculate_tree_size(const std::string& path, int64_t* size,
         int32_t include_gid, int32_t exclude_gid, bool exclude_apps) {
     FTS *fts;
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index cb30993..ecea1d2 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -171,6 +171,8 @@
         uid_t uid, gid_t gid);
 
 bool supports_sdcardfs();
+long get_project_id(uid_t uid, long start_project_id_range);
+int set_quota_project_id(const std::string& path, long project_id, bool set_inherit);
 int64_t get_occupied_app_space_external(const std::string& uuid, int32_t userId, int32_t appId);
 int64_t get_occupied_app_cache_space_external(const std::string& uuid, int32_t userId, int32_t appId);
 
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index fcfe21b..e69fc78 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -76,16 +76,30 @@
 
 class InputSurface {
 public:
-    InputSurface(const sp<SurfaceControl> &sc, int width, int height) {
+    InputSurface(const sp<SurfaceControl> &sc, int width, int height, bool noInputChannel = false) {
         mSurfaceControl = sc;
 
         mInputFlinger = getInputFlinger();
-        mClientChannel = std::make_shared<InputChannel>();
-        mInputFlinger->createInputChannel("testchannels", mClientChannel.get());
+        if (noInputChannel) {
+            mInputInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, true);
+        } else {
+            mClientChannel = std::make_shared<InputChannel>();
+            mInputFlinger->createInputChannel("testchannels", mClientChannel.get());
+            mInputInfo.token = mClientChannel->getConnectionToken();
+            mInputConsumer = new InputConsumer(mClientChannel);
+        }
 
-        populateInputInfo(width, height);
+        mInputInfo.name = "Test info";
+        mInputInfo.dispatchingTimeout = 5s;
+        mInputInfo.globalScaleFactor = 1.0;
+        mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height));
 
-        mInputConsumer = new InputConsumer(mClientChannel);
+        InputApplicationInfo aInfo;
+        aInfo.token = new BBinder();
+        aInfo.name = "Test app info";
+        aInfo.dispatchingTimeoutMillis =
+                std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
+        mInputInfo.applicationInfo = aInfo;
     }
 
     static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient> &scc,
@@ -114,6 +128,16 @@
         return std::make_unique<InputSurface>(surfaceControl, width, height);
     }
 
+    static std::unique_ptr<InputSurface> makeContainerInputSurfaceNoInputChannel(
+            const sp<SurfaceComposerClient> &scc, int width, int height) {
+        sp<SurfaceControl> surfaceControl =
+                scc->createSurface(String8("Test Container Surface"), 100 /* height */,
+                                   100 /* width */, PIXEL_FORMAT_RGBA_8888,
+                                   ISurfaceComposerClient::eFXSurfaceContainer);
+        return std::make_unique<InputSurface>(surfaceControl, width, height,
+                                              true /* noInputChannel */);
+    }
+
     static std::unique_ptr<InputSurface> makeCursorInputSurface(
             const sp<SurfaceComposerClient> &scc, int width, int height) {
         sp<SurfaceControl> surfaceControl =
@@ -219,7 +243,9 @@
     }
 
     virtual ~InputSurface() {
-        mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken());
+        if (mClientChannel) {
+            mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken());
+        }
     }
 
     virtual void doTransaction(
@@ -263,21 +289,6 @@
         poll(&fd, 1, timeoutMs);
     }
 
-    void populateInputInfo(int width, int height) {
-        mInputInfo.token = mClientChannel->getConnectionToken();
-        mInputInfo.name = "Test info";
-        mInputInfo.dispatchingTimeout = 5s;
-        mInputInfo.globalScaleFactor = 1.0;
-        mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height));
-
-        InputApplicationInfo aInfo;
-        aInfo.token = new BBinder();
-        aInfo.name = "Test app info";
-        aInfo.dispatchingTimeoutMillis =
-                std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
-
-        mInputInfo.applicationInfo = aInfo;
-    }
 public:
     sp<SurfaceControl> mSurfaceControl;
     std::shared_ptr<InputChannel> mClientChannel;
@@ -1085,6 +1096,23 @@
     EXPECT_EQ(containerSurface->consumeEvent(100), nullptr);
 }
 
+TEST_F(InputSurfacesTest, child_container_with_no_input_channel_blocks_parent) {
+    std::unique_ptr<InputSurface> parent = makeSurface(100, 100);
+
+    parent->showAt(100, 100);
+    injectTap(101, 101);
+    parent->expectTap(1, 1);
+
+    std::unique_ptr<InputSurface> childContainerSurface =
+            InputSurface::makeContainerInputSurfaceNoInputChannel(mComposerClient, 100, 100);
+    childContainerSurface->showAt(0, 0);
+    childContainerSurface->doTransaction(
+            [&](auto &t, auto &sc) { t.reparent(sc, parent->mSurfaceControl); });
+    injectTap(101, 101);
+
+    EXPECT_EQ(parent->consumeEvent(100), nullptr);
+}
+
 class MultiDisplayTests : public InputSurfacesTest {
 public:
     MultiDisplayTests() : InputSurfacesTest() { ProcessState::self()->startThreadPool(); }
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 66a9ef7..dd3858b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -1310,7 +1310,8 @@
     static const Region kLowerHalfBoundsNoRotation;
     static const Region kFullBounds90Rotation;
     static const Region kTransparentRegionHint;
-    static const Region kTransparentRegionHint90Rotation;
+    static const Region kTransparentRegionHintTwo;
+    static const Region kTransparentRegionHintTwo90Rotation;
 
     StrictMock<OutputPartialMock> mOutput;
     LayerFESet mGeomSnapshots;
@@ -1329,8 +1330,10 @@
 const Region OutputEnsureOutputLayerIfVisibleTest::kFullBounds90Rotation =
         Region(Rect(0, 0, 200, 100));
 const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHint =
+        Region(Rect(0, 0, 100, 100));
+const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHintTwo =
         Region(Rect(25, 20, 50, 75));
-const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHint90Rotation =
+const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHintTwo90Rotation =
         Region(Rect(125, 25, 180, 50));
 
 TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerIncluded) {
@@ -1787,6 +1790,7 @@
     mLayer.layerFEState.contentDirty = true;
     mLayer.layerFEState.compositionType =
             aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION;
+    mLayer.layerFEState.transparentRegionHint = kTransparentRegionHintTwo;
 
     mOutput.mState.layerStackSpace.setContent(Rect(0, 0, 300, 200));
     mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
@@ -1797,7 +1801,7 @@
     ensureOutputLayerIfVisible();
 
     EXPECT_THAT(mLayer.outputLayerState.outputSpaceBlockingRegionHint,
-                RegionEq(kTransparentRegionHint90Rotation));
+                RegionEq(kTransparentRegionHintTwo90Rotation));
 }
 
 /*
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index aeaf1e1..ac7bcde 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2392,7 +2392,8 @@
 }
 
 bool Layer::hasInputInfo() const {
-    return mDrawingState.inputInfo.token != nullptr;
+    return mDrawingState.inputInfo.token != nullptr ||
+            mDrawingState.inputInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
 }
 
 bool Layer::canReceiveInput() const {