Revert "feat(force invert): detect the polarity of an app to dec..."

Revert submission 30679429-forcedark-colorarea-detection

Reason for revert: Triggered a performance regression

Bug: 410295655

Reverted changes: /q/submissionid:30679429-forcedark-colorarea-detection

Change-Id: I8cbf0af2fd567b1a125cb3e5abe9617cf3eb9df6
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 8f50bde..7251622 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -135,10 +135,10 @@
 import static com.android.text.flags.Flags.disableHandwritingInitiatorForIme;
 import static com.android.window.flags.Flags.enableBufferTransformHintFromDisplay;
 import static com.android.window.flags.Flags.enableWindowContextResourcesUpdateOnConfigChange;
-import static com.android.window.flags.Flags.fixViewRootCallTrace;
 import static com.android.window.flags.Flags.predictiveBackSwipeEdgeNoneApi;
 import static com.android.window.flags.Flags.reduceChangedExclusionRectsMsgs;
 import static com.android.window.flags.Flags.setScPropertiesInClient;
+import static com.android.window.flags.Flags.fixViewRootCallTrace;
 
 import android.Manifest;
 import android.accessibilityservice.AccessibilityService;
@@ -190,6 +190,7 @@
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.graphics.RenderNode;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.GradientDrawable;
 import android.hardware.SyncFence;
@@ -293,6 +294,7 @@
 import com.android.internal.policy.DecorView;
 import com.android.internal.policy.PhoneFallbackEventHandler;
 import com.android.internal.protolog.ProtoLog;
