Loading services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java +17 −1 Original line number Original line Diff line number Diff line Loading @@ -21,13 +21,21 @@ import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIG import android.annotation.Nullable; import android.annotation.Nullable; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal; import android.os.Trace; import android.os.Trace; import android.util.Slog; import android.view.Display; 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 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. * An offload session is used to control the display's brightness using the offload chip. */ */ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.DisplayOffloadSession { 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 @Nullable private final DisplayManagerInternal.DisplayOffloader mDisplayOffloader; private final DisplayManagerInternal.DisplayOffloader mDisplayOffloader; Loading Loading @@ -99,9 +107,14 @@ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.Display if (mDisplayOffloader == null || mIsActive) { if (mDisplayOffloader == null || mIsActive) { return false; return false; } } Trace.traceBegin(Trace.TRACE_TAG_POWER, "DisplayOffloader#startOffload"); Trace.traceBegin(Trace.TRACE_TAG_POWER, "DisplayOffloader#startOffload"); try { try { return mIsActive = mDisplayOffloader.startOffload(); mIsActive = mDisplayOffloader.startOffload(); if (DEBUG) { Slog.d(TAG, "startOffload = " + mIsActive); } return mIsActive; } finally { } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); Trace.traceEnd(Trace.TRACE_TAG_POWER); } } Loading @@ -118,6 +131,9 @@ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.Display try { try { mDisplayOffloader.stopOffload(); mDisplayOffloader.stopOffload(); mIsActive = false; mIsActive = false; if (DEBUG) { Slog.i(TAG, "stopOffload"); } } finally { } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); Trace.traceEnd(Trace.TRACE_TAG_POWER); } } Loading services/core/java/com/android/server/display/DisplayPowerController.java +27 −2 Original line number Original line Diff line number Diff line Loading @@ -791,6 +791,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Override @Override public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) { public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) { Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState)); mHandler.postAtTime(() -> { mHandler.postAtTime(() -> { if (mDisplayOffloadSession == null if (mDisplayOffloadSession == null || !(DisplayOffloadSession.isSupportedOffloadState(displayState) || !(DisplayOffloadSession.isSupportedOffloadState(displayState) Loading Loading @@ -1279,7 +1280,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private void updatePowerStateInternal() { private void updatePowerStateInternal() { // Update the power state request. // Update the power state request. final boolean mustNotify; boolean mustNotify = false; final int previousPolicy; final int previousPolicy; boolean mustInitialize = false; boolean mustInitialize = false; mBrightnessReasonTemp.set(null); mBrightnessReasonTemp.set(null); Loading Loading @@ -1327,6 +1328,30 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN); 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. // Animate the screen state change unless already animating. // The transition may be deferred, so after this point we will use the // The transition may be deferred, so after this point we will use the // actual state instead of the desired one. // actual state instead of the desired one. Loading services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +10 −0 Original line number Original line Diff line number Diff line Loading @@ -174,6 +174,11 @@ public class DisplayManagerFlags { Flags::enableSynthetic60hzModes 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. * @return {@code true} if 'port' is allowed in display layout configuration file. */ */ Loading Loading @@ -343,6 +348,10 @@ public class DisplayManagerFlags { return mPeakRefreshRatePhysicalLimit.isEnabled(); return mPeakRefreshRatePhysicalLimit.isEnabled(); } } public boolean isOffloadDozeOverrideHoldsWakelockEnabled() { return mOffloadDozeOverrideHoldsWakelock.isEnabled(); } /** /** * @return Whether to ignore preferredRefreshRate app request or not * @return Whether to ignore preferredRefreshRate app request or not */ */ Loading Loading @@ -389,6 +398,7 @@ public class DisplayManagerFlags { pw.println(" " + mPeakRefreshRatePhysicalLimit); pw.println(" " + mPeakRefreshRatePhysicalLimit); pw.println(" " + mIgnoreAppPreferredRefreshRate); pw.println(" " + mIgnoreAppPreferredRefreshRate); pw.println(" " + mSynthetic60hzModes); pw.println(" " + mSynthetic60hzModes); pw.println(" " + mOffloadDozeOverrideHoldsWakelock); } } private static class FlagState { private static class FlagState { Loading services/core/java/com/android/server/display/feature/display_flags.aconfig +10 −0 Original line number Original line Diff line number Diff line Loading @@ -289,3 +289,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 } } services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -1538,6 +1538,8 @@ public final class DisplayPowerControllerTest { @Test @Test public void testDozeScreenStateOverride_toSupportedOffloadStateFromDoze_DisplayStateChanges() { public void testDozeScreenStateOverride_toSupportedOffloadStateFromDoze_DisplayStateChanges() { when(mDisplayManagerFlagsMock.isOffloadDozeOverrideHoldsWakelockEnabled()).thenReturn(true); // set up. // set up. int initState = Display.STATE_DOZE; int initState = Display.STATE_DOZE; int supportedTargetState = Display.STATE_DOZE_SUSPEND; int supportedTargetState = Display.STATE_DOZE_SUSPEND; Loading @@ -1556,10 +1558,15 @@ public final class DisplayPowerControllerTest { mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState advanceTime(1); // Run updatePowerState reset(mHolder.wakelockController); mHolder.dpc.overrideDozeScreenState( mHolder.dpc.overrideDozeScreenState( supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); advanceTime(1); // Run updatePowerState 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) verify(mHolder.displayPowerState) .setScreenState(supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); .setScreenState(supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); } } Loading Loading
services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java +17 −1 Original line number Original line Diff line number Diff line Loading @@ -21,13 +21,21 @@ import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIG import android.annotation.Nullable; import android.annotation.Nullable; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal; import android.os.Trace; import android.os.Trace; import android.util.Slog; import android.view.Display; 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 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. * An offload session is used to control the display's brightness using the offload chip. */ */ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.DisplayOffloadSession { 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 @Nullable private final DisplayManagerInternal.DisplayOffloader mDisplayOffloader; private final DisplayManagerInternal.DisplayOffloader mDisplayOffloader; Loading Loading @@ -99,9 +107,14 @@ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.Display if (mDisplayOffloader == null || mIsActive) { if (mDisplayOffloader == null || mIsActive) { return false; return false; } } Trace.traceBegin(Trace.TRACE_TAG_POWER, "DisplayOffloader#startOffload"); Trace.traceBegin(Trace.TRACE_TAG_POWER, "DisplayOffloader#startOffload"); try { try { return mIsActive = mDisplayOffloader.startOffload(); mIsActive = mDisplayOffloader.startOffload(); if (DEBUG) { Slog.d(TAG, "startOffload = " + mIsActive); } return mIsActive; } finally { } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); Trace.traceEnd(Trace.TRACE_TAG_POWER); } } Loading @@ -118,6 +131,9 @@ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.Display try { try { mDisplayOffloader.stopOffload(); mDisplayOffloader.stopOffload(); mIsActive = false; mIsActive = false; if (DEBUG) { Slog.i(TAG, "stopOffload"); } } finally { } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); Trace.traceEnd(Trace.TRACE_TAG_POWER); } } Loading
services/core/java/com/android/server/display/DisplayPowerController.java +27 −2 Original line number Original line Diff line number Diff line Loading @@ -791,6 +791,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Override @Override public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) { public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) { Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState)); mHandler.postAtTime(() -> { mHandler.postAtTime(() -> { if (mDisplayOffloadSession == null if (mDisplayOffloadSession == null || !(DisplayOffloadSession.isSupportedOffloadState(displayState) || !(DisplayOffloadSession.isSupportedOffloadState(displayState) Loading Loading @@ -1279,7 +1280,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private void updatePowerStateInternal() { private void updatePowerStateInternal() { // Update the power state request. // Update the power state request. final boolean mustNotify; boolean mustNotify = false; final int previousPolicy; final int previousPolicy; boolean mustInitialize = false; boolean mustInitialize = false; mBrightnessReasonTemp.set(null); mBrightnessReasonTemp.set(null); Loading Loading @@ -1327,6 +1328,30 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN); 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. // Animate the screen state change unless already animating. // The transition may be deferred, so after this point we will use the // The transition may be deferred, so after this point we will use the // actual state instead of the desired one. // actual state instead of the desired one. Loading
services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +10 −0 Original line number Original line Diff line number Diff line Loading @@ -174,6 +174,11 @@ public class DisplayManagerFlags { Flags::enableSynthetic60hzModes 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. * @return {@code true} if 'port' is allowed in display layout configuration file. */ */ Loading Loading @@ -343,6 +348,10 @@ public class DisplayManagerFlags { return mPeakRefreshRatePhysicalLimit.isEnabled(); return mPeakRefreshRatePhysicalLimit.isEnabled(); } } public boolean isOffloadDozeOverrideHoldsWakelockEnabled() { return mOffloadDozeOverrideHoldsWakelock.isEnabled(); } /** /** * @return Whether to ignore preferredRefreshRate app request or not * @return Whether to ignore preferredRefreshRate app request or not */ */ Loading Loading @@ -389,6 +398,7 @@ public class DisplayManagerFlags { pw.println(" " + mPeakRefreshRatePhysicalLimit); pw.println(" " + mPeakRefreshRatePhysicalLimit); pw.println(" " + mIgnoreAppPreferredRefreshRate); pw.println(" " + mIgnoreAppPreferredRefreshRate); pw.println(" " + mSynthetic60hzModes); pw.println(" " + mSynthetic60hzModes); pw.println(" " + mOffloadDozeOverrideHoldsWakelock); } } private static class FlagState { private static class FlagState { Loading
services/core/java/com/android/server/display/feature/display_flags.aconfig +10 −0 Original line number Original line Diff line number Diff line Loading @@ -289,3 +289,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 } }
services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -1538,6 +1538,8 @@ public final class DisplayPowerControllerTest { @Test @Test public void testDozeScreenStateOverride_toSupportedOffloadStateFromDoze_DisplayStateChanges() { public void testDozeScreenStateOverride_toSupportedOffloadStateFromDoze_DisplayStateChanges() { when(mDisplayManagerFlagsMock.isOffloadDozeOverrideHoldsWakelockEnabled()).thenReturn(true); // set up. // set up. int initState = Display.STATE_DOZE; int initState = Display.STATE_DOZE; int supportedTargetState = Display.STATE_DOZE_SUSPEND; int supportedTargetState = Display.STATE_DOZE_SUSPEND; Loading @@ -1556,10 +1558,15 @@ public final class DisplayPowerControllerTest { mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState advanceTime(1); // Run updatePowerState reset(mHolder.wakelockController); mHolder.dpc.overrideDozeScreenState( mHolder.dpc.overrideDozeScreenState( supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); advanceTime(1); // Run updatePowerState 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) verify(mHolder.displayPowerState) .setScreenState(supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); .setScreenState(supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); } } Loading