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

Commit 63402cf7 authored by Lucas Silva's avatar Lucas Silva Committed by Android (Google) Code Review
Browse files

Merge "Update PowerManager to make ambient display suppression apply to dreams." into tm-qpr-dev

parents b6100796 6430c547
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2479,6 +2479,8 @@
    <integer name="config_attentionMaximumExtension">900000</integer> <!-- 15 minutes.  -->
    <!-- Is the system user the only user allowed to dream. -->
    <bool name="config_dreamsOnlyEnabledForSystemUser">false</bool>
    <!-- Whether dreams are disabled when ambient mode is suppressed. -->
    <bool name="config_dreamsDisabledByAmbientModeSuppressionConfig">false</bool>

    <!-- Whether to dismiss the active dream when an activity is started. Doesn't apply to
         assistant activities (ACTIVITY_TYPE_ASSISTANT) -->
+1 −0
Original line number Diff line number Diff line
@@ -2235,6 +2235,7 @@
  <java-symbol type="integer" name="config_dreamsBatteryLevelMinimumWhenNotPowered" />
  <java-symbol type="integer" name="config_dreamsBatteryLevelDrainCutoff" />
  <java-symbol type="string" name="config_dreamsDefaultComponent" />
  <java-symbol type="bool" name="config_dreamsDisabledByAmbientModeSuppressionConfig" />
  <java-symbol type="bool" name="config_dreamsOnlyEnabledForSystemUser" />
  <java-symbol type="array" name="config_supportedDreamComplications" />
  <java-symbol type="array" name="config_disabledDreamComponents" />
+21 −4
Original line number Diff line number Diff line
@@ -40,13 +40,24 @@ import java.util.Set;
public class AmbientDisplaySuppressionController {
    private static final String TAG = "AmbientDisplaySuppressionController";

    private final Context mContext;
    private final Set<Pair<String, Integer>> mSuppressionTokens;
    private final AmbientDisplaySuppressionChangedCallback mCallback;
    private IStatusBarService mStatusBarService;

