Move things in InputWindowInfo to enum classes

Also introduce a new Flag class to make it possible to deal with flags
while treating the individual flags as part of an enum class in a type
safe manner.

Bug: 160010896
Test: atest inputflinger_tests, atest libinput_tests
Change-Id: I915a1c1e3b31f1c0fd99b83ba5fad7e537cd6f84
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index ae9b3f0..36c1f80 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <type_traits>
 #define LOG_TAG "InputWindow"
 #define LOG_NDEBUG 0
 
@@ -26,117 +27,6 @@
 
 namespace android {
 
-const char* inputWindowFlagToString(uint32_t flag) {
-    switch (flag) {
-        case InputWindowInfo::FLAG_ALLOW_LOCK_WHILE_SCREEN_ON: {
-            return "ALLOW_LOCK_WHILE_SCREEN_ON";
-        }
-        case InputWindowInfo::FLAG_DIM_BEHIND: {
-            return "DIM_BEHIND";
-        }
-        case InputWindowInfo::FLAG_BLUR_BEHIND: {
-            return "BLUR_BEHIND";
-        }
-        case InputWindowInfo::FLAG_NOT_FOCUSABLE: {
-            return "NOT_FOCUSABLE";
-        }
-        case InputWindowInfo::FLAG_NOT_TOUCHABLE: {
-            return "NOT_TOUCHABLE";
-        }
-        case InputWindowInfo::FLAG_NOT_TOUCH_MODAL: {
-            return "NOT_TOUCH_MODAL";
-        }
-        case InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING: {
-            return "TOUCHABLE_WHEN_WAKING";
-        }
-        case InputWindowInfo::FLAG_KEEP_SCREEN_ON: {
-            return "KEEP_SCREEN_ON";
-        }
-        case InputWindowInfo::FLAG_LAYOUT_IN_SCREEN: {
-            return "LAYOUT_IN_SCREEN";
-        }
-        case InputWindowInfo::FLAG_LAYOUT_NO_LIMITS: {
-            return "LAYOUT_NO_LIMITS";
-        }
-        case InputWindowInfo::FLAG_FULLSCREEN: {
-            return "FULLSCREEN";
-        }
-        case InputWindowInfo::FLAG_FORCE_NOT_FULLSCREEN: {
-            return "FORCE_NOT_FULLSCREEN";
-        }
-        case InputWindowInfo::FLAG_DITHER: {
-            return "DITHER";
-        }
-        case InputWindowInfo::FLAG_SECURE: {
-            return "SECURE";
-        }
-        case InputWindowInfo::FLAG_SCALED: {
-            return "SCALED";
-        }
-        case InputWindowInfo::FLAG_IGNORE_CHEEK_PRESSES: {
-            return "IGNORE_CHEEK_PRESSES";
-        }
-        case InputWindowInfo::FLAG_LAYOUT_INSET_DECOR: {
-            return "LAYOUT_INSET_DECOR";
-        }
-        case InputWindowInfo::FLAG_ALT_FOCUSABLE_IM: {
-            return "ALT_FOCUSABLE_IM";
-        }
-        case InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH: {
-            return "WATCH_OUTSIDE_TOUCH";
-        }
-        case InputWindowInfo::FLAG_SHOW_WHEN_LOCKED: {
-            return "SHOW_WHEN_LOCKED";
-        }
-        case InputWindowInfo::FLAG_SHOW_WALLPAPER: {
-            return "SHOW_WALLPAPER";
-        }
-        case InputWindowInfo::FLAG_TURN_SCREEN_ON: {
-            return "TURN_SCREEN_ON";
-        }
-        case InputWindowInfo::FLAG_DISMISS_KEYGUARD: {
-            return "DISMISS_KEYGUARD";
-        }
-        case InputWindowInfo::FLAG_SPLIT_TOUCH: {
-            return "SPLIT_TOUCH";
-        }
-        case InputWindowInfo::FLAG_HARDWARE_ACCELERATED: {
-            return "HARDWARE_ACCELERATED";
-        }
-        case InputWindowInfo::FLAG_LAYOUT_IN_OVERSCAN: {
-            return "LAYOUT_IN_OVERSCAN";
-        }
-        case InputWindowInfo::FLAG_TRANSLUCENT_STATUS: {
-            return "TRANSLUCENT_STATUS";
-        }
-        case InputWindowInfo::FLAG_TRANSLUCENT_NAVIGATION: {
-            return "TRANSLUCENT_NAVIGATION";
-        }
-        case InputWindowInfo::FLAG_LOCAL_FOCUS_MODE: {
-            return "LOCAL_FOCUS_MODE";
-        }
-        case InputWindowInfo::FLAG_SLIPPERY: {
-            return "SLIPPERY";
-        }
-        case InputWindowInfo::FLAG_LAYOUT_ATTACHED_IN_DECOR: {
-            return "LAYOUT_ATTACHED_IN_DECOR";
-        }
-        case InputWindowInfo::FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS: {
-            return "DRAWS_SYSTEM_BAR_BACKGROUNDS";
-        }
-    }
-    return "UNKNOWN";
-}
-
-std::string inputWindowFlagsToString(uint32_t flags) {
-    std::string result;
-    for (BitSet32 bits(flags); !bits.isEmpty();) {
-        uint32_t bit = bits.clearLastMarkedBit(); // counts from left
-        const uint32_t flag = 1 << (32 - bit - 1);
-        result += android::base::StringPrintf("%s | ", inputWindowFlagToString(flag));
-    }
-    return result;
-}
 
 // --- InputWindowInfo ---
 void InputWindowInfo::addTouchableRegion(const Rect& region) {
@@ -153,7 +43,7 @@
 }
 
 bool InputWindowInfo::supportsSplitTouch() const {
-    return layoutParamsFlags & FLAG_SPLIT_TOUCH;
+    return flags.test(Flag::SPLIT_TOUCH);
 }
 
 bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
@@ -162,14 +52,12 @@
 }
 
 bool InputWindowInfo::operator==(const InputWindowInfo& info) const {
-    return info.token == token && info.id == id && info.name == name &&
-            info.layoutParamsFlags == layoutParamsFlags &&
-            info.layoutParamsType == layoutParamsType &&
-            info.dispatchingTimeout == dispatchingTimeout && info.frameLeft == frameLeft &&
-            info.frameTop == frameTop && info.frameRight == frameRight &&
-            info.frameBottom == frameBottom && info.surfaceInset == surfaceInset &&
-            info.globalScaleFactor == globalScaleFactor && info.windowXScale == windowXScale &&
-            info.windowYScale == windowYScale &&
+    return info.token == token && info.id == id && info.name == name && info.flags == flags &&
+            info.type == type && info.dispatchingTimeout == dispatchingTimeout &&
+            info.frameLeft == frameLeft && info.frameTop == frameTop &&
+            info.frameRight == frameRight && info.frameBottom == frameBottom &&
+            info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor &&
+            info.windowXScale == windowXScale && info.windowYScale == windowYScale &&
             info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible &&
             info.canReceiveKeys == canReceiveKeys && info.trustedOverlay == trustedOverlay &&
             info.hasFocus == hasFocus && info.hasWallpaper == hasWallpaper &&
@@ -197,8 +85,8 @@
         parcel->writeInt64(dispatchingTimeout.count()) ?:
         parcel->writeInt32(id) ?:
         parcel->writeUtf8AsUtf16(name) ?:
-        parcel->writeInt32(layoutParamsFlags) ?:
-        parcel->writeInt32(layoutParamsType) ?:
+        parcel->writeInt32(flags.get()) ?:
+        parcel->writeInt32(static_cast<std::underlying_type_t<InputWindowInfo::Type>>(type)) ?:
         parcel->writeInt32(frameLeft) ?:
         parcel->writeInt32(frameTop) ?:
         parcel->writeInt32(frameRight) ?:
@@ -215,7 +103,7 @@
         parcel->writeBool(trustedOverlay) ?:
         parcel->writeInt32(ownerPid) ?:
         parcel->writeInt32(ownerUid) ?:
-        parcel->writeInt32(inputFeatures) ?:
+        parcel->writeInt32(inputFeatures.get()) ?:
         parcel->writeInt32(displayId) ?:
         parcel->writeInt32(portalToDisplayId) ?:
         applicationInfo.writeToParcel(parcel) ?:
@@ -236,12 +124,15 @@
     }
 
     token = parcel->readStrongBinder();
