diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index fcea0c3f890a6..982e5c2a69249 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -843,6 +843,32 @@ public class RenderNode { return nGetDebugSize(mNativeRenderNode); } + /** + * Sets whether or not to allow force dark to apply to this RenderNode. + * + * Setting this to false will disable the auto-dark feature on everything this RenderNode + * draws, including any descendants. + * + * Setting this to true will allow this RenderNode 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. + * + * @param allow Whether or not to allow force dark. + * @return true If the value has changed, false otherwise. + */ + public boolean setAllowForceDark(boolean allow) { + return nSetAllowForceDark(mNativeRenderNode, allow); + } + + /** + * See {@link #setAllowForceDark(boolean)} + * + * @return true if force dark is allowed (default), false if it is disabled + */ + public boolean getAllowForceDark() { + return nGetAllowForceDark(mNativeRenderNode); + } + /////////////////////////////////////////////////////////////////////////// // Animations /////////////////////////////////////////////////////////////////////////// @@ -1043,4 +1069,8 @@ public class RenderNode { private static native int nGetWidth(long renderNode); @CriticalNative private static native int nGetHeight(long renderNode); + @CriticalNative + private static native boolean nSetAllowForceDark(long renderNode, boolean allowForceDark); + @CriticalNative + private static native boolean nGetAllowForceDark(long renderNode); } diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 427f570b1294a..6fb1bbabddc2a 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -895,6 +895,7 @@ public class Surface implements Parcelable { HwuiContext(boolean isWideColorGamut) { mRenderNode = RenderNode.create("HwuiCanvas", null); mRenderNode.setClipToBounds(false); + mRenderNode.setAllowForceDark(false); mIsWideColorGamut = isWideColorGamut; mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject, isWideColorGamut); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 19e3f7f623cb9..f4be9f2d79490 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -15245,6 +15245,40 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1; } + /** + * Sets whether or not to allow force dark to apply to this view. + * + * Setting this to false will disable the auto-dark feature on everything this view + * draws, including any descendants. + * + * 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. + * + * @param allow Whether or not to allow force dark. + * + * @hide + */ + public void setAllowForceDark(boolean allow) { + if (mRenderNode.setAllowForceDark(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(); + } + } + + /** + * See {@link #setAllowForceDark(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(); + } + /** * Top position of this view relative to its parent. * diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 46b19bdf660ff..0701f3e0d2ed3 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -444,6 +444,14 @@ static jint android_view_RenderNode_getHeight(jlong renderNodePtr) { return reinterpret_cast(renderNodePtr)->stagingProperties().getHeight(); } +static jboolean android_view_RenderNode_setAllowForceDark(jlong renderNodePtr, jboolean allow) { + return SET_AND_DIRTY(setAllowForceDark, allow, RenderNode::GENERIC); +} + +static jboolean android_view_RenderNode_getAllowForceDark(jlong renderNodePtr) { + return reinterpret_cast(renderNodePtr)->stagingProperties().getAllowForceDark(); +} + // ---------------------------------------------------------------------------- // RenderProperties - Animations // ---------------------------------------------------------------------------- @@ -664,6 +672,8 @@ static const JNINativeMethod gMethods[] = { { "nGetPivotY", "(J)F", (void*) android_view_RenderNode_getPivotY }, { "nGetWidth", "(J)I", (void*) android_view_RenderNode_getWidth }, { "nGetHeight", "(J)I", (void*) android_view_RenderNode_getHeight }, + { "nSetAllowForceDark", "(JZ)Z", (void*) android_view_RenderNode_setAllowForceDark }, + { "nGetAllowForceDark", "(J)Z", (void*) android_view_RenderNode_getAllowForceDark }, }; int register_android_view_RenderNode(JNIEnv* env) { diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index cea6c1c5d1256..9cbbf4ef366fc 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -1253,6 +1253,7 @@ public final class Bitmap implements Parcelable { final RenderNode node = RenderNode.create("BitmapTemporary", null); node.setLeftTopRightBottom(0, 0, width, height); node.setClipToBounds(false); + node.setAllowForceDark(false); final DisplayListCanvas canvas = node.start(width, height); if (source.getWidth() != width || source.getHeight() != height) { canvas.scale(width / (float) source.getWidth(), diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 26e5cea2452aa..9cfaa6a881aeb 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -112,7 +112,9 @@ void RenderNode::prepareTree(TreeInfo& info) { LOG_ALWAYS_FATAL_IF(!info.damageAccumulator, "DamageAccumulator missing"); MarkAndSweepRemoved observer(&info); + const int before = info.disableForceDark; prepareTreeImpl(observer, info, false); + LOG_ALWAYS_FATAL_IF(before != info.disableForceDark, "Mis-matched force dark"); } void RenderNode::addAnimator(const sp& animator) { @@ -195,6 +197,11 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu if (info.mode == TreeInfo::MODE_FULL) { pushStagingPropertiesChanges(info); } + + if (!mProperties.getAllowForceDark()) { + info.disableForceDark++; + } + uint32_t animatorDirtyMask = 0; if (CC_LIKELY(info.runAnimations)) { animatorDirtyMask = mAnimatorManager.animate(info); @@ -232,6 +239,9 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu } pushLayerUpdate(info); + if (!mProperties.getAllowForceDark()) { + info.disableForceDark--; + } info.damageAccumulator->popTransform(); } @@ -273,7 +283,7 @@ void RenderNode::syncDisplayList(TreeObserver& observer, TreeInfo* info) { if (mDisplayList) { mDisplayList->syncContents(); - if (CC_UNLIKELY(Properties::forceDarkMode)) { + if (CC_UNLIKELY(info && !info->disableForceDark)) { auto usage = usageHint(); if (mDisplayList->hasText()) { usage = UsageHint::Foreground; diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index 7966845ff814d..04379ae68a0dc 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -535,6 +535,14 @@ public: return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType; } + bool setAllowForceDark(bool allow) { + return RP_SET(mPrimitiveFields.mAllowForceDark, allow); + } + + bool getAllowForceDark() const { + return mPrimitiveFields.mAllowForceDark; + } + private: // Rendering properties struct PrimitiveFields { @@ -554,6 +562,7 @@ private: bool mMatrixOrPivotDirty = false; bool mProjectBackwards = false; bool mProjectionReceiver = false; + bool mAllowForceDark = true; Rect mClipBounds; Outline mOutline; RevealClip mRevealClip; diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h index f2766d6a5b6e2..caa5762d174ae 100644 --- a/libs/hwui/TreeInfo.h +++ b/libs/hwui/TreeInfo.h @@ -17,6 +17,7 @@ #pragma once #include "utils/Macros.h" +#include "Properties.h" #include @@ -93,6 +94,8 @@ public: bool updateWindowPositions = false; + int disableForceDark = Properties::forceDarkMode ? 0 : 1; + struct Out { bool hasFunctors = false; // This is only updated if evaluateAnimations is true diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index 044cc5cab20cd..48181bc629a86 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -187,9 +187,11 @@ public class ScreenDecorations extends SystemUI implements Tunable { mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE); mOverlay.setAlpha(0); + mOverlay.setAllowForceDark(false); mBottomOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE); mBottomOverlay.setAlpha(0); + mBottomOverlay.setAllowForceDark(false); updateViews();