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

Commit eb351637 authored by Will Leshner's avatar Will Leshner
Browse files

Fix an issue with dream settings not being disabled properly.

Bug: 416099970
Test: atest DreamSettingsTest
Flag: EXEMPT bug fix
NO_IFTTT=No change necessary

Change-Id: I6da2f373b741b9580bdf24458efaefef0053afcc
parent cf4a1f5a
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -50,12 +50,11 @@
        android:summary="@string/dream_complications_toggle_summary"
        settings:controller="com.android.settings.dream.DreamComplicationPreferenceController"/>

    <com.android.settingslib.PrimarySwitchPreference
    <com.android.settings.dream.LowLightModePreference
        android:key="low_light_mode"
        android:order="350"
        android:title="@string/screensaver_settings_low_light_mode"
        android:fragment="com.android.settings.dream.LowLightModePicker"
        settings:controller="com.android.settings.dream.LowLightModePreferenceController" />
        android:fragment="com.android.settings.dream.LowLightModePicker" />

    <SwitchPreferenceCompat
        android:key="dream_home_controls_toggle"
+31 −12
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import androidx.recyclerview.widget.RecyclerView;

import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -70,9 +71,12 @@ public class DreamSettings extends DashboardFragment implements OnCheckedChangeL

    private DreamPickerController mDreamPickerController;
    private DreamHomeControlsPreferenceController mDreamHomeControlsPreferenceController;
    private LowLightModePreferenceController mLowLightModePreferenceController;

    private final DreamPickerController.Callback mCallback =
            this::updateComplicationsToggleVisibility;
    /** A callback that is invoked whenever the selected dream changes. */
    private final DreamPickerController.Callback mCallback = () ->
            updateSelectedDreamSettingsState(
                    mMainSwitchPreference != null ? mMainSwitchPreference.isChecked() : false);

    @WhenToDream
    static int getSettingFromPrefKey(String key) {
@@ -157,12 +161,20 @@ public class DreamSettings extends DashboardFragment implements OnCheckedChangeL
        if (mDreamPickerController == null) {
            mDreamPickerController = new DreamPickerController(context);
        }

        DreamBackend backend = DreamBackend.getInstance(context);
        if (mDreamHomeControlsPreferenceController == null) {
            mDreamHomeControlsPreferenceController = new DreamHomeControlsPreferenceController(
                    context, DreamBackend.getInstance(getContext()));
            mDreamHomeControlsPreferenceController =
                    new DreamHomeControlsPreferenceController(context, backend);
        }
        if (mLowLightModePreferenceController == null) {
            mLowLightModePreferenceController =
                    new LowLightModePreferenceController(context, backend);
        }

        controllers.add(mDreamPickerController);
        controllers.add(mDreamHomeControlsPreferenceController);
        controllers.add(mLowLightModePreferenceController);
        controllers.add(new WhenToDreamPreferenceController(context));
        return controllers;
    }
@@ -193,6 +205,11 @@ public class DreamSettings extends DashboardFragment implements OnCheckedChangeL
        mDreamHomeControlsPreferenceController = dreamHomeControlsPreferenceController;
    }

    @VisibleForTesting
    void setLowLightModePreferenceController(LowLightModePreferenceController controller) {
        mLowLightModePreferenceController = controller;
    }

    private void setAllPreferencesEnabled(boolean isEnabled) {
        getPreferenceControllers().forEach(controllers -> {
            controllers.forEach(controller -> {
@@ -210,7 +227,8 @@ public class DreamSettings extends DashboardFragment implements OnCheckedChangeL
                }
            });
        });
        updateComplicationsToggleVisibility();

        updateSelectedDreamSettingsState(isEnabled);
    }

    @Override
