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

Commit ea8a433d authored by Candice Lo's avatar Candice Lo Committed by Android (Google) Code Review
Browse files

Merge changes I4a42b718,I0cf8f90d,I0d7916b6 into main

* changes:
  Invert everything for text if it is ForceInvert
  Change the order of how forceDark and forceInvert are applied
  Remove light background related tests
parents ab12b117 3fb9b227
Loading
Loading
Loading
Loading
+16 −9
Original line number Diff line number Diff line
@@ -2057,6 +2057,21 @@ public final class ViewRootImpl implements ViewParent,
    public @ForceDarkType.ForceDarkTypeDef int determineForceDarkType() {
        TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
        try {
            // Checking if the app choose to apply AutoDark for its dark theme before applying
            // forceInvertDark from the system.
            boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
            if (useAutoDark) {
                boolean forceDarkAllowedDefault =
                        SystemProperties.getBoolean(ThreadedRenderer.DEBUG_FORCE_DARK, false);
                useAutoDark = a.getBoolean(R.styleable.Theme_isLightTheme, true)
                        && a.getBoolean(R.styleable.Theme_forceDarkAllowed,
                            forceDarkAllowedDefault);
                if (useAutoDark) {
                    return ForceDarkType.FORCE_DARK;
                }
            }
            if (forceInvertColor()) {
                // Force invert ignores all developer opt-outs.
                // We also ignore dark theme, since the app developer can override the user's
@@ -2076,15 +2091,7 @@ public final class ViewRootImpl implements ViewParent,
                }
            }
            boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
            if (useAutoDark) {
                boolean forceDarkAllowedDefault =
                        SystemProperties.getBoolean(ThreadedRenderer.DEBUG_FORCE_DARK, false);
                useAutoDark = a.getBoolean(R.styleable.Theme_isLightTheme, true)
                        && a.getBoolean(R.styleable.Theme_forceDarkAllowed,
                            forceDarkAllowedDefault);
            }
            return useAutoDark ? ForceDarkType.FORCE_DARK : ForceDarkType.NONE;
            return ForceDarkType.NONE;
        } finally {
            a.recycle();
        }
+18 −0
Original line number Diff line number Diff line
@@ -95,4 +95,22 @@
        <item name="android:height">200px</item>
    </style>

    <style name="ForceDarkAllowed" />
    <style name="ForceDarkAllowed.Light">
        <item name="android:isLightTheme">true</item>
        <item name="android:forceDarkAllowed">true</item>
    </style>
    <style name="ForceDarkAllowed.Dark">
        <item name="android:isLightTheme">false</item>
        <item name="android:forceDarkAllowed">true</item>
    </style>
    <style name="ForceDarkAllowedFalse" />
    <style name="ForceDarkAllowedFalse.Light">
        <item name="android:isLightTheme">true</item>
        <item name="android:forceDarkAllowed">false</item>
    </style>
    <style name="ForceDarkAllowedFalse.Dark">
        <item name="android:isLightTheme">false</item>
        <item name="android:forceDarkAllowed">false</item>
    </style>
</resources>
+45 −81
Original line number Diff line number Diff line
@@ -24,8 +24,8 @@ import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT;
import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
import static android.view.Surface.FRAME_RATE_COMPATIBILITY_AT_LEAST;
import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
@@ -58,18 +58,15 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import android.annotation.NonNull;
import android.app.Instrumentation;
import android.app.UiModeManager;
import android.content.Context;
import android.graphics.Color;
import android.graphics.ForceDarkType;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Binder;
import android.os.SystemProperties;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsEnabled;
@@ -92,6 +89,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.TestUtils;
import com.android.cts.input.BlockingQueueEventVerifier;
import com.android.frameworks.coretests.R;
import com.android.window.flags.Flags;