+import com.android.internal.util.ContrastColorUtil;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.RootViewSurfaceTaker;
@@ -2086,12 +2088,21 @@
                 // preference for dark mode in configuration.uiMode. Instead, we assume that both
                 // force invert and the system's dark theme are enabled.
                 if (shouldApplyForceInvertDark()) {
-                    // We will use HWUI color area detection to determine if it should actually be
-                    // inverted. Checking light theme simply gives the developer a way to "opt-out"
-                    // of force invert.
+                    // TODO: b/368725782 - Use hwui color area detection instead of / in
+                    //  addition to these heuristics.
                     final boolean isLightTheme =
                             a.getBoolean(R.styleable.Theme_isLightTheme, false);
-                    if (isLightTheme) {
+                    final boolean isBackgroundColorLight;
+                    if (mView != null && mView.getBackground()
+                            instanceof ColorDrawable colorDrawable) {
+                        isBackgroundColorLight =
+                                !ContrastColorUtil.isColorDarkLab(colorDrawable.getColor());
+                    } else {
+                        // Treat unknown as light, so that only isLightTheme is used to determine
+                        // force dark treatment.
+                        isBackgroundColorLight = true;
+                    }
+                    if (isLightTheme && isBackgroundColorLight) {
                         return ForceDarkType.FORCE_INVERT_COLOR_DARK;
                     } else {
                         return ForceDarkType.NONE;
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 5d178ac..1b7805c 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -1548,7 +1548,7 @@
 
     @Test
     @EnableFlags(FLAG_FORCE_INVERT_COLOR)
-    public void determineForceDarkType_isLightThemeAndNotLightBackground_returnsForceInvertColorDark()
+    public void determineForceDarkType_isLightThemeAndNotLightBackground_returnsNone()
             throws Exception {
         // Set up configurations for force invert color
         waitForSystemNightModeActivated(true);
@@ -1557,8 +1557,7 @@
         setUpViewAttributes(/* isLightTheme= */ true, /* isLightBackground = */ false);
 
         TestUtils.waitUntil("Waiting for ForceDarkType to be ready",
-                () -> (mViewRootImpl.determineForceDarkType()
-                        == ForceDarkType.FORCE_INVERT_COLOR_DARK));
+                () -> (mViewRootImpl.determineForceDarkType() == ForceDarkType.NONE));
     }
 
     @Test
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index f943cad..1bde5ff 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -616,7 +616,6 @@
         "Animator.cpp",
         "AnimatorManager.cpp",
         "CanvasTransform.cpp",
-        "ColorArea.cpp",
         "DamageAccumulator.cpp",
         "DeviceInfo.cpp",
         "FrameInfo.cpp",
diff --git a/libs/hwui/ColorArea.cpp b/libs/hwui/ColorArea.cpp
deleted file mode 100644
index 8d4320a..0000000
--- a/libs/hwui/ColorArea.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2024 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 "ColorArea.h"
-
-#include "utils/MathUtils.h"
-
-namespace android::uirenderer {
-
-constexpr static int kMinimumAlphaToConsiderArea = 200;
-
-void ColorArea::addArea(const SkRect& rect, const SkPaint* paint) {
-    addArea(rect.width(), rect.height(), paint);
-}
-
-void ColorArea::addArea(int32_t width, int32_t height, const SkPaint* paint) {
-    if (!paint) return;
-    // HWUI doesn't draw anything with negative width or height
-    if (width <= 0 || height <= 0) return;
-
-    uint64_t area = width * height;
-    addArea(area, *paint);
-}
-
-void ColorArea::addArea(uint64_t area, const SkPaint& paint) {
-    if (paint.getStyle() == SkPaint::Style::kStroke_Style) return;
-    if (CC_UNLIKELY(paint.nothingToDraw())) return;
-
-    if (paint.getShader()) {
-        // TODO(b/409395389): check if the shader is a gradient, and then slice up area into
-        //  sections, determining polarity for each color stop of the gradient.
-        return;
-    }
-
-    addArea(area, paint.getColor());
-}
-
-void ColorArea::addArea(uint64_t area, SkColor color) {
-    if (CC_UNLIKELY(SkColorGetA(color) < kMinimumAlphaToConsiderArea)) return;
-
-    // TODO(b/381930266): optimize by detecting common black/white/grey colors and avoid converting
-    //  also maybe cache colors or something?
-    Lab lab = sRGBToLab(color);
-    // TODO(b/372558459): add a case for a middle L that is grey, and don't count it?
-    addArea(area, lab.L > 50 ? Light : Dark);
-}
-
-void ColorArea::addArea(uint64_t area, Polarity polarity) {
-    // HWUI doesn't draw anything with negative width or height
-    if (area <= 0) return;
-
-    if (polarity == Light) {
-        mLight += area;
-    } else if (polarity == Dark) {
-        mDark += area;
-    }
-}
-
-Polarity ColorArea::getPolarity() const {
-    if (mLight == mDark) {  // also covers the case if it was just reset()
-        return Polarity::Unknown;
-    }
-    if (mLight > mDark) {
-        return Polarity::Light;
-    } else {
-        return Polarity::Dark;
-    }
-}
-
-void ColorArea::reset() {
-    mParentHeight = -1;
-    mParentWidth = -1;
-    mLight = 0;
-    mDark = 0;
-}
-
-void ColorArea::merge(const ColorArea& source) {
-    mLight += source.mLight;
-    mDark += source.mDark;
-}
-
-int ColorArea::getParentWidth() const {
-    return mParentWidth;
-}
-
-void ColorArea::setParentWidth(int width) {
-    mParentWidth = width;
-}
-
-int ColorArea::getParentHeight() const {
-    return mParentHeight;
-}
-
-void ColorArea::setParentHeight(int height) {
-    mParentHeight = height;
-}
-
-}  // namespace android::uirenderer
diff --git a/libs/hwui/ColorArea.h b/libs/hwui/ColorArea.h
deleted file mode 100644
index 807826d..0000000
--- a/libs/hwui/ColorArea.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-#pragma once
-
-#include <SkCanvas.h>
-#include <SkPaintFilterCanvas.h>
-
-#include "utils/Color.h"
-#include "utils/Macros.h"
-
-namespace android::uirenderer {
-
-/**
- * The result of counting the color area.
- */
-enum Polarity {
-    /** The result is too close to make a definite determination */
-    Unknown = 0,
-    /** Majority light fills */
-    Light,
-    /** Majority dark fills */
-    Dark
-};
-
-/**
- * Tracks the app's overall polarity (i.e. dark or light theme) by counting the areas of backgrounds
- * and their colors. This is used to determine if we should force invert the app, for instance if
- * the user prefers dark theme but this app is mainly light.
- *
- * The idea is that we count the fill colors of any background-type draw calls: drawRect(),
- * drawColor(), etc. If the area of light fills drawn to the screen is greater than the area of dark
- * fills drawn to the screen, we can reasonably guess that the app is light theme, and vice-versa.
- */
-class ColorArea {
-public:
-    ColorArea() {}
-    ~ColorArea() {}
-
-    /**
-     * Counts the given area of a draw call that is reasonably expected to draw a background:
-     * drawRect, drawColor, etc.
-     *
-     * @param area the total area of the draw call's fill (approximate)
-     * @param paint the paint used to fill the area. If the paint is not a fill, the area will not
-     *              be added.
-     */
-    void addArea(uint64_t area, const SkPaint& paint);
-
-    /**
-     * See [addArea(uint64_t, SkPaint&)]
-     */
-    void addArea(const SkRect& rect, const SkPaint* paint);
-
-    /**
-     * See [addArea(uint64_t, SkPaint&)]
-     */
-    void addArea(int32_t width, int32_t height, const SkPaint* paint);
-
-    /**
-     * See [addArea(uint64_t, SkPaint&)]
-     */
-    void addArea(uint64_t area, SkColor color);
-
-    /**
-     * Prefer [addArea(uint64_t, SkPaint&)], unless the area you're measuring doesn't have a paint
-     * with measurable colors.
-     *
-     * @param area the total area of the draw call's fill (approximate)
-     * @param polarity whether the color of the given area is light or dark
-     */
-    void addArea(uint64_t area, Polarity polarity);
-
-    /**
-     * Adds the source's area to this area. This is so you can sum up the areas of a bunch of child
-     * nodes.
-     */
-    void merge(const ColorArea& source);
-
-    /** Resets the object back to the initial state */
-    void reset();
-
-    int getParentWidth() const;
-    void setParentWidth(int width);
-    int getParentHeight() const;
-    void setParentHeight(int height);
-
-    /** Returns the best guess of the polarity of this area */
-    Polarity getPolarity() const;
-
-private:
-    int mParentWidth = -1;
-    int mParentHeight = -1;
-
-    uint64_t mLight = 0;
-    uint64_t mDark = 0;
-};
-
-}  // namespace android::uirenderer
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 894454d..b1c5bf4 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -16,13 +16,12 @@
 
 #pragma once
 
+#include "pipeline/skia/SkiaDisplayList.h"
+#include "canvas/CanvasOpBuffer.h"
+
 #include <memory>
 #include <variant>
 
-#include "ColorArea.h"
-#include "canvas/CanvasOpBuffer.h"
-#include "pipeline/skia/SkiaDisplayList.h"
-
 namespace android {
 namespace uirenderer {
 
@@ -154,13 +153,6 @@
         }
     }
 
-    /** Adds all relevant draw calls with fills to the given ColorArea */
-    void findFillAreas(ColorArea& accumulator) {
-        if (mImpl) {
-            mImpl->findFillAreas(accumulator);
-        }
-    }
-
 private:
     std::unique_ptr<skiapipeline::SkiaDisplayList> mImpl;
 };
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 186f168..0d09fb1 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -27,7 +27,6 @@
 #include <experimental/type_traits>
 #include <utility>
 
-#include "FeatureFlags.h"
 #include "Mesh.h"
 #include "SkAndroidFrameworkUtils.h"
 #include "SkBlendMode.h"
@@ -802,80 +801,6 @@
     return (value & (value - 1)) == 0;
 }
 