    AmbientDisplaySuppressionController(Context context) {
        mContext = requireNonNull(context);
    /** Interface to get a list of available logical devices. */
    interface AmbientDisplaySuppressionChangedCallback {
        /**
         * Called when the suppression state changes.
         *
         * @param isSuppressed Whether ambient is suppressed.
         */
        void onSuppressionChanged(boolean isSuppressed);
    }

    AmbientDisplaySuppressionController(
            @NonNull AmbientDisplaySuppressionChangedCallback callback) {
        mSuppressionTokens = Collections.synchronizedSet(new ArraySet<>());
        mCallback = requireNonNull(callback);
    }

    /**
@@ -58,6 +69,7 @@ public class AmbientDisplaySuppressionController {
     */
    public void suppress(@NonNull String token, int callingUid, boolean suppress) {
        Pair<String, Integer> suppressionToken = Pair.create(requireNonNull(token), callingUid);
        final boolean wasSuppressed = isSuppressed();

        if (suppress) {
            mSuppressionTokens.add(suppressionToken);
@@ -65,9 +77,14 @@ public class AmbientDisplaySuppressionController {
            mSuppressionTokens.remove(suppressionToken);
        }

        final boolean isSuppressed = isSuppressed();
        if (isSuppressed != wasSuppressed) {
            mCallback.onSuppressionChanged(isSuppressed);
        }

        try {
            synchronized (mSuppressionTokens) {
                getStatusBar().suppressAmbientDisplay(isSuppressed());
                getStatusBar().suppressAmbientDisplay(isSuppressed);
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to suppress ambient display", e);
+41 −4
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ import com.android.server.am.BatteryStatsService;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.power.AmbientDisplaySuppressionController.AmbientDisplaySuppressionChangedCallback;
import com.android.server.power.batterysaver.BatterySaverController;
import com.android.server.power.batterysaver.BatterySaverPolicy;
import com.android.server.power.batterysaver.BatterySaverStateMachine;
@@ -507,6 +508,9 @@ public final class PowerManagerService extends SystemService
    // effectively and terminate the dream.  Use -1 to disable this safety feature.
    private int mDreamsBatteryLevelDrainCutoffConfig;

    // Whether dreams should be disabled when ambient mode is suppressed.
    private boolean mDreamsDisabledByAmbientModeSuppressionConfig;

    // True if dreams are enabled by the user.
    private boolean mDreamsEnabledSetting;

@@ -964,8 +968,8 @@ public final class PowerManagerService extends SystemService
        }

        AmbientDisplaySuppressionController createAmbientDisplaySuppressionController(
                Context context) {
            return new AmbientDisplaySuppressionController(context);
                @NonNull AmbientDisplaySuppressionChangedCallback callback) {
            return new AmbientDisplaySuppressionController(callback);
        }

        InattentiveSleepWarningController createInattentiveSleepWarningController() {
@@ -1044,7 +1048,8 @@ public final class PowerManagerService extends SystemService
        mConstants = new Constants(mHandler);
        mAmbientDisplayConfiguration = mInjector.createAmbientDisplayConfiguration(context);
        mAmbientDisplaySuppressionController =
                mInjector.createAmbientDisplaySuppressionController(context);
                mInjector.createAmbientDisplaySuppressionController(
                        mAmbientSuppressionChangedCallback);
        mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock);
        mFaceDownDetector = new FaceDownDetector(this::onFlip);
        mScreenUndimDetector = new ScreenUndimDetector();
@@ -1403,6 +1408,8 @@ public final class PowerManagerService extends SystemService
                com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenNotPowered);
        mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger(
                com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff);
        mDreamsDisabledByAmbientModeSuppressionConfig = resources.getBoolean(
                com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig);
        mDozeAfterScreenOff = resources.getBoolean(
                com.android.internal.R.bool.config_dozeAfterScreenOffByDefault);
        mMinimumScreenOffTimeoutConfig = resources.getInteger(
@@ -3340,12 +3347,32 @@ public final class PowerManagerService extends SystemService
        }
    }

    @GuardedBy("mLock")
    private void onDreamSuppressionChangedLocked(final boolean isSuppressed) {
        if (!mDreamsDisabledByAmbientModeSuppressionConfig) {
            return;
        }
        if (!isSuppressed && mIsPowered && mDreamsSupportedConfig && mDreamsEnabledSetting
                && shouldNapAtBedTimeLocked() && isItBedTimeYetLocked(
                mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP))) {
            napInternal(SystemClock.uptimeMillis(), Process.SYSTEM_UID, /* allowWake= */ true);
        } else if (isSuppressed) {
            mDirty |= DIRTY_SETTINGS;
            updatePowerStateLocked();
        }
    }


    /**
     * Returns true if the {@code groupId} is allowed to dream in its current state.
     */
    @GuardedBy("mLock")
    private boolean canDreamLocked(final PowerGroup powerGroup) {
        final boolean dreamsSuppressed = mDreamsDisabledByAmbientModeSuppressionConfig
                && mAmbientDisplaySuppressionController.isSuppressed();

        if (!mBootCompleted
                || dreamsSuppressed
                || getGlobalWakefulnessLocked() != WAKEFULNESS_DREAMING
                || !mDreamsSupportedConfig
                || !mDreamsEnabledSetting
@@ -5037,6 +5064,16 @@ public final class PowerManagerService extends SystemService
        }
    };

    private final AmbientDisplaySuppressionChangedCallback mAmbientSuppressionChangedCallback =
            new AmbientDisplaySuppressionChangedCallback() {
                @Override
                public void onSuppressionChanged(boolean isSuppressed) {
                    synchronized (mLock) {
                        onDreamSuppressionChangedLocked(isSuppressed);
                    }
                }
            };

    /**
     * Callback for asynchronous operations performed by the power manager.
     */
+91 −0
Original line number Diff line number Diff line
@@ -393,6 +393,12 @@ public class PowerManagerServiceTest {
                .thenReturn(minimumScreenOffTimeoutConfigMillis);
    }

    private void setDreamsDisabledByAmbientModeSuppressionConfig(boolean disable) {
        when(mResourcesSpy.getBoolean(
                com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig))
                .thenReturn(disable);
    }

    private void advanceTime(long timeMs) {
        mClock.fastForward(timeMs);
        mTestLooper.dispatchAll();
@@ -790,6 +796,91 @@ public class PowerManagerServiceTest {
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
    }

    @SuppressWarnings("GuardedBy")
    @Test
    public void testAmbientSuppression_disablesDreamingAndWakesDevice() {
        Settings.Secure.putInt(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1);
        Settings.Secure.putInt(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ENABLED, 1);

        setDreamsDisabledByAmbientModeSuppressionConfig(true);
        setMinimumScreenOffTimeoutConfig(10000);
        createService();
        startSystem();

        doAnswer(inv -> {
            when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
            return null;
        }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString());

        setPluggedIn(true);
        // Allow asynchronous sandman calls to execute.
        advanceTime(10000);

        forceDream();
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
        mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
        advanceTime(50);
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
    }

    @SuppressWarnings("GuardedBy")
    @Test
    public void testAmbientSuppressionDisabled_shouldNotWakeDevice() {
        Settings.Secure.putInt(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1);
        Settings.Secure.putInt(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ENABLED, 1);

        setDreamsDisabledByAmbientModeSuppressionConfig(false);
        setMinimumScreenOffTimeoutConfig(10000);
        createService();
        startSystem();

        doAnswer(inv -> {
            when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
            return null;
        }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString());

        setPluggedIn(true);
        // Allow asynchronous sandman calls to execute.
        advanceTime(10000);

        forceDream();
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
        mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
        advanceTime(50);
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
    }

    @Test
    public void testAmbientSuppression_doesNotAffectDreamForcing() {
        Settings.Secure.putInt(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1);
        Settings.Secure.putInt(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ENABLED, 1);

        setDreamsDisabledByAmbientModeSuppressionConfig(true);
        setMinimumScreenOffTimeoutConfig(10000);
        createService();
        startSystem();

        doAnswer(inv -> {
            when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
            return null;
        }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString());

        mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
        setPluggedIn(true);
        // Allow asynchronous sandman calls to execute.
        advanceTime(10000);

        // Verify that forcing dream still works even though ambient display is suppressed
        forceDream();
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
    }

    @Test
    public void testSetDozeOverrideFromDreamManager_triggersSuspendBlocker() {
        final String suspendBlockerName = "PowerManagerService.Display";