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

Commit a2d20b44 authored by John Reck's avatar John Reck
Browse files

Add theme & View API to control force-dark

Bug: 102591313
Test: CTS android.uirendering.cts.testclasses.ForceDarkTests

Change-Id: I6ba129681aed8e2f3f1b1ac60d458bb5f5393e9b
parent c63d1cc4
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -283,7 +283,6 @@ package android {
    field public static final int allowBackup = 16843392; // 0x1010280
    field public static final int allowClearUserData = 16842757; // 0x1010005
    field public static final int allowEmbedded = 16843765; // 0x10103f5
    field public static final int allowForceDark = 16844172; // 0x101058c
    field public static final int allowParallelSyncs = 16843570; // 0x1010332
    field public static final int allowSingleTap = 16843353; // 0x1010259
    field public static final int allowTaskReparenting = 16843268; // 0x1010204
@@ -638,6 +637,7 @@ package android {
    field public static final int fontVariationSettings = 16844144; // 0x1010570
    field public static final int fontWeight = 16844083; // 0x1010533
    field public static final int footerDividersEnabled = 16843311; // 0x101022f
    field public static final int forceDarkAllowed = 16844172; // 0x101058c
    field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
    field public static final int foreground = 16843017; // 0x1010109
    field public static final int foregroundGravity = 16843264; // 0x1010200
@@ -48508,6 +48508,7 @@ package android.view {
    method public final boolean isFocusableInTouchMode();
    method public boolean isFocused();
    method public final boolean isFocusedByDefault();
    method public boolean isForceDarkAllowed();
    method public boolean isHapticFeedbackEnabled();
    method public boolean isHardwareAccelerated();
    method public boolean isHorizontalFadingEdgeEnabled();
@@ -48694,6 +48695,7 @@ package android.view {
    method public void setFocusable(int);
    method public void setFocusableInTouchMode(boolean);
    method public void setFocusedByDefault(boolean);
    method public void setForceDarkAllowed(boolean);
    method public void setForeground(android.graphics.drawable.Drawable);
    method public void setForegroundGravity(int);
    method public void setForegroundTintList(android.content.res.ColorStateList);
+1 −1
Original line number Diff line number Diff line
@@ -897,7 +897,7 @@ public class Surface implements Parcelable {
        HwuiContext(boolean isWideColorGamut) {
            mRenderNode = RenderNode.create("HwuiCanvas", null);
            mRenderNode.setClipToBounds(false);
            mRenderNode.setAllowForceDark(false);
            mRenderNode.setForceDarkAllowed(false);
            mIsWideColorGamut = isWideColorGamut;
            mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject,
                    isWideColorGamut);
+9 −9
Original line number Diff line number Diff line
@@ -5542,6 +5542,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                    break;
                case com.android.internal.R.styleable.View_accessibilityHeading:
                    setAccessibilityHeading(a.getBoolean(attr, false));
                    break;
                case R.styleable.View_forceDarkAllowed:
                    mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
                    break;
            }
        }
@@ -15286,11 +15290,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
     *
     * @param allow Whether or not to allow force dark.
     *
     * @hide
     */
    public void setAllowForceDark(boolean allow) {
        if (mRenderNode.setAllowForceDark(allow)) {
    public void setForceDarkAllowed(boolean allow) {
        if (mRenderNode.setForceDarkAllowed(allow)) {
            // Currently toggling force-dark requires a new display list push to apply
            // TODO: Make it not clobber the display list so this is just a damageSelf() instead
            invalidate();
@@ -15298,15 +15300,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    }
    /**
     * See {@link #setAllowForceDark(boolean)}
     * See {@link #setForceDarkAllowed(boolean)}
     *
     * @return true if force dark is allowed (default), false if it is disabled
     *
     * @hide
     */
    @ViewDebug.ExportedProperty(category = "drawing")
    public boolean getAllowForceDark() {
        return mRenderNode.getAllowForceDark();
    public boolean isForceDarkAllowed() {
        return mRenderNode.isForceDarkAllowed();
    }
    /**
+13 −7
Original line number Diff line number Diff line
@@ -1096,15 +1096,21 @@ public final class ViewRootImpl implements ViewParent,
    private void updateForceDarkMode() {
        if (mAttachInfo.mThreadedRenderer == null) return;

        boolean nightMode = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
        boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES;

        // Allow debug.hwui.force_dark to override the target SDK check
        if (useAutoDark && !SystemProperties.getBoolean("debug.hwui.force_dark", false)) {
            useAutoDark = mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
        }

        if (useAutoDark) {
            TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
        boolean isLightTheme = a.getBoolean(R.styleable.Theme_isLightTheme, false);
            useAutoDark = a.getBoolean(R.styleable.Theme_isLightTheme, true)
                    && a.getBoolean(R.styleable.Theme_forceDarkAllowed, true);
            a.recycle();
        }

        boolean changed = mAttachInfo.mThreadedRenderer.setForceDark(nightMode);
        changed |= mAttachInfo.mThreadedRenderer.getRootNode().setAllowForceDark(isLightTheme);

        if (changed) {
        if (mAttachInfo.mThreadedRenderer.setForceDark(useAutoDark)) {
            // TODO: Don't require regenerating all display lists to apply this setting
            invalidateWorld(mView);
        }
+16 −2
Original line number Diff line number Diff line
@@ -1141,6 +1141,15 @@

        <!-- Alpha value of the spot shadow projected by elevated views, between 0 and 1. -->
        <attr name="spotShadowAlpha" format="float" />

        <!-- <p>Whether or not the force dark feature is allowed to be applied to this theme.
             <p>Setting this to false will disable the auto-dark feature on everything this
             theme is applied to along with anything drawn by any children of views using
             this theme.
             <p>Setting this to true will allow this view to be automatically made dark, however
             a value of 'true' will not override any 'false' value in its parent chain nor will
             it prevent any 'false' in any of its children. -->
        <attr name="forceDarkAllowed" format="boolean" />
    </declare-styleable>

    <!-- **************************************************************** -->
@@ -3116,8 +3125,13 @@
             {@link android.R.attr#ambientShadowAlpha} theme attribute. -->
        <attr name="outlineAmbientShadowColor" format="color" />

        <!-- Whether to allow the rendering system to force this View to render as light-on-dark. -->
        <attr name="allowForceDark" format="boolean" />
        <!-- <p>Whether or not the force dark feature is allowed to be applied to this View.
             <p>Setting this to false will disable the auto-dark feature on this View draws
             including any descendants.
             <p>Setting this to true will allow this view to be automatically made dark, however
             a value of 'true' will not override any 'false' value in its parent chain nor will
             it prevent any 'false' in any of its children. -->
        <attr name="forceDarkAllowed" format="boolean" />
    </declare-styleable>

    <!-- Attributes that can be assigned to a tag for a particular View. -->
Loading