-template <class T>
-using has_paint_helper = decltype(std::declval<T>().paint);
-
-template <class T>
-constexpr bool has_paint = std::experimental::is_detected_v<has_paint_helper, T>;
-
-template <class T>
-using has_palette_helper = decltype(std::declval<T>().palette);
-
-template <class T>
-constexpr bool has_palette = std::experimental::is_detected_v<has_palette_helper, T>;
-
-inline bool DisplayListData::shouldCountColorAreas() const {
-    return view_accessibility_flags::force_invert_color();
-}
-
-typedef void (*color_area_fn)(const void*, ColorArea*);
-
-template <class T>
-using has_bounds_helper = decltype(std::declval<T>().getConservativeBounds());
-
-template <class T>
-constexpr bool has_bounds = std::experimental::is_detected_v<has_bounds_helper, T>;
-
-template <class T>
-constexpr color_area_fn colorAreaForOp() {
-    if constexpr (has_paint<T> && has_bounds<T>) {
-        return [](const void* opRaw, ColorArea* accumulator) {
-            const T* op = reinterpret_cast<const T*>(opRaw);
-            const SkPaint* paint = &op->paint;
-            if (!paint) return;
-
-            auto rect = op->getConservativeBounds();
-            if (!rect.has_value()) return;
-
-            accumulator->addArea(*rect, paint);
-        };
-    } else {
-        return nullptr;
-    }
-}
-
-template <>
-constexpr color_area_fn colorAreaForOp<DrawBehind>() {
-    return [](const void* opRaw, ColorArea* accumulator) {
-        const DrawBehind* op = reinterpret_cast<const DrawBehind*>(opRaw);
-        const SkPaint* paint = &op->paint;
-
-        // drawColor() fills the entire canvas area / RenderNode. We are ignoring clipping for now,
-        // since usually people only slightly exceed their bounds.
-        accumulator->addArea(accumulator->getParentWidth() * accumulator->getParentHeight(),
-                             *paint);
-    };
-}
-
-template <>
-constexpr color_area_fn colorAreaForOp<DrawPaint>() {
-    return [](const void* opRaw, ColorArea* accumulator) {
-        const DrawPaint* op = reinterpret_cast<const DrawPaint*>(opRaw);
-        const SkPaint* paint = &op->paint;
-
-        // drawColor() fills the entire canvas area / RenderNode. We are ignoring clipping for now,
-        // since usually people only slightly exceed their bounds.
-        accumulator->addArea(accumulator->getParentWidth() * accumulator->getParentHeight(),
-                             *paint);
-    };
-}
-
-#define X(T) colorAreaForOp<T>(),
-static const color_area_fn color_area_fns[] = {
-#include "DisplayListOps.in"
-};
-#undef X
-
 template <typename T>
 constexpr bool doesPaintHaveFill(T& paint) {
     using T1 = std::remove_cv_t<T>;
@@ -923,12 +848,6 @@
         }
     }
 
