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

Commit 3fa7d763 authored by William Xiao's avatar William Xiao
Browse files

Implement setting to restrict dream to wireless charging

The new setting limits dreams to only start when the device is charging
wirelessly. This CL implements the logic for both screen timeout and
power button presses. Note that the setting does not apply when the
"When to dream" setting is "Docked and charging" because there are
currently no devices that can be both docked and wireless charging.
The setting will be hidden on devices that cannot be wirelessly
charged.

Bug: 406802735
Test: atest DreamManagerServiceTest PowerManagerServiceTest
Flag: android.service.dreams.dreams_v2
Change-Id: I518e12dd9078031faff77cfeabbf54f071ae898d
parent 740452e3
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -339,6 +339,10 @@ message PowerServiceSettingsAndConfigurationDumpProto {
    optional sint32 attentive_timeout_config_ms = 38;
    // The attentive warning duration config value in milliseconds.
    optional sint32 attentive_warning_duration_config_ms = 39;
    // Whether dreams should be activated when device is postured (stationary and upright)
    optional bool are_dreams_activate_while_postured_setting = 40;
    // True if dreams should only be activated while wireless charging.
    optional bool are_dreams_activate_only_while_wireless_charging = 41;
}

message BatterySaverStateMachineProto {
+38 −4
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.service.dreams.Flags.allowDreamWhenPostured;
import static android.service.dreams.Flags.cleanupDreamSettingsOnUninstall;
import static android.service.dreams.Flags.dreamHandlesBeingObscured;
import static android.service.dreams.Flags.dreamsV2;

import static com.android.server.wm.ActivityInterceptorCallback.DREAM_MANAGER_ORDERED_ID;

@@ -140,6 +141,7 @@ public final class DreamManagerService extends SystemService {
    private final boolean mDreamsActivatedOnChargeByDefault;
    private final boolean mDreamsActivatedOnDockByDefault;
    private final boolean mDreamsActivatedOnPosturedByDefault;
    private final boolean mOnlyDreamOnWirelessChargingDefault;
    private final boolean mKeepDreamingWhenUnpluggingDefault;
    private final boolean mDreamsDisabledByAmbientModeSuppressionConfig;

@@ -153,8 +155,14 @@ public final class DreamManagerService extends SystemService {
    private SettingsObserver mSettingsObserver;
    private boolean mDreamsEnabledSetting;
    @WhenToDream private int mWhenToDream;

    /**
     * If true, the user has enabled the setting to only dream when charging wirelessly.
     */
    private boolean mOnlyDreamOnWirelessChargingSetting;
    private boolean mIsDocked;
    private boolean mIsCharging;
    private boolean mIsWirelessCharging;
    private boolean mIsPostured;

    // A temporary dream component that, when present, takes precedence over user configured dream
@@ -202,6 +210,8 @@ public final class DreamManagerService extends SystemService {
        @Override
        public void onReceive(Context context, Intent intent) {
            mIsCharging = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
            mIsWirelessCharging = mBatteryManagerInternal.isPowered(
                    BatteryManager.BATTERY_PLUGGED_WIRELESS);
        }
    };

@@ -272,6 +282,8 @@ public final class DreamManagerService extends SystemService {
                com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
        mDreamsActivatedOnPosturedByDefault = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_dreamsActivatedOnPosturedByDefault);
        // TODO(b/407768891): use default config when added.
        mOnlyDreamOnWirelessChargingDefault = false;
        mSettingsObserver = new SettingsObserver(mHandler);
        mKeepDreamingWhenUnpluggingDefault = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_keepDreamingWhenUnplugging);
@@ -326,10 +338,15 @@ public final class DreamManagerService extends SystemService {
            mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
                            Settings.Secure.SCREENSAVER_ENABLED),
                    false, mSettingsObserver, UserHandle.USER_ALL);
            mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
                            Settings.Secure.SCREENSAVER_RESTRICT_TO_WIRELESS_CHARGING),
                    false, mSettingsObserver, UserHandle.USER_ALL);

            // We don't get an initial broadcast for the batter state, so we have to initialize
            // We don't get an initial broadcast for the battery state, so we have to initialize
            // directly from BatteryManager.
            mIsCharging = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
            mIsWirelessCharging = mBatteryManagerInternal.isPowered(
                    BatteryManager.BATTERY_PLUGGED_WIRELESS);

            updateWhenToDreamSettings();
        }
