Introducing the notion of DisplayBrightnessController, and making it use
DisplayBrightnessModeStrategies
DisplayBrightnessController is expected to handle all the changes that
happens to the brightness of the display. We have also introduced the
notion of DisplayBrightnessModeStrategies, and are making this
controller implement 2 different strategies - DozeBrightnessModeStrategy
and ScreenOffBrightnessModeStrategy. In the future, we will be
introducing more such strategies.
In future, DisplayBrightnessController will also be responsible for clamping the
brightness, and notifying the system about the changes
Test: atest ScreenOffBrightnessModeStrategyTest DisplayBrightnessControllerTest DozeBrightnessModeStrategyTest
Bug: 253226419
Change-Id: I6658ccf778274378194e158b4e9f19fb04dc1d3f
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 6b3e673..1c2c895 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -412,7 +412,7 @@
* the PowerManagerService to focus on the global power state and not
* have to micro-manage screen off animations, auto-brightness and other effects.
*/
- public static final class DisplayPowerRequest {
+ public static class DisplayPowerRequest {
// Policy: Turn screen off as if the user pressed the power button
// including playing a screen off animation if applicable.
public static final int POLICY_OFF = 0;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index c06101f..8f095950 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -68,6 +68,7 @@
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.DisplayBrightnessController;
import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
import com.android.server.display.utils.SensorUtils;
@@ -209,9 +210,6 @@
// True if auto-brightness should be used.
private boolean mUseSoftwareAutoBrightnessConfig;
- // True if should use light sensor to automatically determine doze screen brightness.
- private final boolean mAllowAutoBrightnessWhileDozingConfig;
-
// Whether or not the color fade on screen on / off is enabled.
private final boolean mColorFadeEnabled;
@@ -348,6 +346,8 @@
private final BrightnessEvent mLastBrightnessEvent;
private final BrightnessEvent mTempBrightnessEvent;
+ private final DisplayBrightnessController mDisplayBrightnessController;
+
// Keeps a record of brightness changes for dumpsys.
private RingBuffer<BrightnessEvent> mBrightnessEventRingBuffer;
@@ -499,9 +499,6 @@
mScreenBrightnessForVrRangeMinimum = clampAbsoluteBrightness(
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR));
- mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
- R.bool.config_allowAutoBrightnessWhileDozing);
-
loadBrightnessRampRates();
mSkipScreenOnBrightnessRamp = resources.getBoolean(
R.bool.config_skipScreenOnBrightnessRamp);
@@ -565,6 +562,8 @@
mBrightnessBucketsInDozeConfig = resources.getBoolean(
R.bool.config_displayBrightnessBucketsInDoze);
+ mDisplayBrightnessController =
+ new DisplayBrightnessController(context, null, mDisplayId);
mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
@@ -1113,7 +1112,6 @@
final int previousPolicy;
boolean mustInitialize = false;
int brightnessAdjustmentFlags = 0;
- mBrightnessReasonTemp.set(null);
mTempBrightnessEvent.reset();
synchronized (mLock) {
if (mStopped) {
@@ -1149,7 +1147,6 @@
// We might override this below based on other factors.
// Initialise brightness as invalid.
int state;
- float brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
boolean performScreenOffTransition = false;
switch (mPowerRequest.policy) {
case DisplayPowerRequest.POLICY_OFF:
@@ -1162,10 +1159,6 @@
} else {
state = Display.STATE_DOZE;
}
- if (!mAllowAutoBrightnessWhileDozingConfig) {
- brightnessState = mPowerRequest.dozeScreenBrightness;
- mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE);
- }
break;
case DisplayPowerRequest.POLICY_VR:
state = Display.STATE_VR;
@@ -1198,10 +1191,10 @@
animateScreenStateChange(state, performScreenOffTransition);
state = mPowerState.getScreenState();
- if (state == Display.STATE_OFF) {
- brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
- mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
- }
+ DisplayBrightnessState displayBrightnessState = mDisplayBrightnessController
+ .updateBrightness(mPowerRequest, state);
+ float brightnessState = displayBrightnessState.getBrightness();
+ mBrightnessReasonTemp.set(displayBrightnessState.getBrightnessReason());
// Always use the VR brightness when in the VR state.
if (state == Display.STATE_VR) {
@@ -1219,7 +1212,8 @@
}
final boolean autoBrightnessEnabledInDoze =
- mAllowAutoBrightnessWhileDozingConfig && Display.isDozeState(state);
+ mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig()
+ && Display.isDozeState(state);
final boolean autoBrightnessEnabled = mPowerRequest.useAutoBrightness
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& Float.isNaN(brightnessState)
@@ -2282,8 +2276,6 @@
pw.println(" mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum);
pw.println(" mScreenBrightnessForVrDefault=" + mScreenBrightnessForVrDefault);
pw.println(" mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
- pw.println(" mAllowAutoBrightnessWhileDozingConfig="
- + mAllowAutoBrightnessWhileDozingConfig);
pw.println(" mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp);
pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig);
pw.println(" mColorFadeEnabled=" + mColorFadeEnabled);
@@ -2383,6 +2375,11 @@
mWakelockController.dumpLocal(pw);
}
+ pw.println();
+ if (mDisplayBrightnessController != null) {
+ mDisplayBrightnessController.dump(pw);
+ }
+
if (mDisplayPowerProximityStateController != null) {
mDisplayPowerProximityStateController.dumpLocal(pw);
}
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
new file mode 100644
index 0000000..fe4c101
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness;
+
+import android.content.Context;
+import android.hardware.display.DisplayManagerInternal;
+import android.util.IndentingPrintWriter;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
+
+import java.io.PrintWriter;
+
+/**
+ * Deploys different DozeBrightnessStrategy to choose the current brightness for a specified
+ * display. Applies the chosen brightness.
+ */
+public final class DisplayBrightnessController {
+ private final int mDisplayId;
+ // Selects an appropriate strategy based on the request provided by the clients.
+ private DisplayBrightnessStrategySelector mDisplayBrightnessStrategySelector;
+
+ /**
+ * The constructor of DisplayBrightnessController.
+ */
+ public DisplayBrightnessController(Context context, Injector injector, int displayId) {
+ if (injector == null) {
+ injector = new Injector();
+ }
+ mDisplayId = displayId;
+ mDisplayBrightnessStrategySelector = injector.getDisplayBrightnessStrategySelector(context,
+ displayId);
+ }
+
+ /**
+ * Updates the display brightness. This delegates the responsibility of selecting an appropriate
+ * strategy to DisplayBrightnessStrategySelector, which is then applied to evaluate the
+ * DisplayBrightnessState. In the future,
+ * 1. This will account for clamping the brightness if needed.
+ * 2. This will notify the system about the updated brightness
+ *
+ * @param displayPowerRequest The request to update the brightness
+ * @param targetDisplayState The target display state of the system
+ */
+ public DisplayBrightnessState updateBrightness(
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
+ int targetDisplayState) {
+ DisplayBrightnessStrategy displayBrightnessStrategy =
+ mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest,
+ targetDisplayState);
+ return displayBrightnessStrategy.updateBrightness(displayPowerRequest);
+ }
+
+ /**
+ * Returns a boolean flag indicating if the light sensor is to be used to decide the screen
+ * brightness when dozing
+ */
+ public boolean isAllowAutoBrightnessWhileDozingConfig() {
+ return mDisplayBrightnessStrategySelector.isAllowAutoBrightnessWhileDozingConfig();
+ }
+
+ /**
+ * Used to dump the state.
+ *
+ * @param writer The PrintWriter used to dump the state.
+ */
+ public void dump(PrintWriter writer) {
+ writer.println();
+ writer.println("DisplayBrightnessController:");
+ IndentingPrintWriter ipw = new IndentingPrintWriter(writer, " ");
+ mDisplayBrightnessStrategySelector.dump(ipw);
+ }
+
+ @VisibleForTesting
+ static class Injector {
+ DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(Context context,
+ int displayId) {
+ return new DisplayBrightnessStrategySelector(context, /* injector= */ null, displayId);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
new file mode 100644
index 0000000..88707f0
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.display.DisplayManagerInternal;
+import android.util.Slog;
+import android.view.Display;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
+import com.android.server.display.brightness.strategy.DozeBrightnessStrategy;
+import com.android.server.display.brightness.strategy.InvalidBrightnessStrategy;
+import com.android.server.display.brightness.strategy.ScreenOffBrightnessStrategy;
+
+import java.io.PrintWriter;
+
+/**
+ * This maintains the logic needed to decide the eligible display brightness strategy.
+ */
+public class DisplayBrightnessStrategySelector {
+ private static final String TAG = "DisplayBrightnessStrategySelector";
+ // True if light sensor is to be used to automatically determine doze screen brightness.
+ private final boolean mAllowAutoBrightnessWhileDozingConfig;
+
+ // The brightness strategy used to manage the brightness state when the display is dozing.
+ private final DozeBrightnessStrategy mDozeBrightnessStrategy;
+ // The brightness strategy used to manage the brightness state when the display is in
+ // screen off state.
+ private final ScreenOffBrightnessStrategy mScreenOffBrightnessStrategy;
+ // The brightness strategy used to manage the brightness state when the request state is
+ // invalid.
+ private final InvalidBrightnessStrategy mInvalidBrightnessStrategy;
+
+ // We take note of the old brightness strategy so that we can know when the strategy changes.
+ private String mOldBrightnessStrategyName;
+
+ private final int mDisplayId;
+
+ /**
+ * The constructor of DozeBrightnessStrategy.
+ */
+ public DisplayBrightnessStrategySelector(Context context, Injector injector, int displayId) {
+ if (injector == null) {
+ injector = new Injector();
+ }
+ mDisplayId = displayId;
+ mDozeBrightnessStrategy = injector.getDozeBrightnessStrategy();
+ mScreenOffBrightnessStrategy = injector.getScreenOffBrightnessStrategy();
+ mInvalidBrightnessStrategy = injector.getInvalidBrightnessStrategy();
+ mAllowAutoBrightnessWhileDozingConfig = context.getResources().getBoolean(
+ R.bool.config_allowAutoBrightnessWhileDozing);
+ mOldBrightnessStrategyName = mInvalidBrightnessStrategy.getName();
+ }
+
+ /**
+ * Selects the appropriate DisplayBrightnessStrategy based on the request and the display state
+ * to which the display is transitioning
+ */
+ @NonNull
+ public DisplayBrightnessStrategy selectStrategy(
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
+ int targetDisplayState) {
+ DisplayBrightnessStrategy displayBrightnessStrategy = mInvalidBrightnessStrategy;
+ if (targetDisplayState == Display.STATE_OFF) {
+ displayBrightnessStrategy = mScreenOffBrightnessStrategy;
+ } else if (shouldUseDozeBrightnessStrategy(displayPowerRequest)) {
+ displayBrightnessStrategy = mDozeBrightnessStrategy;
+ }
+
+ if (!mOldBrightnessStrategyName.equals(displayBrightnessStrategy.getName())) {
+ Slog.i(TAG,
+ "Changing the DisplayBrightnessStrategy from " + mOldBrightnessStrategyName
+ + " to" + displayBrightnessStrategy.getName() + " for display "
+ + mDisplayId);
+ mOldBrightnessStrategyName = displayBrightnessStrategy.getName();
+ }
+ return displayBrightnessStrategy;
+ }
+
+ /**
+ * Returns a boolean flag indicating if the light sensor is to be used to decide the screen
+ * brightness when dozing
+ */
+ public boolean isAllowAutoBrightnessWhileDozingConfig() {
+ return mAllowAutoBrightnessWhileDozingConfig;
+ }
+
+ /**
+ * Dumps the state of this class.
+ */
+ public void dump(PrintWriter writer) {
+ writer.println();
+ writer.println("DisplayBrightnessStrategySelector:");
+ writer.println(
+ " mAllowAutoBrightnessWhileDozingConfig=" + mAllowAutoBrightnessWhileDozingConfig);
+ }
+
+ /**
+ * Validates if the conditions are met to qualify for the DozeBrightnessStrategy.
+ */
+ private boolean shouldUseDozeBrightnessStrategy(
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ // We are not checking the targetDisplayState, but rather relying on the policy because
+ // a user can define a different display state(displayPowerRequest.dozeScreenState) too
+ // in the request with the Doze policy
+ if (displayPowerRequest.policy == DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE) {
+ if (!mAllowAutoBrightnessWhileDozingConfig) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @VisibleForTesting
+ static class Injector {
+ ScreenOffBrightnessStrategy getScreenOffBrightnessStrategy() {
+ return new ScreenOffBrightnessStrategy();
+ }
+
+ DozeBrightnessStrategy getDozeBrightnessStrategy() {
+ return new DozeBrightnessStrategy();
+ }
+
+ InvalidBrightnessStrategy getInvalidBrightnessStrategy() {
+ return new InvalidBrightnessStrategy();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessModeStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessModeStrategy.java
deleted file mode 100644
index 3be5933..0000000
--- a/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessModeStrategy.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.display.brightness.strategy;
-
-import android.hardware.display.DisplayManagerInternal;
-
-import com.android.server.display.DisplayBrightnessState;
-
-import java.io.PrintWriter;
-
-/**
- * An interface to define the general skeleton of how a BrightnessModeStrategy should look like
- * This is responsible for deciding the DisplayBrightnessState that the display should change to,
- * not taking into account clamping that might be needed
- */
-public interface DisplayBrightnessModeStrategy {
- /**
- * Decides the DisplayBrightnessState that the system should change to.
- *
- * @param displayPowerRequest The request to evaluate the updated brightness
- * @param displayState The target displayState to which the system should
- * change to after processing the request
- * @param displayBrightnessStateBuilder The DisplayBrightnessStateBuilder, consisting of
- * DisplayBrightnessState that have been constructed so far
- */
- DisplayBrightnessState.Builder updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest, int displayState,
- DisplayBrightnessState.Builder displayBrightnessStateBuilder);
-
- /**
- * Used to dump the state.
- *
- * @param writer The PrintWriter used to dump the state.
- */
- void dump(PrintWriter writer);
-}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
new file mode 100644
index 0000000..27d04fd
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+import android.annotation.NonNull;
+import android.hardware.display.DisplayManagerInternal;
+
+import com.android.server.display.DisplayBrightnessState;
+
+/**
+ * Decides the DisplayBrighntessState that the display should change to based on strategy-specific
+ * logic within each implementation. Clamping should be done outside of DisplayBrightnessStrategy if
+ * not an integral part of the strategy.
+ */
+public interface DisplayBrightnessStrategy {
+ /**
+ * Decides the DisplayBrightnessState that the system should change to.
+ *
+ * @param displayPowerRequest The request to evaluate the updated brightness
+ */
+ DisplayBrightnessState updateBrightness(
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest);
+
+ /**
+ * Returns the name of the Strategy
+ */
+ @NonNull
+ String getName();
+}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
new file mode 100644
index 0000000..c8b2c83
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+import android.hardware.display.DisplayManagerInternal;
+
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.BrightnessReason;
+
+/**
+ * Manages the brightness of the display when the system is in the doze state.
+ */
+public class DozeBrightnessStrategy implements DisplayBrightnessStrategy {
+
+ @Override
+ public DisplayBrightnessState updateBrightness(
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ // Todo(brup): Introduce a validator class and add validations before setting the brightness
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.setReason(BrightnessReason.REASON_DOZE);
+ return new DisplayBrightnessState.Builder()
+ .setBrightness(displayPowerRequest.dozeScreenBrightness)
+ .setSdrBrightness(displayPowerRequest.dozeScreenBrightness)
+ .setBrightnessReason(brightnessReason)
+ .build();
+ }
+
+ @Override
+ public String getName() {
+ return "DozeBrightnessStrategy";
+ }
+
+}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
new file mode 100644
index 0000000..f6ddf4f
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+import android.hardware.display.DisplayManagerInternal;
+import android.os.PowerManager;
+
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.BrightnessReason;
+
+/**
+ * Manages the brightness of the display when the system is in the invalid state.
+ */
+public class InvalidBrightnessStrategy implements DisplayBrightnessStrategy {
+ @Override
+ public DisplayBrightnessState updateBrightness(
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.set(null);
+ return new DisplayBrightnessState.Builder()
+ .setBrightness(PowerManager.BRIGHTNESS_INVALID_FLOAT)
+ .setSdrBrightness(PowerManager.BRIGHTNESS_INVALID_FLOAT)
+ .setBrightnessReason(brightnessReason)
+ .build();
+ }
+
+ @Override
+ public String getName() {
+ return "InvalidBrightnessStrategy";
+ }
+}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
new file mode 100644
index 0000000..4138513
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+import android.hardware.display.DisplayManagerInternal;
+import android.os.PowerManager;
+
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.BrightnessReason;
+
+/**
+ * Manages the brightness of the display when the system is in the ScreenOff state.
+ */
+public class ScreenOffBrightnessStrategy implements DisplayBrightnessStrategy {
+ @Override
+ public DisplayBrightnessState updateBrightness(
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ // Todo(brup): Introduce a validator class and add validations before setting the brightness
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.setReason(BrightnessReason.REASON_SCREEN_OFF);
+ return new DisplayBrightnessState.Builder()
+ .setBrightness(PowerManager.BRIGHTNESS_OFF_FLOAT)
+ .setSdrBrightness(PowerManager.BRIGHTNESS_OFF_FLOAT)
+ .setBrightnessReason(brightnessReason)
+ .build();
+ }
+
+ @Override
+ public String getName() {
+ return "ScreenOffBrightnessStrategy";
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
new file mode 100644
index 0000000..cbeaf7b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.view.Display;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class DisplayBrightnessControllerTest {
+ private static final int DISPLAY_ID = 1;
+
+ @Mock
+ private DisplayBrightnessStrategySelector mDisplayBrightnessStrategySelector;
+ @Mock
+ private Context mContext;
+
+ private DisplayBrightnessController mDisplayBrightnessController;
+
+ @Before
+ public void before() {
+ MockitoAnnotations.initMocks(this);
+ DisplayBrightnessController.Injector injector = new DisplayBrightnessController.Injector() {
+ @Override
+ DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(
+ Context context, int displayId) {
+ return mDisplayBrightnessStrategySelector;
+ }
+ };
+ mDisplayBrightnessController = new DisplayBrightnessController(mContext, injector,
+ DISPLAY_ID);
+ }
+
+ @Test
+ public void updateBrightnessWorksAsExpected() {
+ DisplayPowerRequest displayPowerRequest = mock(DisplayPowerRequest.class);
+ DisplayBrightnessStrategy displayBrightnessStrategy = mock(DisplayBrightnessStrategy.class);
+ int targetDisplayState = Display.STATE_DOZE;
+ when(mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest,
+ targetDisplayState)).thenReturn(displayBrightnessStrategy);
+ mDisplayBrightnessController.updateBrightness(displayPowerRequest, targetDisplayState);
+ verify(displayBrightnessStrategy).updateBrightness(displayPowerRequest);
+ }
+
+ @Test
+ public void isAllowAutoBrightnessWhileDozingConfigDelegatesToDozeBrightnessStrategy() {
+ mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig();
+ verify(mDisplayBrightnessStrategySelector).isAllowAutoBrightnessWhileDozingConfig();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
new file mode 100644
index 0000000..ba31e8c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.display.DisplayManagerInternal;
+import android.view.Display;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.R;
+import com.android.server.display.brightness.strategy.DozeBrightnessStrategy;
+import com.android.server.display.brightness.strategy.InvalidBrightnessStrategy;
+import com.android.server.display.brightness.strategy.ScreenOffBrightnessStrategy;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class DisplayBrightnessStrategySelectorTest {
+ private static final boolean DISALLOW_AUTO_BRIGHTNESS_WHILE_DOZING = false;
+ private static final int DISPLAY_ID = 1;
+
+ @Mock
+ private ScreenOffBrightnessStrategy mScreenOffBrightnessModeStrategy;
+ @Mock
+ private DozeBrightnessStrategy mDozeBrightnessModeStrategy;
+ @Mock
+ private InvalidBrightnessStrategy mInvalidBrightnessStrategy;
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+
+ private DisplayBrightnessStrategySelector mDisplayBrightnessStrategySelector;
+
+ @Before
+ public void before() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getResources()).thenReturn(mResources);
+ DisplayBrightnessStrategySelector.Injector injector =
+ new DisplayBrightnessStrategySelector.Injector() {
+ @Override
+ ScreenOffBrightnessStrategy getScreenOffBrightnessStrategy() {
+ return mScreenOffBrightnessModeStrategy;
+ }
+
+ @Override
+ DozeBrightnessStrategy getDozeBrightnessStrategy() {
+ return mDozeBrightnessModeStrategy;
+ }
+
+ @Override
+ InvalidBrightnessStrategy getInvalidBrightnessStrategy() {
+ return mInvalidBrightnessStrategy;
+ }
+ };
+ mDisplayBrightnessStrategySelector = new DisplayBrightnessStrategySelector(mContext,
+ injector, DISPLAY_ID);
+
+ }
+
+ @Test
+ public void selectStrategySelectsDozeStrategyWhenValid() {
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
+ DisplayManagerInternal.DisplayPowerRequest.class);
+ displayPowerRequest.policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
+ when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn(
+ DISALLOW_AUTO_BRIGHTNESS_WHILE_DOZING);
+ assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest,
+ Display.STATE_DOZE), mDozeBrightnessModeStrategy);
+ }
+
+ @Test
+ public void selectStrategySelectsScreenOffStrategyWhenValid() {
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
+ DisplayManagerInternal.DisplayPowerRequest.class);
+ assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest,
+ Display.STATE_OFF), mScreenOffBrightnessModeStrategy);
+ }
+
+ @Test
+ public void selectStrategySelectsInvalidStrategyWhenNoStrategyIsValid() {
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
+ DisplayManagerInternal.DisplayPowerRequest.class);
+ assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest,
+ Display.STATE_ON), mInvalidBrightnessStrategy);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
new file mode 100644
index 0000000..29652ff
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+import static org.junit.Assert.assertEquals;
+
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.BrightnessReason;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DozeBrightnessStrategyTest {
+ private DozeBrightnessStrategy mDozeBrightnessModeStrategy;
+
+ @Before
+ public void before() {
+ mDozeBrightnessModeStrategy = new DozeBrightnessStrategy();
+ }
+
+ @Test
+ public void updateBrightnessWorksAsExpectedWhenScreenDozeStateIsRequested() {
+ DisplayPowerRequest displayPowerRequest = new DisplayPowerRequest();
+ float dozeScreenBrightness = 0.2f;
+ displayPowerRequest.dozeScreenBrightness = dozeScreenBrightness;
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.setReason(BrightnessReason.REASON_DOZE);
+ DisplayBrightnessState expectedDisplayBrightnessState =
+ new DisplayBrightnessState.Builder()
+ .setBrightness(dozeScreenBrightness)
+ .setBrightnessReason(brightnessReason)
+ .setSdrBrightness(dozeScreenBrightness)
+ .build();
+ DisplayBrightnessState updatedDisplayBrightnessState =
+ mDozeBrightnessModeStrategy.updateBrightness(displayPowerRequest);
+ assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
new file mode 100644
index 0000000..0505475
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.brightness.strategy;
+
+import static org.junit.Assert.assertEquals;
+
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.os.PowerManager;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.BrightnessReason;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class ScreenOffBrightnessStrategyTest {
+
+ private ScreenOffBrightnessStrategy mScreenOffBrightnessModeStrategy;
+
+ @Before
+ public void before() {
+ mScreenOffBrightnessModeStrategy = new ScreenOffBrightnessStrategy();
+ }
+
+ @Test
+ public void updateBrightnessWorksAsExpectedWhenScreenOffDisplayState() {
+ DisplayPowerRequest displayPowerRequest = new DisplayPowerRequest();
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.setReason(BrightnessReason.REASON_SCREEN_OFF);
+ DisplayBrightnessState expectedDisplayBrightnessState =
+ new DisplayBrightnessState.Builder()
+ .setBrightness(PowerManager.BRIGHTNESS_OFF_FLOAT)
+ .setSdrBrightness(PowerManager.BRIGHTNESS_OFF_FLOAT)
+ .setBrightnessReason(brightnessReason)
+ .build();
+ DisplayBrightnessState updatedDisplayBrightnessState =
+ mScreenOffBrightnessModeStrategy.updateBrightness(displayPowerRequest);
+ assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
+ }
+}