-    if (shouldCountColorAreas()) {
-        if (auto fn = color_area_fns[op->type]) {
-            fn(op, &mColorArea);
-        }
-    }
-
     return op + 1;
 }
 
@@ -1147,32 +1066,44 @@
 
     // Leave fBytes and fReserved alone.
     fUsed = 0;
-
-    // TODO(b/372558459): reset here only?
-    mColorArea.reset();
 }
 
 template <class T>
+using has_paint_helper = decltype(std::declval<T>().paint);
+
+template <class T>
+constexpr bool has_paint = std::experimental::is_detected_v<has_paint_helper, T>;
+
+template <class T>
+using has_palette_helper = decltype(std::declval<T>().palette);
+
+template <class T>
+constexpr bool has_palette = std::experimental::is_detected_v<has_palette_helper, T>;
+
+template <class T>
 constexpr color_transform_fn colorTransformForOp() {
     if
         constexpr(has_paint<T> && has_palette<T>) {
-        // It's a bitmap
-        return [](const void* opRaw, ColorTransform transform) {
-            // TODO: We should be const. Or not. Or just use a different map
-            // Unclear, but this is the quick fix
-            const T* op = reinterpret_cast<const T*>(opRaw);
-            const SkPaint* paint = &op->paint;
-            transformPaint(transform, const_cast<SkPaint*>(paint), op->palette);
-        };
-    } else if constexpr (has_paint<T>) {
-        return [](const void* opRaw, ColorTransform transform) {
-            // TODO: We should be const. Or not. Or just use a different map
-            // Unclear, but this is the quick fix
-            const T* op = reinterpret_cast<const T*>(opRaw);
-            const SkPaint* paint = &op->paint;
-            transformPaint(transform, const_cast<SkPaint*>(paint));
-        };
-    } else {
+            // It's a bitmap
+            return [](const void* opRaw, ColorTransform transform) {
+                // TODO: We should be const. Or not. Or just use a different map
+                // Unclear, but this is the quick fix
+                const T* op = reinterpret_cast<const T*>(opRaw);
+                const SkPaint* paint = &op->paint;
+                transformPaint(transform, const_cast<SkPaint*>(paint), op->palette);
+            };
+        }
+    else if
+        constexpr(has_paint<T>) {
+            return [](const void* opRaw, ColorTransform transform) {
+                // TODO: We should be const. Or not. Or just use a different map
+                // Unclear, but this is the quick fix
+                const T* op = reinterpret_cast<const T*>(opRaw);
+                const SkPaint* paint = &op->paint;
+                transformPaint(transform, const_cast<SkPaint*>(paint));
+            };
+        }
+    else {
         return nullptr;
     }
 }
@@ -1215,15 +1146,6 @@
     this->map(color_transform_fns, transform);
 }
 