@@ -275,14 +293,16 @@ public class DreamSettings extends DashboardFragment implements OnCheckedChangeL
        return mRecyclerView;
    }

    private void updateComplicationsToggleVisibility() {
    /**
     * Updates the visibility and enabled state of preferences that depend on the currently selected
     * dream.
     */
    private void updateSelectedDreamSettingsState(boolean dreamsEnabled) {
        if (mDreamPickerController == null) {
            return;
        }
        final DreamBackend.DreamInfo activeDream = mDreamPickerController.getActiveDreamInfo();

        final DreamBackend dreamBackend = DreamBackend.getInstance(getContext());

        final DreamBackend.DreamInfo activeDream = mDreamPickerController.getActiveDreamInfo();

        if (mComplicationsTogglePreference != null) {
            mComplicationsTogglePreference.setVisible(
@@ -290,13 +310,12 @@ public class DreamSettings extends DashboardFragment implements OnCheckedChangeL
        }

        if (mHomeControllerTogglePreference != null) {
            boolean isEnabled = dreamBackend.isEnabled()
            boolean isEnabled = dreamsEnabled
                                && (activeDream == null
                                || (activeDream.dreamCategory
                                & DreamService.DREAM_CATEGORY_HOME_PANEL) == 0)
                                && mDreamHomeControlsPreferenceController
                                    .getAvailabilityStatus()
                                    == mDreamHomeControlsPreferenceController.AVAILABLE;
                                    .getAvailabilityStatus() == BasePreferenceController.AVAILABLE;
            mHomeControllerTogglePreference.setEnabled(isEnabled);
        }
    }
+40 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.dream;

import android.content.Context;
import android.util.AttributeSet;

import com.android.settingslib.PrimarySwitchPreference;

/**
 * A {@link PrimarySwitchPreference} used for the low-light mode setting that includes an in-line
 * toggle. The toggle is enabled or disabled with the preference whenever setEnabled() is called.
 */
public class LowLightModePreference extends PrimarySwitchPreference {
    public LowLightModePreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);

        // Set the switch's enabled state as well.
        setSwitchEnabled(enabled);
    }
}
+5 −3
Original line number Diff line number Diff line
@@ -33,14 +33,16 @@ import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.dream.DreamBackend;

public class LowLightModePreferenceController extends TogglePreferenceController {
    public static final String PREF_KEY = "low_light_mode";

    private final DreamBackend mBackend;
    @Nullable
    private Preference mPreference;