@@ -390,6 +407,10 @@ public final class DreamManagerService extends SystemService {
            pw.println("mDreamsActivatedOnChargeByDefault=" + mDreamsActivatedOnChargeByDefault);
            pw.println("mDreamsActivatedOnPosturedByDefault="
                    + mDreamsActivatedOnPosturedByDefault);
            pw.println("mOnlyDreamOnWirelessChargingSetting="
                    + mOnlyDreamOnWirelessChargingSetting);
            pw.println("mOnlyDreamOnWirelessChargingDefault="
                    + mOnlyDreamOnWirelessChargingDefault);
            pw.println("mIsDocked=" + mIsDocked);
            pw.println("mIsCharging=" + mIsCharging);
            pw.println("mWhenToDream=" + mWhenToDream);
@@ -407,12 +428,16 @@ public final class DreamManagerService extends SystemService {
        synchronized (mLock) {
            final ContentResolver resolver = mContext.getContentResolver();

            mOnlyDreamOnWirelessChargingSetting = Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.SCREENSAVER_RESTRICT_TO_WIRELESS_CHARGING,
                    mOnlyDreamOnWirelessChargingDefault ? 1 : 0, UserHandle.USER_CURRENT) != 0;

            mWhenToDream = DREAM_DISABLED;

            if ((Settings.Secure.getIntForUser(resolver,
            if (Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
                    mDreamsActivatedOnChargeByDefault ? 1 : 0,
                    UserHandle.USER_CURRENT) != 0)) {
                    UserHandle.USER_CURRENT) != 0) {
                mWhenToDream |= DREAM_ON_CHARGE;
            }

@@ -496,14 +521,23 @@ public final class DreamManagerService extends SystemService {

    private boolean dreamConditionActiveInternalLocked() {
        if ((mWhenToDream & DREAM_ON_CHARGE) == DREAM_ON_CHARGE) {
            if (dreamsV2() && mOnlyDreamOnWirelessChargingSetting) {
                return mIsWirelessCharging;
            } else {
                return mIsCharging;
            }
        }

        if ((mWhenToDream & DREAM_ON_DOCK) == DREAM_ON_DOCK) {
            // Don't check wireless charging on dock as wireless charging is mutually exclusive with
            // docking.
            return mIsDocked;
        }

        if ((mWhenToDream & DREAM_ON_POSTURED) == DREAM_ON_POSTURED) {
            if (dreamsV2() && mOnlyDreamOnWirelessChargingSetting && !mIsWirelessCharging) {
                return false;
            }
            return mIsPostured;
        }

+40 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
import static android.os.PowerManagerInternal.isInteractive;
import static android.os.PowerManagerInternal.wakefulnessToString;
import static android.service.dreams.Flags.allowDreamWhenPostured;
import static android.service.dreams.Flags.dreamsV2;

import static com.android.internal.util.LatencyTracker.ACTION_TURN_ON_SCREEN;
import static com.android.server.deviceidle.Flags.disableWakelocksInLightIdle;
@@ -545,6 +546,9 @@ public final class PowerManagerService extends SystemService
    /** Default value for whether dreams are activated when postured (stationary + upright) */
    private boolean mDreamsActivatedWhilePosturedByDefaultConfig;

    /** Default value for whether dreams should only be activated while wireless charging. */
    private boolean mDreamsActivatedOnlyWhileWirelessChargingConfig;

    // True if dreams can run while not plugged in.
    private boolean mDreamsEnabledOnBatteryConfig;

@@ -576,6 +580,9 @@ public final class PowerManagerService extends SystemService
    /** Whether dreams should be activated when device is postured (stationary and upright) */
    private boolean mDreamsActivateWhilePosturedSetting;

    /** True if dreams should only be activated while wireless charging. */
    private boolean mDreamsOnlyWhileWirelessChargingSetting;

    // True if doze should not be started until after the screen off transition.
    private boolean mDozeAfterScreenOff;

@@ -1492,6 +1499,9 @@ public final class PowerManagerService extends SystemService
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_POSTURED),
                false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                Settings.Secure.SCREENSAVER_RESTRICT_TO_WIRELESS_CHARGING),
                false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.System.getUriFor(
                Settings.System.SCREEN_OFF_TIMEOUT),
                false, mSettingsObserver, UserHandle.USER_ALL);
@@ -1572,6 +1582,9 @@ public final class PowerManagerService extends SystemService
                com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
        mDreamsActivatedWhilePosturedByDefaultConfig = resources.getBoolean(
                com.android.internal.R.bool.config_dreamsActivatedOnPosturedByDefault);
        mDreamsActivatedOnlyWhileWirelessChargingConfig = resources.getBoolean(
                com.android.internal.R.bool.config_onlyShowGlanceableHubWhenWirelessChargingDefault
        );
        mDreamsEnabledOnBatteryConfig = resources.getBoolean(
                com.android.internal.R.bool.config_dreamsEnabledOnBattery);
        mDreamsBatteryLevelMinimumWhenPoweredConfig = resources.getInteger(
@@ -1616,6 +1629,10 @@ public final class PowerManagerService extends SystemService
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_POSTURED,
                mDreamsActivatedWhilePosturedByDefaultConfig ? 1 : 0,
                UserHandle.USER_CURRENT) != 0);
        mDreamsOnlyWhileWirelessChargingSetting = (Settings.Secure.getIntForUser(resolver,
                Settings.Secure.SCREENSAVER_RESTRICT_TO_WIRELESS_CHARGING,
                mDreamsActivatedOnlyWhileWirelessChargingConfig ? 1 : 0,
                UserHandle.USER_CURRENT) != 0);
        mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
                Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
                UserHandle.USER_CURRENT);