-void DisplayListData::findFillAreas(ColorArea& accumulator) {
-    accumulator.merge(mColorArea);
-}
-
-void DisplayListData::setBounds(const SkIRect& bounds) {
-    mColorArea.setParentWidth(bounds.width());
-    mColorArea.setParentHeight(bounds.height());
-}
-
 RecordingCanvas::RecordingCanvas() : INHERITED(1, 1), fDL(nullptr) {}
 
 void RecordingCanvas::reset(DisplayListData* dl, const SkIRect& bounds) {
@@ -1231,9 +1153,6 @@
     fDL = dl;
     mClipMayBeComplex = false;
     mSaveCount = mComplexSaveCount = 0;
-
-    // TODO(b/372558459) - Check if dl->reset() should be called here
-    dl->setBounds(bounds);
 }
 
 sk_sp<SkSurface> RecordingCanvas::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index a4ac8d4..f867852 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -32,7 +32,6 @@
 #include <vector>
 
 #include "CanvasTransform.h"
-#include "ColorArea.h"
 #include "Gainmap.h"
 #include "hwui/Bitmap.h"
 #include "pipeline/skia/AnimatedDrawables.h"
@@ -106,27 +105,15 @@
     void draw(SkCanvas* canvas) const;
 
     void reset();
-
-    /** Resets the ColorArea counter with the new bounds */
-    void setBounds(const SkIRect& bounds);
-
     bool empty() const { return fUsed == 0; }
 
     void applyColorTransform(ColorTransform transform);
 
-    /** Adds all relevant draw calls with fills to the given ColorArea */
-    void findFillAreas(ColorArea& accumulator);
-
-    const ColorArea& getColorArea() const { return mColorArea; }
-
     bool hasText() const { return mHasText; }
     bool hasFill() const { return mHasFill; }
     size_t usedSize() const { return fUsed; }
     size_t allocatedSize() const { return fReserved; }
 
-    /** Returns true if this list should count ColorAreas as Ops are recorded. */
-    bool shouldCountColorAreas() const;
-
 private:
     friend class RecordingCanvas;
 
@@ -197,8 +184,6 @@
 
     bool mHasText : 1;
     bool mHasFill : 1;
-
-    ColorArea mColorArea;
 };
 
 class RecordingCanvas final : public SkCanvasVirtualEnforcer<SkNoDrawCanvas> {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 2d88bd2..8b4e59a 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -419,22 +419,6 @@
     return CC_UNLIKELY(info && !info->disableForceDark);
 }
 
