Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe97af4f authored by Tyler Freeman's avatar Tyler Freeman
Browse files

feat(force invert): force invert the entire app if its polarity is light

Instead of forcing dark each rendernode individually, we force invert
the entire app. This helps us avoid issues where some text or icons
don't get detected as dark, and they get inverted, causing black-on-
black text, etc.

By checking if the app is in light theme, and then inverting all the
RenderNodes indiscriminately, we have a much smaller chance of missing
some individual RenderNode.

This also disables the old force invert behavior even when the flag is
enabled. Force invert will supersede force dark if
android.view.accessibility.Flags.forceInvertColor is enabled.

Bug: 372558459
Flag: android.view.accessibility.force_invert_color
Test: manual: tested LinkedIn, Fitbit, Amazon

Change-Id: I296b7303b602938eee54d2e382a3c9dd4c4e9f15
parent 4ad7a592
Loading
Loading
Loading
Loading
+11 −5
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@
#ifdef __ANDROID__
#ifdef __ANDROID__
#include "include/gpu/ganesh/SkImageGanesh.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
#endif
#endif
#include "FeatureFlags.h"
#include "utils/ForceDark.h"
#include "utils/ForceDark.h"
#include "utils/MathUtils.h"
#include "utils/MathUtils.h"
#include "utils/StringUtils.h"
#include "utils/StringUtils.h"
@@ -409,8 +410,10 @@ void RenderNode::syncDisplayList(TreeObserver& observer, TreeInfo* info) {
// Return true if the tree should use the force invert feature that inverts
// Return true if the tree should use the force invert feature that inverts
// the entire tree to darken it.
// the entire tree to darken it.
inline bool RenderNode::isForceInvertDark(TreeInfo& info) {
inline bool RenderNode::isForceInvertDark(TreeInfo& info) {
    return CC_UNLIKELY(info.forceDarkType ==
    return CC_UNLIKELY(view_accessibility_flags::force_invert_color() &&
                       android::uirenderer::ForceDarkType::FORCE_INVERT_COLOR_DARK);
                       info.forceDarkType ==
                               android::uirenderer::ForceDarkType::FORCE_INVERT_COLOR_DARK &&
                       info.colorArea && info.colorArea->getPolarity() == Polarity::Light);
}
}


// Return true if the tree should use the force dark feature that selectively
// Return true if the tree should use the force dark feature that selectively
@@ -435,12 +438,15 @@ void RenderNode::gatherColorAreasForSubtree(ColorArea& target, bool isModeFull)
    }
    }
}
}


void RenderNode::handleForceDark(TreeInfo *info) {
void RenderNode::handleForceDark(android::uirenderer::TreeInfo* info) {
    if (CC_UNLIKELY(view_accessibility_flags::force_invert_color() && info &&
    if (CC_UNLIKELY(info && isForceInvertDark(*info))) {
                    isForceInvertDark(*info))) {
        // TODO(b/391959649): what about apps who have opted in to force dark, but only partially?
        //  will this mess them up? e.g. if they set disableForceDark but only on a few nodes.
        // The app is too bright, captain! Reverse the polarity!
        mDisplayList.applyColorTransform(ColorTransform::Invert);
        mDisplayList.applyColorTransform(ColorTransform::Invert);
        return;
        return;
    }
    }

    if (!shouldEnableForceDark(info)) {
    if (!shouldEnableForceDark(info)) {
        return;
        return;
    }
    }
+1 −1
Original line number Original line Diff line number Diff line
@@ -24,7 +24,7 @@ TreeInfo::TreeInfo(TraversalMode mode, renderthread::CanvasContext& canvasContex
        : mode(mode)
        : mode(mode)
        , prepareTextures(mode == MODE_FULL)
        , prepareTextures(mode == MODE_FULL)
        , canvasContext(canvasContext)
        , canvasContext(canvasContext)
        , disableForceDark(canvasContext.getForceDarkType() == ForceDarkType::NONE ? 1 : 0)
        , disableForceDark(canvasContext.getForceDarkType() == ForceDarkType::FORCE_DARK ? 0 : 1)
        , forceDarkType(canvasContext.getForceDarkType())
        , forceDarkType(canvasContext.getForceDarkType())
        , screenSize(canvasContext.getNextFrameSize()) {}
        , screenSize(canvasContext.getNextFrameSize()) {}