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

Commit 2274e83e authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Revert "feat(EDT): Update the force dark theme trigger condition"" into main

parents a0fe53e0 22ea2ffb
Loading
Loading
Loading
Loading
+45 −24
Original line number Diff line number Diff line
@@ -152,8 +152,6 @@ import android.annotation.UiContext;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ResourcesManager;
import android.app.UiModeManager;
import android.app.UiModeManager.ForceInvertStateChangeListener;
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
import android.app.servertransaction.WindowStateTransactionItem;
@@ -169,6 +167,7 @@ import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.BLASTBufferQueue;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -214,6 +213,7 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.os.Vibrator;
import android.provider.Settings;
import android.sysprop.DisplayProperties;
import android.sysprop.ViewProperties;
import android.text.TextUtils;
@@ -469,8 +469,10 @@ public final class ViewRootImpl implements ViewParent,
    private CompatOnBackInvokedCallback mCompatOnBackInvokedCallback;
    @Nullable
    private ForceInvertStateChangeListener mForceInvertStateChangeListener;
    private ContentObserver mForceInvertObserver;
    private static final int INVALID_VALUE = Integer.MIN_VALUE;
    private int mForceInvertEnabled = INVALID_VALUE;
    /**
     * Callback for notifying about global configuration changes.
     */
@@ -552,8 +554,6 @@ public final class ViewRootImpl implements ViewParent,
    @UiContext
    public final Context mContext;
    private UiModeManager mUiModeManager;
    @UnsupportedAppUsage
    final IWindowSession mWindowSession;
    @NonNull Display mDisplay;
@@ -1255,7 +1255,6 @@ public final class ViewRootImpl implements ViewParent,
    public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
            WindowLayout windowLayout) {
        mContext = context;
        mUiModeManager = context.getSystemService(UiModeManager.class);
        mWindowSession = session;
        mWindowLayout = windowLayout;
        mDisplay = display;
@@ -1804,6 +1803,23 @@ public final class ViewRootImpl implements ViewParent,
        }
    }
    private boolean isForceInvertEnabled() {
        if (mForceInvertEnabled == INVALID_VALUE) {
            reloadForceInvertEnabled();
        }
        return mForceInvertEnabled == 1;
    }
    private void reloadForceInvertEnabled() {
        if (forceInvertColor()) {
            mForceInvertEnabled = Settings.Secure.getIntForUser(
                    mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
                    /* def= */ 0,
                    UserHandle.myUserId());
        }
    }
    /**
     * Register any kind of listeners if setView was success.
     */
@@ -1835,11 +1851,21 @@ public final class ViewRootImpl implements ViewParent,
                        mBasePackageName);
        if (forceInvertColor()) {
            if (mForceInvertStateChangeListener == null) {
                mForceInvertStateChangeListener =
                        forceInvertState -> updateForceDarkMode();
                mUiModeManager.addForceInvertStateChangeListener(mExecutor,
                        mForceInvertStateChangeListener);
            if (mForceInvertObserver == null) {
                mForceInvertObserver = new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        reloadForceInvertEnabled();
                        updateForceDarkMode();
                    }
                };
                mContext.getContentResolver().registerContentObserver(
                        Settings.Secure.getUriFor(
                                Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED
                        ),
                        false,
                        mForceInvertObserver,
                        UserHandle.myUserId());
            }
        }
    }