-void RenderNode::gatherColorAreasForSubtree(ColorArea& target, bool isModeFull) {
-    SkiaDisplayListWrapper* displayList = &mDisplayList;
-    if (isModeFull && mNeedsDisplayListSync) {
-        displayList = &mStagingDisplayList;
-    }
-
-    if (displayList && displayList->isValid() && !(displayList->isEmpty())) {
-        displayList->findFillAreas(target);
-        displayList->updateChildren([&target, &isModeFull](RenderNode* node) {
-            if (!node) return;
-
-            node->gatherColorAreasForSubtree(target, isModeFull);
-        });
-    }
-}
-
 void RenderNode::handleForceDark(TreeInfo *info) {
     if (CC_UNLIKELY(view_accessibility_flags::force_invert_color() && info &&
                     isForceInvertDark(*info))) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 7ea919b..afbbce7 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -225,9 +225,6 @@
     void markDrawStart(SkCanvas& canvas);
     void markDrawEnd(SkCanvas& canvas);
 
-    /** Accumulates all the background color areas of all children into the given target */
-    void gatherColorAreasForSubtree(ColorArea& target, bool isModeFull);
-
 private:
     void computeOrderingImpl(RenderNodeOp* opState,
                              std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 36152a66..88449f3 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -21,7 +21,6 @@
 #include <optional>
 #include <string>
 
-#include "ColorArea.h"
 #include "Properties.h"
 #include "SkSize.h"
 #include "SkippedFrameInfo.h"
@@ -93,8 +92,6 @@
     DamageAccumulator* damageAccumulator = nullptr;
     int64_t damageGenerationId = 0;
 
-    ColorArea* colorArea = nullptr;
-
     LayerUpdateQueue* layerUpdateQueue = nullptr;
     ErrorHandler* errorHandler = nullptr;
 
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 508a856..071a4e8 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -126,9 +126,6 @@
         mDisplayList.applyColorTransform(transform);
     }
 
-    /** Adds all relevant draw calls with fills to the given ColorArea */
-    void findFillAreas(ColorArea& accumulator) { mDisplayList.findFillAreas(accumulator); }
-
     /**
      * ONLY to be called by RenderNode::prepareTree in order to prepare this
      * list while the UI thread is blocked.  Here we can upload mutable bitmaps
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index b8e61fd..d5ac993 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -36,8 +36,6 @@
 
 #include "../Properties.h"
 #include "AnimationContext.h"
-#include "ColorArea.h"
-#include "FeatureFlags.h"
 #include "Frame.h"
 #include "LayerUpdateQueue.h"
 #include "Properties.h"
@@ -478,17 +476,11 @@
     mCurrentFrameInfo->markSyncStart();
 
     info.damageAccumulator = &mDamageAccumulator;
-    info.colorArea = &mColorArea;
     info.layerUpdateQueue = &mLayerUpdateQueue;
     info.damageGenerationId = mDamageId++;
     info.out.skippedFrameReason = std::nullopt;
 
     mAnimationContext->startFrame(info.mode);
-
-    if (target) {
-        determineColors(target);
-    }
-
     for (const sp<RenderNode>& node : mRenderNodes) {
         // Only the primary target node will be drawn full - all other nodes would get drawn in
         // real time mode. In case of a window, the primary node is the window content and the other
@@ -1034,7 +1026,6 @@
     ScopedActiveContext activeContext(this);
     TreeInfo info(TreeInfo::MODE_FULL, *this);
     info.damageAccumulator = &mDamageAccumulator;
-    info.colorArea = &mColorArea;
     info.layerUpdateQueue = &mLayerUpdateQueue;
     info.runAnimations = false;
     node->prepareTree(info);
@@ -1174,20 +1165,6 @@
     return windowDirty;
 }
 
-void CanvasContext::determineColors(const RenderNode* target) {
-    if (CC_UNLIKELY(view_accessibility_flags::force_invert_color() &&
-                    mForceDarkType == ForceDarkType::FORCE_INVERT_COLOR_DARK)) {
-        ATRACE_FORMAT("determineColors(): Color area calculation pre-pass");
-
-        // first pass: figure out if the app is light or dark mode
-        mColorArea.reset();
-
-        for (const sp<RenderNode>& node : mRenderNodes) {
-            node->gatherColorAreasForSubtree(mColorArea, target == node.get());
-        }
-    }
-}
-
 CanvasContext* CanvasContext::getActiveContext() {
     return ScopedActiveContext::getActiveContext();
 }
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 1e691ec..655aeba 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -30,7 +30,6 @@
 #include <utility>
 #include <vector>
 
-#include "ColorArea.h"
 #include "ColorMode.h"
 #include "DamageAccumulator.h"
 #include "FrameInfo.h"
@@ -208,8 +207,6 @@
 
     SkISize getNextFrameSize() const;
 
-    const ColorArea& getColorArea() const { return mColorArea; }
-
     // Returns the matrix to use to nudge non-AA'd points/lines towards the fragment center
     const SkM44& getPixelSnapMatrix() const;
 
@@ -337,7 +334,6 @@
 
     bool mHaveNewSurface = false;
     DamageAccumulator mDamageAccumulator;
-    ColorArea mColorArea;
     LayerUpdateQueue mLayerUpdateQueue;
     std::unique_ptr<AnimationContext> mAnimationContext;
 
@@ -386,15 +382,6 @@
         int64_t startTime;
     };
     std::optional<SkippedFrameInfo> mSkippedFrameInfo;
-
-    /**
-     * Does a pre-pass on all the nodes and populates mColorArea with color information. Used by
-     * force invert to determine if the app is light theme.
-     *
-     * @param target the target node to run in MODE_FULL. For this node, the staging displaylist is
-     *    used. All other nodes are treated in MODE_RT, using their main displaylists.
-     */
-    void determineColors(const RenderNode* target);
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/tests/unit/CanvasContextTests.cpp b/libs/hwui/tests/unit/CanvasContextTests.cpp
index 2f41e5e..47a4105 100644
--- a/libs/hwui/tests/unit/CanvasContextTests.cpp
+++ b/libs/hwui/tests/unit/CanvasContextTests.cpp
@@ -17,7 +17,6 @@
 #include <gtest/gtest.h>
 
 #include "AnimationContext.h"
-#include "FeatureFlags.h"
 #include "IContextFactory.h"
 #include "renderthread/CanvasContext.h"
 #include "renderthread/VulkanManager.h"
@@ -79,95 +78,3 @@
         }
     }
 }