import org.hamcrest.Matcher;
@@ -169,8 +167,6 @@ public class ViewRootImplTest {

            var uiModeManager = sContext.getSystemService(UiModeManager.class);
            uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);

            setForceDarkSysProp(false);
        });
        if (mView != null) {
            sInstrumentation.runOnMainSync(() -> {
@@ -1478,14 +1474,12 @@ public class ViewRootImplTest {

    @Test
    @EnableFlags(FLAG_FORCE_INVERT_COLOR)
    public void
            determineForceDarkType_isLightThemeAndIsLightBackground_returnsForceInvertColorDark()
            throws Exception {
    public void determineForceDarkType_isLightTheme_returnsForceInvertColorDark() throws Exception {
        // Set up configurations for force invert color
        waitForSystemNightModeActivated(true);
        enableForceInvertColor(true);

        setUpViewAttributes(/* isLightTheme= */ true, /* isLightBackground = */ true);
        setUpViewAttributes(/* isLightTheme= */ true, /* isForceDarkAllowed= */ false);

        TestUtils.waitUntil("Waiting for ForceDarkType to be ready",
                () -> (mViewRootImpl.determineForceDarkType()
@@ -1494,83 +1488,58 @@ public class ViewRootImplTest {

    @Test
    @EnableFlags(FLAG_FORCE_INVERT_COLOR)
    public void
            determineForceDarkType_isLightThemeAndNotLightBackground_returnsForceInvertColorDark()
            throws Exception {
    public void determineForceDarkType_notLightTheme_returnsNone() throws Exception {
        // Set up configurations for force invert color
        waitForSystemNightModeActivated(true);
        enableForceInvertColor(true);

        setUpViewAttributes(/* isLightTheme= */ true, /* isLightBackground = */ false);
        setUpViewAttributes(/* isLightTheme= */ false, /* isForceDarkAllowed= */ false);

        TestUtils.waitUntil("Waiting for ForceDarkType to be ready",
                () -> (mViewRootImpl.determineForceDarkType()
                        == ForceDarkType.FORCE_INVERT_COLOR_DARK));
                () -> (mViewRootImpl.determineForceDarkType() == ForceDarkType.NONE));
    }

    @Test
    @EnableFlags(FLAG_FORCE_INVERT_COLOR)
    public void determineForceDarkType_notLightThemeAndIsLightBackground_returnsNone()
            throws Exception {
    public void forceInvertOffForceDarkOff_forceDarkModeDisabled() {
        // Set up configurations for force invert color
        waitForSystemNightModeActivated(true);
        enableForceInvertColor(true);
        enableForceInvertColor(false);

        setUpViewAttributes(/* isLightTheme= */ false, /* isLightBackground = */ true);
        // Set up view attributes
        setUpViewAttributes(
                /* isLightTheme= */ false,
                /* isForceDarkAllowed= */ false);

        TestUtils.waitUntil("Waiting for ForceDarkType to be ready",
                () -> (mViewRootImpl.determineForceDarkType() == ForceDarkType.NONE));
        assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.NONE);
    }

    @Test
    @EnableFlags(FLAG_FORCE_INVERT_COLOR)
    public void determineForceDarkType_notLightThemeAndNotLightBackground_returnsNone()
            throws Exception {
    public void forceInvertOffForceDarkOn_forceDarkModeEnabled() {
        // Set up configurations for force invert color
        waitForSystemNightModeActivated(true);
        enableForceInvertColor(true);

        setUpViewAttributes(/* isLightTheme= */ false, /* isLightBackground = */ false);

        TestUtils.waitUntil("Waiting for ForceDarkType to be ready",
                () -> (mViewRootImpl.determineForceDarkType() == ForceDarkType.NONE));
    }

    @Test
    @EnableFlags(FLAG_FORCE_INVERT_COLOR)
    public void forceInvertOffForceDarkOff_forceDarkModeDisabled() {
        ShellIdentityUtils.invokeWithShellPermissions(() -> {
            Settings.Secure.putInt(
                    sContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
                    /* value= */ 0
            );

            // TODO(b/297556388): figure out how to set this without getting blocked by SELinux
            assumeTrue(setForceDarkSysProp(true));
        });
        enableForceInvertColor(false);

        sInstrumentation.runOnMainSync(() ->
                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
        // Set up view attributes
        setUpViewAttributes(
                /* isLightTheme= */ true,
                /* isForceDarkAllowed= */ true);

        assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.NONE);
        assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.FORCE_DARK);
    }

    @Test
    @EnableFlags(FLAG_FORCE_INVERT_COLOR)
    public void forceInvertOffForceDarkOn_forceDarkModeEnabled() {
        ShellIdentityUtils.invokeWithShellPermissions(() -> {
            Settings.Secure.putInt(
                    sContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
                    /* value= */ 0
            );

            assumeTrue(setForceDarkSysProp(true));
        });
    public void forceInvertOnForceDarkOn_forceDarkModeEnabled() {
        // Set up configurations for force invert color
        waitForSystemNightModeActivated(true);
        enableForceInvertColor(true);

        sInstrumentation.runOnMainSync(() ->
                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
        // Setup view attributes
        setUpViewAttributes(
                /* isLightTheme= */ true,
                /* isForceDarkAllowed= */ true);

        assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.FORCE_DARK);
    }
@@ -1658,19 +1627,6 @@ public class ViewRootImplTest {
        assertThat(bounds.height()).isAtLeast(strokeWidth * 2);
    }

    private boolean setForceDarkSysProp(boolean isForceDarkEnabled) {
        try {
            SystemProperties.set(
                    ThreadedRenderer.DEBUG_FORCE_DARK,
                    Boolean.toString(isForceDarkEnabled)
            );
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Failed to set force_dark sysprop", e);
            return false;
        }
    }

    static class InputView extends View {
        private final BlockingQueue<InputEvent> mEvents = new LinkedBlockingQueue<>();
        private final BlockingQueueEventVerifier mVerifier =
@@ -1797,10 +1753,23 @@ public class ViewRootImplTest {
        });
    }

    private void setUpViewAttributes(boolean isLightTheme, boolean isLightBackground) {
    private void setUpViewAttributes(boolean isLightTheme, boolean isForceDarkAllowed) {
        ShellIdentityUtils.invokeWithShellPermissions(() -> {
            sContext.setTheme(isLightTheme ? android.R.style.Theme_DeviceDefault_Light
                    : android.R.style.Theme_DeviceDefault);
            int themeId;
            if (isForceDarkAllowed) {
                if (isLightTheme) {
                    themeId = R.style.ForceDarkAllowed_Light;
                } else {
                    themeId = R.style.ForceDarkAllowed_Dark;
                }
            } else {
                if (isLightTheme) {
                    themeId = R.style.ForceDarkAllowedFalse_Light;
                } else {
                    themeId = R.style.ForceDarkAllowedFalse_Dark;
                }
            }
            sContext.setTheme(themeId);
        });

        sInstrumentation.runOnMainSync(() -> {
@@ -1809,11 +1778,6 @@ public class ViewRootImplTest {
                    TYPE_APPLICATION_OVERLAY);
            layoutParams.token = new Binder();
            view.setLayoutParams(layoutParams);
            if (isLightBackground) {
                view.setBackgroundColor(Color.WHITE);
            } else {
                view.setBackgroundColor(Color.BLACK);
            }
            mViewRootImpl.setView(view, layoutParams, /* panelParentView= */ null);
            mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId());
        });
+7 −0
Original line number Diff line number Diff line
@@ -1227,6 +1227,13 @@ template<>
constexpr color_transform_fn colorTransformForOp<DrawTextBlob>() {
    return [](const void *opRaw, ColorTransform transform) {
        const DrawTextBlob *op = reinterpret_cast<const DrawTextBlob*>(opRaw);
        if (transform == ColorTransform::Invert) {
            // Invert the colors no matter the usages of the ops to guarantee the contrast between
            // ops when we perform a full force invert
            transformPaint(transform, const_cast<SkPaint*>(&(op->paint)));
            return;
        }

        switch (op->drawTextBlobMode) {
        case DrawTextBlobMode::HctOutline:
            const_cast<SkPaint&>(op->paint).setColor(SK_ColorBLACK);