@@ -3410,9 +3427,18 @@ public final class PowerManagerService extends SystemService
        if (!powerGroup.supportsSandmanLocked()) {
            return false;
        }
        if (mDreamsActivateOnDockSetting
                && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
            return true;
        }
        if (dreamsV2() && mDreamsOnlyWhileWirelessChargingSetting
                && mPlugType != BatteryManager.BATTERY_PLUGGED_WIRELESS) {
            // Only limit dream to wireless charging for dream on sleep or dream on postured, as
            // docking (as defined by the dream setting) is mutually exclusive with wireless
            // charging.
            return false;
        }
        return mDreamsActivateOnSleepSetting
                || (mDreamsActivateOnDockSetting
                        && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED)
                || (mDreamsActivateWhilePosturedSetting && mDevicePostured);
    }

@@ -4858,6 +4884,8 @@ public final class PowerManagerService extends SystemService
                    + mDreamsActivatedOnDockByDefaultConfig);
            pw.println("  mDreamsActivatedWhilePosturedByDefaultConfig="
                    + mDreamsActivatedWhilePosturedByDefaultConfig);
            pw.println("  mDreamsActivatedOnlyWhileWirelessChargingConfig="
                    + mDreamsActivatedOnlyWhileWirelessChargingConfig);
            pw.println("  mDreamsEnabledOnBatteryConfig="
                    + mDreamsEnabledOnBatteryConfig);
            pw.println("  mDreamsBatteryLevelMinimumWhenPoweredConfig="
@@ -4871,6 +4899,8 @@ public final class PowerManagerService extends SystemService
            pw.println("  mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting);
            pw.println("  mDreamsActivateWhilePosturedSetting="
                    + mDreamsActivateWhilePosturedSetting);
            pw.println("  mDreamsOnlyOnWirelessChargingSetting="
                    + mDreamsOnlyWhileWirelessChargingSetting);
            pw.println("  mDozeAfterScreenOff=" + mDozeAfterScreenOff);
            pw.println("  mBrightWhenDozingConfig=" + mBrightWhenDozingConfig);
            pw.println("  mMinimumScreenOffTimeoutConfig=" + mMinimumScreenOffTimeoutConfig);
@@ -5200,6 +5230,14 @@ public final class PowerManagerService extends SystemService
                    PowerServiceSettingsAndConfigurationDumpProto
                            .ARE_DREAMS_ACTIVATE_ON_DOCK_SETTING,
                    mDreamsActivateOnDockSetting);
            proto.write(
                    PowerServiceSettingsAndConfigurationDumpProto
                            .ARE_DREAMS_ACTIVATE_WHILE_POSTURED_SETTING,
                    mDreamsActivateWhilePosturedSetting);
            proto.write(
                    PowerServiceSettingsAndConfigurationDumpProto
                            .ARE_DREAMS_ACTIVATE_ONLY_WHILE_WIRELESS_CHARGING,
                    mDreamsOnlyWhileWirelessChargingSetting);
            proto.write(
                    PowerServiceSettingsAndConfigurationDumpProto.IS_DOZE_AFTER_SCREEN_OFF_CONFIG,
                    mDozeAfterScreenOff);
+1 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ android_test {

    static_libs: [
        "androidx.test.ext.truth",
        "flag-junit",
        "frameworks-base-testutils",
        "mockito-target-minus-junit4",
        "services.core",
+67 −23
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.dreams;

import static android.service.dreams.Flags.FLAG_DREAMS_V2;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -31,10 +33,13 @@ import android.app.ActivityManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ContextWrapper;
import android.content.Intent;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.PowerManagerInternal;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.testing.TestableContext;

@@ -60,6 +65,9 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DreamManagerServiceTest {
    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

    private ContextWrapper mContextSpy;

    @Mock
@@ -77,10 +85,8 @@ public class DreamManagerServiceTest {
    @Rule
    public LocalServiceKeeperRule mLocalServiceKeeperRule = new LocalServiceKeeperRule();


    @Rule
    public final TestableContext mContext = new TestableContext(
            getInstrumentation().getContext());
    public final TestableContext mContext = new TestableContext(getInstrumentation().getContext());

    private TestHandler mTestHandler;

@@ -90,14 +96,14 @@ public class DreamManagerServiceTest {
        MockitoAnnotations.initMocks(this);
        mContextSpy = spy(mContext);

        mLocalServiceKeeperRule.overrideLocalService(
                ActivityManagerInternal.class, mActivityManagerInternalMock);
        mLocalServiceKeeperRule.overrideLocalService(
                BatteryManagerInternal.class, mBatteryManagerInternal);
        mLocalServiceKeeperRule.overrideLocalService(
                InputManagerInternal.class, mInputManagerInternal);
        mLocalServiceKeeperRule.overrideLocalService(
                PowerManagerInternal.class, mPowerManagerInternalMock);
        mLocalServiceKeeperRule.overrideLocalService(ActivityManagerInternal.class,
                mActivityManagerInternalMock);
        mLocalServiceKeeperRule.overrideLocalService(BatteryManagerInternal.class,
                mBatteryManagerInternal);
        mLocalServiceKeeperRule.overrideLocalService(InputManagerInternal.class,
                mInputManagerInternal);
        mLocalServiceKeeperRule.overrideLocalService(PowerManagerInternal.class,
                mPowerManagerInternalMock);

        Settings.Secure.putInt(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 0);
@@ -117,8 +123,7 @@ public class DreamManagerServiceTest {
    public void testSettingsQueryUserChange() {
        // Enable dreams.
        Settings.Secure.putIntForUser(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ENABLED, 1,
                UserHandle.USER_CURRENT);
                Settings.Secure.SCREENSAVER_ENABLED, 1, UserHandle.USER_CURRENT);

        // Initialize dream service so settings are read.
        final DreamManagerService service = createService();
@@ -129,8 +134,7 @@ public class DreamManagerServiceTest {

        // Disable dreams.
        Settings.Secure.putIntForUser(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ENABLED, 0,
                UserHandle.USER_CURRENT);
                Settings.Secure.SCREENSAVER_ENABLED, 0, UserHandle.USER_CURRENT);

        // Switch users, dreams are disabled.
        service.onUserSwitching(null, null);
@@ -141,8 +145,7 @@ public class DreamManagerServiceTest {
    public void testDreamConditionActive_onDock() {
        // Enable dreaming on dock.
        Settings.Secure.putIntForUser(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 1,
                UserHandle.USER_CURRENT);
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 1, UserHandle.USER_CURRENT);

        // Initialize service so settings are read.
        final DreamManagerService service = createService();
@@ -168,11 +171,9 @@ public class DreamManagerServiceTest {
    public void testDreamConditionActive_postured() {
        // Enable dreaming while postured.
        Settings.Secure.putIntForUser(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 0,
                UserHandle.USER_CURRENT);
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 0, UserHandle.USER_CURRENT);
        Settings.Secure.putIntForUser(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_POSTURED, 1,
                UserHandle.USER_CURRENT);
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_POSTURED, 1, UserHandle.USER_CURRENT);

        // Initialize service so settings are read.
        final DreamManagerService service = createService();
@@ -190,8 +191,7 @@ public class DreamManagerServiceTest {
    public void testDreamConditionActive_charging() {
        // Enable dreaming while charging only.
        Settings.Secure.putIntForUser(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1,
                UserHandle.USER_CURRENT);
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1, UserHandle.USER_CURRENT);

        // Device is charging.
        when(mBatteryManagerInternal.isPowered(anyInt())).thenReturn(true);
@@ -203,4 +203,48 @@ public class DreamManagerServiceTest {
        // Dream condition is active.
        assertThat(service.dreamConditionActiveInternal()).isTrue();
    }

    @EnableFlags(FLAG_DREAMS_V2)
    @Test
    public void testDreamConditionActive_onlyWirelessCharging_falseWhenNotWirelessCharging() {
        // Enable dreaming while wireless charging only.
        Settings.Secure.putIntForUser(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1, UserHandle.USER_CURRENT);
        Settings.Secure.putIntForUser(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_RESTRICT_TO_WIRELESS_CHARGING, 1,
                UserHandle.USER_CURRENT);

        // Device is charging but not wirelessly.
        when(mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY)).thenReturn(
                true);

        // Initialize service so settings are read.
        final DreamManagerService service = createService();
        service.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);

        // Dream condition is not active.
        assertThat(service.dreamConditionActiveInternal()).isFalse();
    }

    @EnableFlags(FLAG_DREAMS_V2)
    @Test
    public void testDreamConditionActive_onlyWirelessCharging_trueWhenWirelessCharging() {
        // Enable dreaming while wireless charging only.
        Settings.Secure.putIntForUser(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1, UserHandle.USER_CURRENT);
        Settings.Secure.putIntForUser(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_RESTRICT_TO_WIRELESS_CHARGING, 1,
                UserHandle.USER_CURRENT);

        // Device is charging wirelessly.
        when(mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_WIRELESS)).thenReturn(
                true);

        // Initialize service so settings are read.
        final DreamManagerService service = createService();
        service.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);

        // Dream condition is active.
        assertThat(service.dreamConditionActiveInternal()).isTrue();
    }
}
Loading