-
-RENDERTHREAD_TEST(CanvasContext, forceInvertColorArea_detectsLightTheme) {
-    if (!view_accessibility_flags::force_invert_color()) {
-        GTEST_SKIP() << "Test only applies when force_invert_colorarea_detector flag is enabled";
-    }
-
-    auto buttonNode =
-            TestUtils::createNode(0, 0, 50, 100, [](RenderProperties& props, Canvas& canvas) {
-                Paint paint;
-                paint.setStyle(SkPaint::Style::kFill_Style);
-                paint.setColor(0xFFEE11CC);
-
-                canvas.drawRoundRect(0, 0, 50, 100, 5, 5, paint);
-            });
-    auto panelNode = TestUtils::createNode(0, 0, 100, 200,
-                                           [buttonNode](RenderProperties& props, Canvas& canvas) {
-                                               Paint paint;
-                                               paint.setStyle(SkPaint::Style::kFill_Style);
-                                               paint.setColor(0xEE111111);
-
-                                               canvas.drawRect(0, 0, 100, 200, paint);
-                                               canvas.drawRenderNode(buttonNode.get());
-                                           });
-
-    auto node = TestUtils::createNode(0, 0, 200, 400,
-                                      [panelNode](RenderProperties& props, Canvas& canvas) {
-                                          canvas.drawColor(0xFFEEEEE1, SkBlendMode::kSrc);
-
-                                          canvas.drawRenderNode(panelNode.get());
-                                      });
-    node->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
-
-    auto& cacheManager = renderThread.cacheManager();
-    ContextFactory contextFactory;
-    std::unique_ptr<CanvasContext> canvasContext(
-            CanvasContext::create(renderThread, false, node.get(), &contextFactory, 0, 0));
-    canvasContext->setForceDark(android::uirenderer::ForceDarkType::FORCE_INVERT_COLOR_DARK);
-
-    EXPECT_EQ(canvasContext->getColorArea().getPolarity(), Unknown);
-
-    canvasContext->prepareAndDraw(node.get());
-
-    EXPECT_EQ(canvasContext->getColorArea().getPolarity(), Light);
-
-    renderThread.destroyRenderingContext();
-}
-
-RENDERTHREAD_TEST(CanvasContext, forceInvertColorArea_detectsDarkTheme) {
-    if (!view_accessibility_flags::force_invert_color()) {
-        GTEST_SKIP() << "Test only applies when force_invert_colorarea_detector flag is enabled";
-    }
-
-    auto buttonNode =
-            TestUtils::createNode(0, 0, 50, 100, [](RenderProperties& props, Canvas& canvas) {
-                Paint paint;
-                paint.setStyle(SkPaint::Style::kFill_Style);
-                paint.setColor(0xFFFF5566);
-
-                canvas.drawRoundRect(0, 0, 50, 100, 5, 5, paint);
-            });
-    auto panelNode = TestUtils::createNode(0, 0, 100, 200,
-                                           [buttonNode](RenderProperties& props, Canvas& canvas) {
-                                               Paint paint;
-                                               paint.setStyle(SkPaint::Style::kFill_Style);
-                                               paint.setColor(0xFFCCCCCC);
-
-                                               canvas.drawRect(0, 0, 100, 200, paint);
-                                               canvas.drawRenderNode(buttonNode.get());
-                                           });
-
-    auto node = TestUtils::createNode(0, 0, 200, 400,
-                                      [panelNode](RenderProperties& props, Canvas& canvas) {
-                                          canvas.drawColor(0xFF030102, SkBlendMode::kSrc);
-
-                                          canvas.drawRenderNode(panelNode.get());
-                                      });
-    node->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
-
-    auto& cacheManager = renderThread.cacheManager();
-    ContextFactory contextFactory;
-    std::unique_ptr<CanvasContext> canvasContext(
-            CanvasContext::create(renderThread, false, node.get(), &contextFactory, 0, 0));
-    canvasContext->setForceDark(android::uirenderer::ForceDarkType::FORCE_INVERT_COLOR_DARK);
-
-    EXPECT_EQ(canvasContext->getColorArea().getPolarity(), Unknown);
-
-    canvasContext->prepareAndDraw(node.get());
-
-    EXPECT_EQ(canvasContext->getColorArea().getPolarity(), Dark);
-
-    renderThread.destroyRenderingContext();
-}