-    dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64());
-    status_t status = parcel->readInt32(&id) ?:
-        parcel->readUtf8FromUtf16(&name) ?:
-        parcel->readInt32(&layoutParamsFlags) ?:
-        parcel->readInt32(&layoutParamsType) ?:
-        parcel->readInt32(&frameLeft) ?:
+    dispatchingTimeout = static_cast<decltype(dispatchingTimeout)>(parcel->readInt64());
+    status_t status = parcel->readInt32(&id) ?: parcel->readUtf8FromUtf16(&name);
+    if (status != OK) {
+        return status;
+    }
+
+    flags = Flags<Flag>(parcel->readInt32());
+    type = static_cast<Type>(parcel->readInt32());
+    status = parcel->readInt32(&frameLeft) ?:
         parcel->readInt32(&frameTop) ?:
         parcel->readInt32(&frameRight) ?:
         parcel->readInt32(&frameBottom) ?:
@@ -256,17 +147,26 @@
         parcel->readBool(&paused) ?:
         parcel->readBool(&trustedOverlay) ?:
         parcel->readInt32(&ownerPid) ?:
-        parcel->readInt32(&ownerUid) ?:
-        parcel->readInt32(&inputFeatures) ?:
-        parcel->readInt32(&displayId) ?:
+        parcel->readInt32(&ownerUid);
+
+    if (status != OK) {
+        return status;
+    }
+
+    inputFeatures = Flags<Feature>(parcel->readInt32());
+    status = parcel->readInt32(&displayId) ?:
         parcel->readInt32(&portalToDisplayId) ?:
         applicationInfo.readFromParcel(parcel) ?:
         parcel->read(touchableRegion) ?:
         parcel->readBool(&replaceTouchableRegionWithCrop);
 