    public LowLightModePreferenceController(@NonNull Context context, @NonNull String key) {
        super(context, key);
    public LowLightModePreferenceController(@NonNull Context context, DreamBackend dreamBackend) {
        super(context, PREF_KEY);

        mBackend = DreamBackend.getInstance(context);
        mBackend = dreamBackend;
    }

    @Override
+66 −4
Original line number Diff line number Diff line
@@ -21,12 +21,14 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.os.Bundle;
import android.service.dreams.DreamService;
import android.widget.CompoundButton;

import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
@@ -37,6 +39,7 @@ import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settingslib.dream.DreamBackend;
import com.android.settingslib.dream.DreamBackend.WhenToDream;
import com.android.settingslib.widget.MainSwitchPreference;

import org.junit.Test;
import org.junit.runner.RunWith;
@@ -88,6 +91,8 @@ public class DreamSettingsTest {
            R.string.screensaver_settings_summary_never
    };

    @Mock
    private MainSwitchPreference mMainSwitchPreference;
    @Mock
    private Preference mDreamPickerPref;
    @Mock
@@ -95,9 +100,13 @@ public class DreamSettingsTest {
    @Mock
    private Preference mHomeControllerTogglePref;
    @Mock
    private LowLightModePreference mLowLightModeTogglePref;
    @Mock
    private DreamPickerController mDreamPickerController;
    @Mock
    private DreamHomeControlsPreferenceController mDreamHomeControlsPreferenceController;
    @Mock
    private LowLightModePreferenceController mLowLightModePreferenceController;
    @Captor
    private ArgumentCaptor<DreamPickerController.Callback> mDreamPickerCallbackCaptor;

@@ -290,7 +299,6 @@ public class DreamSettingsTest {
        final Context context = ApplicationProvider.getApplicationContext();
        final DreamSettings dreamSettings = prepareDreamSettings(context);


        // Active dream does not support complications
        final DreamBackend.DreamInfo activeDream = new DreamBackend.DreamInfo();
        activeDream.dreamCategory = DreamService.DREAM_CATEGORY_DEFAULT;
@@ -315,7 +323,6 @@ public class DreamSettingsTest {
        final Context context = ApplicationProvider.getApplicationContext();
        final DreamSettings dreamSettings = prepareDreamSettings(context);


        // Active dream does not support complications
        final DreamBackend.DreamInfo activeDream = new DreamBackend.DreamInfo();
        activeDream.dreamCategory = DreamService.DREAM_CATEGORY_HOME_PANEL;
@@ -328,33 +335,88 @@ public class DreamSettingsTest {
        verify(mHomeControllerTogglePref).setEnabled(false);
        verify(mDreamPickerController).addCallback(mDreamPickerCallbackCaptor.capture());

        when(mMainSwitchPreference.isChecked()).thenReturn(true);
        activeDream.dreamCategory = DreamService.DREAM_CATEGORY_DEFAULT;
        mDreamPickerCallbackCaptor.getValue().onActiveDreamChanged();
        verify(mHomeControllerTogglePref).setEnabled(true);
    }

    @Test
    public void lowLightModeToggle_disabledWhenMainSwitchDisabled() {
        MockitoAnnotations.initMocks(this);

        final Context context = ApplicationProvider.getApplicationContext();
        final DreamSettings dreamSettings = prepareDreamSettings(context);

        final DreamBackend.DreamInfo activeDream = new DreamBackend.DreamInfo();
        activeDream.dreamCategory = DreamService.DREAM_CATEGORY_DEFAULT;
        when(mDreamPickerController.getActiveDreamInfo()).thenReturn(activeDream);

        dreamSettings.onAttach(context);
        dreamSettings.onCreate(Bundle.EMPTY);
        reset(mLowLightModeTogglePref);

        // DreamSettings ignores the button, but we need something to pass into onCheckedChanged.
        final CompoundButton mockButton = mock(CompoundButton.class);
        dreamSettings.onCheckedChanged(mockButton, false);
        verify(mLowLightModeTogglePref).setEnabled(false);
    }

    @Test
    public void lowLightModeToggle_enabledWhenMainSwitchEnabled() {
        MockitoAnnotations.initMocks(this);

        final Context context = ApplicationProvider.getApplicationContext();
        final DreamSettings dreamSettings = prepareDreamSettings(context);

        final DreamBackend.DreamInfo activeDream = new DreamBackend.DreamInfo();
        activeDream.dreamCategory = DreamService.DREAM_CATEGORY_DEFAULT;
        when(mDreamPickerController.getActiveDreamInfo()).thenReturn(activeDream);

        dreamSettings.onAttach(context);
        dreamSettings.onCreate(Bundle.EMPTY);
        reset(mLowLightModeTogglePref);

        // DreamSettings ignores the button, but we need something to pass into onCheckedChanged.
        final CompoundButton mockButton = mock(CompoundButton.class);
        dreamSettings.onCheckedChanged(mockButton, true);
        verify(mLowLightModeTogglePref).setEnabled(true);
    }

    private DreamSettings prepareDreamSettings(Context context) {
        final TestDreamSettings dreamSettings = new TestDreamSettings(context);
        final Bundle extras = new Bundle();

        when(mDreamPickerController.getPreferenceKey()).thenReturn(DreamPickerController.PREF_KEY);
        when(mDreamHomeControlsPreferenceController.getPreferenceKey())
                .thenReturn(DreamHomeControlsPreferenceController.PREF_KEY);
        when(mDreamPickerPref.getExtras()).thenReturn(new Bundle());
        when(mDreamPickerPref.getExtras()).thenReturn(extras);
        when(mDreamPickerPref.getKey()).thenReturn(DreamPickerController.PREF_KEY);
        when(mComplicationsTogglePref.getKey()).thenReturn(
                DreamComplicationPreferenceController.PREF_KEY);
        when(mHomeControllerTogglePref.getExtras()).thenReturn(new Bundle());
        when(mHomeControllerTogglePref.getExtras()).thenReturn(extras);
        when(mHomeControllerTogglePref.getKey()).thenReturn(
                DreamHomeControlsPreferenceController.PREF_KEY);
        when(mDreamHomeControlsPreferenceController.getAvailabilityStatus())
                .thenReturn(mDreamHomeControlsPreferenceController.AVAILABLE);
        when(mLowLightModeTogglePref.getExtras()).thenReturn(extras);
        when(mLowLightModeTogglePref.getKey())
                .thenReturn(LowLightModePreferenceController.PREF_KEY);
        when(mLowLightModePreferenceController.getPreferenceKey())
                .thenReturn(LowLightModePreferenceController.PREF_KEY);
        dreamSettings.addPreference(
                DreamMainSwitchPreferenceController.MAIN_SWITCH_PREF_KEY, mMainSwitchPreference);
        dreamSettings.addPreference(DreamPickerController.PREF_KEY, mDreamPickerPref);
        dreamSettings.addPreference(DreamComplicationPreferenceController.PREF_KEY,
                mComplicationsTogglePref);
        dreamSettings.addPreference(DreamHomeControlsPreferenceController.PREF_KEY,
                mHomeControllerTogglePref);
        dreamSettings.addPreference(LowLightModePreferenceController.PREF_KEY,
                mLowLightModeTogglePref);
        dreamSettings.setDreamPickerController(mDreamPickerController);
        dreamSettings
                .setDreamHomeControlsPreferenceController(mDreamHomeControlsPreferenceController);
        dreamSettings.setLowLightModePreferenceController(mLowLightModePreferenceController);

        return dreamSettings;
    }
Loading