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

Commit f71d6a6e authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Guard against crashes in effects services

Test: DefaultDeviceEffectsApplierTest
Test: activate mode with effects active, reboot
Bug: 344545351
Flag: android.app.modes_api
Change-Id: Iadc4558aeff2959fb494e730499eebe8afdb59f7
parent aa317c37
Loading
Loading
Loading
Loading
+34 −13
Original line number Diff line number Diff line
@@ -32,12 +32,13 @@ import android.service.notification.DeviceEffectsApplier;
import android.service.notification.ZenDeviceEffects;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ConfigChangeOrigin;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;

/** Default implementation for {@link DeviceEffectsApplier}. */
class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {

    private static final String TAG = "DeviceEffectsApplier";
    private static final String SUPPRESS_AMBIENT_DISPLAY_TOKEN =
            "DefaultDeviceEffectsApplier:SuppressAmbientDisplay";
    private static final int SATURATION_LEVEL_GRAYSCALE = 0;
@@ -75,28 +76,44 @@ class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {
        Binder.withCleanCallingIdentity(() -> {
            if (mLastAppliedEffects.shouldSuppressAmbientDisplay()
                    != effects.shouldSuppressAmbientDisplay()) {
                try {
                    mPowerManager.suppressAmbientDisplay(SUPPRESS_AMBIENT_DISPLAY_TOKEN,
                            effects.shouldSuppressAmbientDisplay());
                } catch (Exception e) {
                    Slog.e(TAG, "Could not change AOD override", e);
                }
            }

            if (mLastAppliedEffects.shouldDisplayGrayscale() != effects.shouldDisplayGrayscale()) {
                if (mColorDisplayManager != null) {
                    try {
                        mColorDisplayManager.setSaturationLevel(
                                effects.shouldDisplayGrayscale() ? SATURATION_LEVEL_GRAYSCALE
                                        : SATURATION_LEVEL_FULL_COLOR);
                    } catch (Exception e) {
                        Slog.e(TAG, "Could not change grayscale override", e);
                    }
                }
            }

            if (mLastAppliedEffects.shouldDimWallpaper() != effects.shouldDimWallpaper()) {
                if (mWallpaperManager != null) {
                    try {
                        mWallpaperManager.setWallpaperDimAmount(
                                effects.shouldDimWallpaper() ? WALLPAPER_DIM_AMOUNT_DIMMED
                                        : WALLPAPER_DIM_AMOUNT_NORMAL);
                    } catch (Exception e) {
                        Slog.e(TAG, "Could not change wallpaper override", e);
                    }
                }
            }

            if (mLastAppliedEffects.shouldUseNightMode() != effects.shouldUseNightMode()) {
                try {
                    updateOrScheduleNightMode(effects.shouldUseNightMode(), origin);
                } catch (Exception e) {
                    Slog.e(TAG, "Could not change dark theme override", e);
                }
            }
        });

@@ -131,9 +148,13 @@ class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {

    private void updateNightModeImmediately(boolean useNightMode) {
        Binder.withCleanCallingIdentity(() -> {
            try {
                mUiModeManager.setAttentionModeThemeOverlay(
                        useNightMode ? MODE_ATTENTION_THEME_OVERLAY_NIGHT
                                : MODE_ATTENTION_THEME_OVERLAY_OFF);
            } catch (Exception e) {
                Slog.e(TAG, "Could not change wallpaper override", e);
            }
        });
    }

+24 −0
Original line number Diff line number Diff line
@@ -25,10 +25,12 @@ import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -322,4 +324,26 @@ public class DefaultDeviceEffectsApplierTest {
                argThat(filter -> Intent.ACTION_SCREEN_OFF.equals(filter.getAction(0))),
                anyInt());
    }

    @Test
    public void apply_servicesThrow_noCrash() {
        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);

        doThrow(new RuntimeException()).when(mPowerManager)
                .suppressAmbientDisplay(anyString(), anyBoolean());
        doThrow(new RuntimeException()).when(mColorDisplayManager).setSaturationLevel(anyInt());
        doThrow(new RuntimeException()).when(mWallpaperManager).setWallpaperDimAmount(anyFloat());
        doThrow(new RuntimeException()).when(mUiModeManager).setAttentionModeThemeOverlay(anyInt());
        mApplier = new DefaultDeviceEffectsApplier(mContext);

        ZenDeviceEffects effects = new ZenDeviceEffects.Builder()
                .setShouldSuppressAmbientDisplay(true)
                .setShouldDimWallpaper(true)
                .setShouldDisplayGrayscale(true)
                .setShouldUseNightMode(true)
                .build();
        mApplier.apply(effects, UPDATE_ORIGIN_USER);

        // No crashes
    }
}