+    if (status != OK) {
+        return status;
+    }
+
     touchableRegionCropHandle = parcel->readStrongBinder();
 
-    return status;
+    return OK;
 }
 
 // --- InputWindowHandle ---
@@ -299,4 +199,106 @@
     mInfo = handle->mInfo;
 }
 
+std::optional<std::string> InputWindowInfo::flagToString(Flag flag) {
+    switch (flag) {
+        case InputWindowInfo::Flag::ALLOW_LOCK_WHILE_SCREEN_ON: {
+            return "ALLOW_LOCK_WHILE_SCREEN_ON";
+        }
+        case InputWindowInfo::Flag::DIM_BEHIND: {
+            return "DIM_BEHIND";
+        }
+        case InputWindowInfo::Flag::BLUR_BEHIND: {
+            return "BLUR_BEHIND";
+        }
+        case InputWindowInfo::Flag::NOT_FOCUSABLE: {
+            return "NOT_FOCUSABLE";
+        }
+        case InputWindowInfo::Flag::NOT_TOUCHABLE: {
+            return "NOT_TOUCHABLE";
+        }
+        case InputWindowInfo::Flag::NOT_TOUCH_MODAL: {
+            return "NOT_TOUCH_MODAL";
+        }
+        case InputWindowInfo::Flag::TOUCHABLE_WHEN_WAKING: {
+            return "TOUCHABLE_WHEN_WAKING";
+        }
+        case InputWindowInfo::Flag::KEEP_SCREEN_ON: {
+            return "KEEP_SCREEN_ON";
+        }
+        case InputWindowInfo::Flag::LAYOUT_IN_SCREEN: {
+            return "LAYOUT_IN_SCREEN";
+        }
+        case InputWindowInfo::Flag::LAYOUT_NO_LIMITS: {
+            return "LAYOUT_NO_LIMITS";
+        }
+        case InputWindowInfo::Flag::FULLSCREEN: {
+            return "FULLSCREEN";
+        }
+        case InputWindowInfo::Flag::FORCE_NOT_FULLSCREEN: {
+            return "FORCE_NOT_FULLSCREEN";
+        }
+        case InputWindowInfo::Flag::DITHER: {
+            return "DITHER";
+        }
+        case InputWindowInfo::Flag::SECURE: {
+            return "SECURE";
+        }
+        case InputWindowInfo::Flag::SCALED: {
+            return "SCALED";
+        }
+        case InputWindowInfo::Flag::IGNORE_CHEEK_PRESSES: {
+            return "IGNORE_CHEEK_PRESSES";
+        }
+        case InputWindowInfo::Flag::LAYOUT_INSET_DECOR: {
+            return "LAYOUT_INSET_DECOR";
+        }
+        case InputWindowInfo::Flag::ALT_FOCUSABLE_IM: {
+            return "ALT_FOCUSABLE_IM";
+        }
+        case InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH: {
+            return "WATCH_OUTSIDE_TOUCH";
+        }
+        case InputWindowInfo::Flag::SHOW_WHEN_LOCKED: {
+            return "SHOW_WHEN_LOCKED";
+        }
+        case InputWindowInfo::Flag::SHOW_WALLPAPER: {
+            return "SHOW_WALLPAPER";
+        }
+        case InputWindowInfo::Flag::TURN_SCREEN_ON: {
+            return "TURN_SCREEN_ON";
+        }
+        case InputWindowInfo::Flag::DISMISS_KEYGUARD: {
+            return "DISMISS_KEYGUARD";
+        }
+        case InputWindowInfo::Flag::SPLIT_TOUCH: {
+            return "SPLIT_TOUCH";
+        }
+        case InputWindowInfo::Flag::HARDWARE_ACCELERATED: {
+            return "HARDWARE_ACCELERATED";
+        }
+        case InputWindowInfo::Flag::LAYOUT_IN_OVERSCAN: {
+            return "LAYOUT_IN_OVERSCAN";
+        }
+        case InputWindowInfo::Flag::TRANSLUCENT_STATUS: {
+            return "TRANSLUCENT_STATUS";
+        }
+        case InputWindowInfo::Flag::TRANSLUCENT_NAVIGATION: {
+            return "TRANSLUCENT_NAVIGATION";
+        }
+        case InputWindowInfo::Flag::LOCAL_FOCUS_MODE: {
+            return "LOCAL_FOCUS_MODE";
+        }
+        case InputWindowInfo::Flag::SLIPPERY: {
+            return "SLIPPERY";
+        }
+        case InputWindowInfo::Flag::LAYOUT_ATTACHED_IN_DECOR: {
+            return "LAYOUT_ATTACHED_IN_DECOR";
+        }
+        case InputWindowInfo::Flag::DRAWS_SYSTEM_BAR_BACKGROUNDS: {
+            return "DRAWS_SYSTEM_BAR_BACKGROUNDS";
+        }
+    }
+    return std::nullopt;
+}
+
 } // namespace android
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 3b57146..9782c1a 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -2,6 +2,7 @@
 cc_test {
     name: "libinput_tests",
     srcs: [
+        "Flags_test.cpp",
         "IdGenerator_test.cpp",
         "InputChannel_test.cpp",
         "InputDevice_test.cpp",
diff --git a/libs/input/tests/Flags_test.cpp b/libs/input/tests/Flags_test.cpp
new file mode 100644
index 0000000..800404d
--- /dev/null
+++ b/libs/input/tests/Flags_test.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#include <gtest/gtest.h>
+#include <input/Flags.h>
+
+#include <type_traits>
+
+namespace android::test {
+
+using namespace android::flag_operators;
+
+enum class TestFlags { ONE = 0x1, TWO = 0x2, THREE = 0x4 };
+
+static std::optional<std::string> toStringComplete(TestFlags f) {
+    switch (f) {
+        case TestFlags::ONE:
+            return "ONE";
+        case TestFlags::TWO:
+            return "TWO";
+        case TestFlags::THREE:
+            return "THREE";
+    }
+    return std::nullopt;
+}
+
+static std::optional<std::string> toStringIncomplete(TestFlags f) {
+    switch (f) {
+        case TestFlags::ONE:
+            return "ONE";
+        case TestFlags::TWO:
+            return "TWO";
+        case TestFlags::THREE:
+        default:
+            return std::nullopt;
+    }
+}
+
+TEST(Flags, Test) {
+    Flags<TestFlags> flags = TestFlags::ONE;
+    ASSERT_TRUE(flags.test(TestFlags::ONE));
+    ASSERT_FALSE(flags.test(TestFlags::TWO));
+    ASSERT_FALSE(flags.test(TestFlags::THREE));
+}
+
+TEST(Flags, Any) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
+    ASSERT_TRUE(flags.any(TestFlags::ONE));
+    ASSERT_TRUE(flags.any(TestFlags::TWO));
+    ASSERT_FALSE(flags.any(TestFlags::THREE));
+    ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO));
+    ASSERT_TRUE(flags.any(TestFlags::TWO | TestFlags::THREE));
+    ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::THREE));
+    ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, All) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
+    ASSERT_TRUE(flags.all(TestFlags::ONE));
+    ASSERT_TRUE(flags.all(TestFlags::TWO));
+    ASSERT_FALSE(flags.all(TestFlags::THREE));
+    ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO));
+    ASSERT_FALSE(flags.all(TestFlags::TWO | TestFlags::THREE));
+    ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::THREE));
+    ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, DefaultConstructor_hasNoFlagsSet) {
+    Flags<TestFlags> flags;
+    ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, NotOperator_onEmptyFlagsSetsAllFlags) {
+    Flags<TestFlags> flags;
+    flags = ~flags;
+    ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, NotOperator_onNonEmptyFlagsInvertsFlags) {
+    Flags<TestFlags> flags = TestFlags::TWO;
+    flags = ~flags;
+    ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE));
+    ASSERT_FALSE(flags.test(TestFlags::TWO));
+}
+
+TEST(Flags, OrOperator_withNewFlag) {
+    Flags<TestFlags> flags = TestFlags::ONE;
+    Flags<TestFlags> flags2 = flags | TestFlags::TWO;
+    ASSERT_FALSE(flags2.test(TestFlags::THREE));
+    ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::TWO));
+}
+
+TEST(Flags, OrOperator_withExistingFlag) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+    Flags<TestFlags> flags2 = flags | TestFlags::THREE;
+    ASSERT_FALSE(flags2.test(TestFlags::TWO));
+    ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::THREE));
+}
+
+TEST(Flags, OrEqualsOperator_withNewFlag) {
+    Flags<TestFlags> flags;
+    flags |= TestFlags::THREE;
+    ASSERT_TRUE(flags.test(TestFlags::THREE));
+    ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO));
+}
+
+TEST(Flags, OrEqualsOperator_withExistingFlag) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+    flags |= TestFlags::THREE;
+    ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE));
+    ASSERT_FALSE(flags.test(TestFlags::TWO));
+}
+
+TEST(Flags, AndOperator_withOneSetFlag) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+    Flags<TestFlags> andFlags = flags & TestFlags::THREE;
+    ASSERT_TRUE(andFlags.test(TestFlags::THREE));
+    ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO));
+}
+
+TEST(Flags, AndOperator_withMultipleSetFlags) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+    Flags<TestFlags> andFlags = flags & (TestFlags::ONE | TestFlags::THREE);
+    ASSERT_TRUE(andFlags.all(TestFlags::ONE | TestFlags::THREE));
+    ASSERT_FALSE(andFlags.test(TestFlags::TWO));
+}
+
+TEST(Flags, AndOperator_withNoSetFlags) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+    Flags<TestFlags> andFlags = flags & TestFlags::TWO;
+    ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, Equality) {
+    Flags<TestFlags> flags1 = TestFlags::ONE | TestFlags::TWO;
+    Flags<TestFlags> flags2 = TestFlags::ONE | TestFlags::TWO;
+    ASSERT_EQ(flags1, flags2);
+}
+
+TEST(Flags, Inequality) {
+    Flags<TestFlags> flags1 = TestFlags::ONE | TestFlags::TWO;
+    Flags<TestFlags> flags2 = TestFlags::ONE | TestFlags::THREE;
+    ASSERT_NE(flags1, flags2);
+}
+
+TEST(Flags, EqualsOperator) {
+    Flags<TestFlags> flags;
+    flags = TestFlags::ONE;
+    ASSERT_TRUE(flags.test(TestFlags::ONE));
+    ASSERT_FALSE(flags.any(TestFlags::TWO | TestFlags::THREE));
+}
+
+TEST(Flags, EqualsOperator_DontShareState) {
+    Flags<TestFlags> flags1 = TestFlags::ONE | TestFlags::TWO;
+    Flags<TestFlags> flags2 = flags1;
+    ASSERT_EQ(flags1, flags2);
+
+    flags1 &= TestFlags::TWO;
+    ASSERT_NE(flags1, flags2);
+}
+
+TEST(Flags, String_NoFlagsWithDefaultStringify) {
+    Flags<TestFlags> flags;
+    ASSERT_EQ(flags.string(), "0x0");
+}
+
+TEST(Flags, String_NoFlagsWithNonDefaultStringify) {
+    Flags<TestFlags> flags;
+    ASSERT_EQ(flags.string(toStringComplete), "0x0");
+}
+
+TEST(Flags, String_WithDefaultStringify) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
+    ASSERT_EQ(flags.string(), "0x00000003");
+}
+
+TEST(Flags, String_WithCompleteStringify) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::TWO;
+    ASSERT_EQ(flags.string(toStringComplete), "ONE | TWO");
+}
+
+TEST(Flags, String_WithIncompleteStringify) {
+    Flags<TestFlags> flags = TestFlags::ONE | TestFlags::THREE;
+    ASSERT_EQ(flags.string(toStringIncomplete), "ONE | 0x00000004");
+}
+
+} // namespace android::test
\ No newline at end of file
diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp
index cdea922..e7a4587 100644
--- a/libs/input/tests/InputWindow_test.cpp
+++ b/libs/input/tests/InputWindow_test.cpp
@@ -44,8 +44,8 @@
     i.token = new BBinder();
     i.id = 1;
     i.name = "Foobar";