@@ -1857,10 +1883,9 @@ public final class ViewRootImpl implements ViewParent,
                .unregisterDisplayListener(mDisplayListener);
        if (forceInvertColor()) {
            if (mForceInvertStateChangeListener != null) {
                mUiModeManager.removeForceInvertStateChangeListener(
                        mForceInvertStateChangeListener);
                mForceInvertStateChangeListener = null;
            if (mForceInvertObserver != null) {
                mContext.getContentResolver().unregisterContentObserver(mForceInvertObserver);
                mForceInvertObserver = null;
            }
        }
@@ -2047,25 +2072,21 @@ public final class ViewRootImpl implements ViewParent,
        return getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
    }
    /**
     * Determines the type of force dark to apply, considering force inversion, system night mode,
     * and app-specific settings (including developer opt-outs).
     *
     * @return A {@link ForceDarkType.ForceDarkTypeDef} constant indicating the force dark type.
     */
    /** Returns true if force dark should be enabled according to various settings */
    @VisibleForTesting
    public @ForceDarkType.ForceDarkTypeDef int determineForceDarkType() {
        if (forceInvertColor()) {
            // Force invert ignores all developer opt-outs.
            // We also ignore dark theme, since the app developer can override the user's preference
            // for dark mode in configuration.uiMode. Instead, we assume that both force invert and
            // the system's dark theme are enabled.
            if (mUiModeManager.getForceInvertState() == UiModeManager.FORCE_INVERT_TYPE_DARK) {
            // for dark mode in configuration.uiMode. Instead, we assume that the force invert
            // setting will be enabled at the same time dark theme is in the Settings app.
            if (isForceInvertEnabled()) {
                return ForceDarkType.FORCE_INVERT_COLOR_DARK;
            }
        }
        boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
        if (useAutoDark) {
            boolean forceDarkAllowedDefault =
                    SystemProperties.getBoolean(ThreadedRenderer.DEBUG_FORCE_DARK, false);
+44 −71
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package android.view;

import static android.app.UiModeManager.MODE_NIGHT_NO;
import static android.app.UiModeManager.MODE_NIGHT_YES;
import static android.util.SequenceUtils.getInitSeq;
import static android.view.HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING;
import static android.view.InputDevice.SOURCE_ROTARY_ENCODER;
@@ -69,10 +67,8 @@ import static org.junit.Assume.assumeTrue;
import android.annotation.NonNull;
import android.app.Instrumentation;
import android.app.UiModeManager;
import android.app.UiModeManager.ForceInvertType;
import android.content.Context;
import android.graphics.ForceDarkType;
import android.graphics.ForceDarkType.ForceDarkTypeDef;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Binder;
@@ -97,12 +93,9 @@ import androidx.test.filters.SmallTest;
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.window.flags.Flags;

import com.google.common.truth.Expect;

import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.AfterClass;
@@ -131,8 +124,6 @@ public class ViewRootImplTest {

    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    @Rule
    public final Expect mExpect = Expect.create();

    private ViewRootImpl mViewRootImpl;
    private View mView;
@@ -1516,34 +1507,49 @@ public class ViewRootImplTest {
    }

    @Test
    @RequiresFlagsEnabled(FLAG_FORCE_INVERT_COLOR)
    public void updateConfiguration_returnsExpectedForceDarkMode() {
        waitForSystemNightModeActivated(true);

        verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ true,
                UiModeManager.FORCE_INVERT_TYPE_DARK, ForceDarkType.FORCE_INVERT_COLOR_DARK);
        verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ false,
                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
        verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ true,
                UiModeManager.FORCE_INVERT_TYPE_DARK, ForceDarkType.FORCE_INVERT_COLOR_DARK);
        verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ false,
                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);

        waitForSystemNightModeActivated(false);

        verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ true,
                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
        verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ false,
                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
        verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ true,
                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
        verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ false,
                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
    public void forceInvertOffDarkThemeOff_forceDarkModeDisabled() {
        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
        ShellIdentityUtils.invokeWithShellPermissions(() -> {
            Settings.Secure.putInt(
                    sContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
                    /* value= */ 0
            );
            var uiModeManager = sContext.getSystemService(UiModeManager.class);
            uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
        });

        sInstrumentation.runOnMainSync(() ->
                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
        );

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

    @Test
    public void forceInvertOnDarkThemeOff_forceDarkModeEnabled() {
        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
        ShellIdentityUtils.invokeWithShellPermissions(() -> {
            Settings.Secure.putInt(
                    sContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
                    /* value= */ 1
            );
            var uiModeManager = sContext.getSystemService(UiModeManager.class);
            uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
        });

        sInstrumentation.runOnMainSync(() ->
                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
        );

        assertThat(mViewRootImpl.determineForceDarkType())
                .isEqualTo(ForceDarkType.FORCE_INVERT_COLOR_DARK);
    }

    @Test
    @EnableFlags(FLAG_FORCE_INVERT_COLOR)
    public void forceInvertOffForceDarkOff_forceDarkModeDisabled() {
        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
        ShellIdentityUtils.invokeWithShellPermissions(() -> {
            Settings.Secure.putInt(
                    sContext.getContentResolver(),
@@ -1556,14 +1562,15 @@ public class ViewRootImplTest {
        });

        sInstrumentation.runOnMainSync(() ->
                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
        );

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

    @Test
    @EnableFlags(FLAG_FORCE_INVERT_COLOR)
    public void forceInvertOffForceDarkOn_forceDarkModeEnabled() {
        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
        ShellIdentityUtils.invokeWithShellPermissions(() -> {
            Settings.Secure.putInt(
                    sContext.getContentResolver(),
@@ -1575,7 +1582,8 @@ public class ViewRootImplTest {
        });

        sInstrumentation.runOnMainSync(() ->
                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
        );

        assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.FORCE_DARK);
    }
@@ -1782,39 +1790,4 @@ public class ViewRootImplTest {
                    () -> view.getViewTreeObserver().removeOnDrawListener(listener));
        }
    }

    private void waitForSystemNightModeActivated(boolean active) {
        ShellIdentityUtils.invokeWithShellPermissions(() ->
                sInstrumentation.runOnMainSync(() -> {
                    var uiModeManager = sContext.getSystemService(UiModeManager.class);
                    uiModeManager.setNightModeActivated(active);
                }));
        sInstrumentation.waitForIdleSync();
    }

    private void verifyForceDarkType(boolean isAppInNightMode, boolean isForceInvertEnabled,
            @ForceInvertType int expectedForceInvertType,
            @ForceDarkTypeDef int expectedForceDarkType) {
        var uiModeManager = sContext.getSystemService(UiModeManager.class);
        ShellIdentityUtils.invokeWithShellPermissions(() -> {
            uiModeManager.setApplicationNightMode(
                    isAppInNightMode ? MODE_NIGHT_YES : MODE_NIGHT_NO);
            Settings.Secure.putInt(
                    sContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
                    isForceInvertEnabled ? 1 : 0);
        });

        sInstrumentation.runOnMainSync(() ->
                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
        try {
            TestUtils.waitUntil("Waiting for force invert state changed",
                    () -> (uiModeManager.getForceInvertState() == expectedForceInvertType));
        } catch (Exception e) {
            Log.e(TAG, "Unexpected error trying to apply force invert state. " + e);
            e.printStackTrace();
        }

        mExpect.that(mViewRootImpl.determineForceDarkType()).isEqualTo(expectedForceDarkType);
    }
}