Remove leftover wallpaper dim on reboot

Unlike other device effects (AOD supression, grayscale, etc) dimWallpaper survives reboots. Because DefaultDeviceEffectsApplier only applies _changed_ effects, this means that dimWallpaper would be stuck if it was active before the reboot, but inactive afterwards.

Although this condition (mode stopping on reboot) is rather rare, it can happen, for example, if DND was set with a timeout and the timeout expired between power-off and power-on.

Fixes: 419466188
Test: atest DefaultDeviceEffectsApplierTest
Flag: EXEMPT Bugfix
Change-Id: Iaeb4b09b4378310142ec1fefe6f9a7409e48411c
diff --git a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
index a75883f..0e1bf62 100644
--- a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
+++ b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
@@ -85,7 +85,7 @@
                 () -> {
                     maybeSuppressAmbientDisplay(effects.shouldSuppressAmbientDisplay());
                     maybeDisplayGrayscale(effects.shouldDisplayGrayscale());
-                    maybeDimWallpaper(effects.shouldDimWallpaper());
+                    maybeDimWallpaper(effects.shouldDimWallpaper(), origin);
                     maybeUseNightMode(effects.shouldUseNightMode(), origin);
                 });
 
@@ -120,19 +120,26 @@
         }
     }
 
-    protected void maybeDimWallpaper(boolean shouldDimWallpaper) {
-        if (mLastAppliedEffects.shouldDimWallpaper() != shouldDimWallpaper) {
-            if (mWallpaperManager != null) {
-                try {
-                    traceApplyDeviceEffect("dimWallpaper", shouldDimWallpaper);
-                    mWallpaperManager.setWallpaperDimAmount(
-                            shouldDimWallpaper
-                                    ? WALLPAPER_DIM_AMOUNT_DIMMED
-                                    : WALLPAPER_DIM_AMOUNT_NORMAL);
-                } catch (Exception e) {
-                    Slog.e(TAG, "Could not change wallpaper override", e);
-                }
+    protected void maybeDimWallpaper(boolean shouldDimWallpaper, @ConfigOrigin int origin) {
+        if (mWallpaperManager == null) {
+            return;
+        }
+        try {
+            // Unlike the other effects, dimWallpaper is serialized (and thus preserved on reboot).
+            if (mLastAppliedEffects.shouldDimWallpaper() != shouldDimWallpaper) {
+                traceApplyDeviceEffect("dimWallpaper", shouldDimWallpaper);
+                mWallpaperManager.setWallpaperDimAmount(
+                        shouldDimWallpaper
+                                ? WALLPAPER_DIM_AMOUNT_DIMMED
+                                : WALLPAPER_DIM_AMOUNT_NORMAL);
+            } else if (origin == ZenModeConfig.ORIGIN_INIT
+                    && !shouldDimWallpaper
+                    && mWallpaperManager.getWallpaperDimAmount() == WALLPAPER_DIM_AMOUNT_DIMMED) {
+                traceApplyDeviceEffect("dimWallpaper (reset on boot)", false);
+                mWallpaperManager.setWallpaperDimAmount(WALLPAPER_DIM_AMOUNT_NORMAL);
             }
+        } catch (Exception e) {
+            Slog.e(TAG, "Could not change wallpaper override", e);
         }
     }
 
@@ -141,7 +148,7 @@
             try {
                 updateOrScheduleNightMode(shouldUseNightMode, origin);
             } catch (Exception e) {
-                Slog.e(TAG, "Could not change dark theme override", e);
+                Slog.e(TAG, "Could not change night mode override", e);
             }
         }
     }
@@ -184,7 +191,7 @@
                         useNightMode ? MODE_ATTENTION_THEME_OVERLAY_NIGHT
                                 : MODE_ATTENTION_THEME_OVERLAY_OFF);
             } catch (Exception e) {
-                Slog.e(TAG, "Could not change wallpaper override", e);
+                Slog.e(TAG, "Could not change night mode override", e);
             }
         });
     }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
index 8023bdd..a5702e2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
@@ -19,6 +19,7 @@
 import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_NIGHT;
 import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_OFF;
 import static android.service.notification.ZenModeConfig.ORIGIN_APP;
+import static android.service.notification.ZenModeConfig.ORIGIN_INIT;
 import static android.service.notification.ZenModeConfig.ORIGIN_USER_IN_SYSTEMUI;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -81,6 +82,8 @@
     @Mock UiModeManager mUiModeManager;
     @Mock WallpaperManager mWallpaperManager;
 
+    private static final ZenDeviceEffects NO_EFFECTS = new ZenDeviceEffects.Builder().build();
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -361,4 +364,28 @@
 
         // No crashes
     }
+
+    @Test
+    public void apply_onBootWithLeftoverDim_forceRemovesDimWallpaper() {
+        when(mWallpaperManager.getWallpaperDimAmount()).thenReturn(0.6f);
+        mApplier.apply(NO_EFFECTS, ORIGIN_INIT);
+        verify(mWallpaperManager).setWallpaperDimAmount(eq(0f));
+
+        String zenLog = getZenLog();
+        assertThat(zenLog).contains("apply_device_effect: dimWallpaper (reset on boot) -> false");
+    }
+
+    @Test
+    public void apply_onBootWithUnrelatedDim_doesNotForceRemoveDimWallpaper() {
+        when(mWallpaperManager.getWallpaperDimAmount()).thenReturn(0.42f);
+        mApplier.apply(NO_EFFECTS, ORIGIN_INIT);
+        verify(mWallpaperManager, never()).setWallpaperDimAmount(anyFloat());
+    }
+
+    @Test
+    public void apply_notOnBoot_doesNotForceRemoveDimWallpaper() {
+        when(mWallpaperManager.getWallpaperDimAmount()).thenReturn(0.6f);
+        mApplier.apply(NO_EFFECTS, ORIGIN_APP);
+        verify(mWallpaperManager, never()).setWallpaperDimAmount(anyFloat());
+    }
 }