-    i.layoutParamsFlags = 7;
-    i.layoutParamsType = 39;
+    i.flags = InputWindowInfo::Flag::SLIPPERY;
+    i.type = InputWindowInfo::Type::INPUT_METHOD;
     i.dispatchingTimeout = 12s;
     i.frameLeft = 93;
     i.frameTop = 34;
@@ -62,7 +62,7 @@
     i.paused = false;
     i.ownerPid = 19;
     i.ownerUid = 24;
-    i.inputFeatures = 29;
+    i.inputFeatures = InputWindowInfo::Feature::DISABLE_USER_ACTIVITY;
     i.displayId = 34;
     i.portalToDisplayId = 2;
     i.replaceTouchableRegionWithCrop = true;
@@ -76,8 +76,8 @@
     ASSERT_EQ(i.token, i2.token);
     ASSERT_EQ(i.id, i2.id);
     ASSERT_EQ(i.name, i2.name);
-    ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags);
-    ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType);
+    ASSERT_EQ(i.flags, i2.flags);
+    ASSERT_EQ(i.type, i2.type);
     ASSERT_EQ(i.dispatchingTimeout, i2.dispatchingTimeout);
     ASSERT_EQ(i.frameLeft, i2.frameLeft);
     ASSERT_EQ(i.frameTop, i2.frameTop);