Merge "Update PowerManager to make ambient display suppression apply to dreams." into tm-qpr-dev
This commit is contained in:
@@ -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) -->
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
@@ -3329,7 +3336,7 @@ public final class PowerManagerService extends SystemService
|
||||
}
|
||||
|
||||
// Doze has ended or will be stopped. Update the power state.
|
||||
sleepPowerGroupLocked(powerGroup, now, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
|
||||
sleepPowerGroupLocked(powerGroup, now, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
|
||||
Process.SYSTEM_UID);
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user