summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java18
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java29
-rw-r--r--services/core/java/com/android/server/display/feature/DisplayManagerFlags.java10
-rw-r--r--services/core/java/com/android/server/display/feature/display_flags.aconfig10
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java7
5 files changed, 71 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
index 65c9f3556fad..26bc17972bd7 100644
--- a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
+++ b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
@@ -21,13 +21,21 @@ import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIG
import android.annotation.Nullable;
import android.hardware.display.DisplayManagerInternal;
import android.os.Trace;
+import android.util.Slog;
import android.view.Display;
+import com.android.server.display.utils.DebugUtils;
+
/**
* An implementation of the offload session that keeps track of whether the session is active.
* An offload session is used to control the display's brightness using the offload chip.
*/
public class DisplayOffloadSessionImpl implements DisplayManagerInternal.DisplayOffloadSession {
+ private static final String TAG = "DisplayOffloadSessionImpl";
+
+ // To enable these logs, run:
+ // 'adb shell setprop persist.log.tag.DisplayOffloadSessionImpl DEBUG && adb reboot'
+ private static final boolean DEBUG = DebugUtils.isDebuggable(TAG);
@Nullable
private final DisplayManagerInternal.DisplayOffloader mDisplayOffloader;
@@ -91,9 +99,14 @@ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.Display
if (mDisplayOffloader == null || mIsActive) {
return false;
}
+
Trace.traceBegin(Trace.TRACE_TAG_POWER, "DisplayOffloader#startOffload");
try {
- return mIsActive = mDisplayOffloader.startOffload();
+ mIsActive = mDisplayOffloader.startOffload();
+ if (DEBUG) {
+ Slog.d(TAG, "startOffload = " + mIsActive);
+ }
+ return mIsActive;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
@@ -110,6 +123,9 @@ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.Display
try {
mDisplayOffloader.stopOffload();
mIsActive = false;
+ if (DEBUG) {
+ Slog.i(TAG, "stopOffload");
+ }
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 0fcdf198eece..5ad20e4daeaf 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -791,10 +791,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
@Override
public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) {
+ Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState));
mHandler.postAtTime(() -> {
if (mDisplayOffloadSession == null
|| !(DisplayOffloadSession.isSupportedOffloadState(displayState)
- || displayState == Display.STATE_UNKNOWN)) {
+ || displayState == Display.STATE_UNKNOWN)) {
return;
}
mDisplayStateController.overrideDozeScreenState(displayState, reason);
@@ -1278,7 +1279,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private void updatePowerStateInternal() {
// Update the power state request.
- final boolean mustNotify;
+ boolean mustNotify = false;
final int previousPolicy;
boolean mustInitialize = false;
mBrightnessReasonTemp.set(null);
@@ -1326,6 +1327,30 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN);
}
+ if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) {
+ // Sometimes, a display-state change can come without an associated PowerRequest,
+ // as with DisplayOffload. For those cases, we have to make sure to also mark the
+ // display as "not ready" so that we can inform power-manager when the state-change is
+ // complete.
+ if (mPowerState.getScreenState() != state) {
+ final boolean wasReady;
+ synchronized (mLock) {
+ wasReady = mDisplayReadyLocked;
+ mDisplayReadyLocked = false;
+ mustNotify = true;
+ }
+
+ if (wasReady) {
+ // If we went from ready to not-ready from the state-change (instead of a
+ // PowerRequest) there's a good chance that nothing is keeping PowerManager
+ // from suspending. Grab the unfinished business suspend blocker to keep the
+ // device awake until the display-state change goes into effect.
+ mWakelockController.acquireWakelock(
+ WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
+ }
+ }
+ }
+
// Animate the screen state change unless already animating.
// The transition may be deferred, so after this point we will use the
// actual state instead of the desired one.
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index a5414fcf3970..48fb9fffdc97 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -169,6 +169,11 @@ public class DisplayManagerFlags {
Flags::enableSynthetic60hzModes
);
+ private final FlagState mOffloadDozeOverrideHoldsWakelock = new FlagState(
+ Flags.FLAG_OFFLOAD_DOZE_OVERRIDE_HOLDS_WAKELOCK,
+ Flags::offloadDozeOverrideHoldsWakelock
+ );
+
/**
* @return {@code true} if 'port' is allowed in display layout configuration file.
*/
@@ -331,6 +336,10 @@ public class DisplayManagerFlags {
return mPeakRefreshRatePhysicalLimit.isEnabled();
}
+ public boolean isOffloadDozeOverrideHoldsWakelockEnabled() {
+ return mOffloadDozeOverrideHoldsWakelock.isEnabled();
+ }
+
/**
* @return Whether to ignore preferredRefreshRate app request or not
*/
@@ -376,6 +385,7 @@ public class DisplayManagerFlags {
pw.println(" " + mPeakRefreshRatePhysicalLimit);
pw.println(" " + mIgnoreAppPreferredRefreshRate);
pw.println(" " + mSynthetic60hzModes);
+ pw.println(" " + mOffloadDozeOverrideHoldsWakelock);
}
private static class FlagState {
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index 316b6db49954..2e9743b01287 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -278,3 +278,13 @@ flag {
}
}
+flag {
+ name: "offload_doze_override_holds_wakelock"
+ namespace: "display_manager"
+ description: "DisplayPowerController holds a suspend-blocker while changing the display state on behalf of offload doze override."
+ bug: "338403827"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index e5685c7f4f43..1a720970e626 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -1477,6 +1477,8 @@ public final class DisplayPowerControllerTest {
@Test
public void testDozeScreenStateOverride_toSupportedOffloadStateFromDoze_DisplayStateChanges() {
+ when(mDisplayManagerFlagsMock.isOffloadDozeOverrideHoldsWakelockEnabled()).thenReturn(true);
+
// set up.
int initState = Display.STATE_DOZE;
int supportedTargetState = Display.STATE_DOZE_SUSPEND;
@@ -1495,10 +1497,15 @@ public final class DisplayPowerControllerTest {
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
+ reset(mHolder.wakelockController);
mHolder.dpc.overrideDozeScreenState(
supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY);
advanceTime(1); // Run updatePowerState
+ // Should get a wakelock to notify powermanager
+ verify(mHolder.wakelockController, atLeastOnce()).acquireWakelock(
+ eq(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS));
+
verify(mHolder.displayPowerState)
.setScreenState(supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY);
}