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

Commit c98fd483 authored by Jason Hsu's avatar Jason Hsu Committed by Android (Google) Code Review
Browse files

Merge "Flash Notifications color dialog crashs if configuration changes" into main

parents f56a1bcc e08c1a5f
Loading
Loading
Loading
Loading
+14 −9
Original line number Diff line number Diff line
@@ -28,11 +28,13 @@ import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.view.View;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;

@@ -40,8 +42,6 @@ import com.android.settings.R;

import java.util.Timer;
import java.util.TimerTask;
import java.util.function.Consumer;


/**
 * DialogFragment for Screen flash notification color picker.
@@ -49,29 +49,33 @@ import java.util.function.Consumer;
public class ScreenFlashNotificationColorDialogFragment extends DialogFragment implements
        ColorSelectorLayout.OnCheckedChangeListener {

    private static final int DEFAULT_COLOR = Color.TRANSPARENT;
    private static final int PREVIEW_LONG_TIME_MS = 5000;
    private static final int BETWEEN_STOP_AND_START_DELAY_MS = 250;
    private static final int MARGIN_FOR_STOP_DELAY_MS = 100;

    @VisibleForTesting
    static final String EXTRA_COLOR = "extra_color";
    @ColorInt
    private int mCurrentColor = Color.TRANSPARENT;
    private Consumer<Integer> mConsumer;
    private int mCurrentColor = DEFAULT_COLOR;

    private Timer mTimer = null;
    private Boolean mIsPreview = false;

    static ScreenFlashNotificationColorDialogFragment getInstance(int initialColor,
            Consumer<Integer> colorConsumer) {
    static ScreenFlashNotificationColorDialogFragment getInstance(int initialColor) {
        final ScreenFlashNotificationColorDialogFragment result =
                new ScreenFlashNotificationColorDialogFragment();
        result.mCurrentColor = initialColor;
        result.mConsumer = colorConsumer != null ? colorConsumer : i -> {};
        Bundle bundle = new Bundle();
        bundle.putInt(EXTRA_COLOR, initialColor);
        result.setArguments(bundle);
        return result;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        mCurrentColor = getArguments().getInt(EXTRA_COLOR, DEFAULT_COLOR);

        final View dialogView = getLayoutInflater().inflate(R.layout.layout_color_selector_dialog,
                null);

@@ -90,7 +94,8 @@ public class ScreenFlashNotificationColorDialogFragment extends DialogFragment i
                })
                .setPositiveButton(R.string.color_selector_dialog_save, (dialog, which) -> {
                    mCurrentColor = colorSelectorLayout.getCheckedColor(DEFAULT_SCREEN_FLASH_COLOR);
                    mConsumer.accept(mCurrentColor);
                    Settings.System.putInt(getContext().getContentResolver(),
                            Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, mCurrentColor);
                })
                .create();
        createdDialog.setOnShowListener(
+57 −10
Original line number Diff line number Diff line
@@ -21,10 +21,17 @@ import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import static com.android.settings.accessibility.FlashNotificationsUtil.DEFAULT_SCREEN_FLASH_COLOR;

import android.content.Context;
import android.database.ContentObserver;
import android.graphics.Color;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

@@ -32,24 +39,37 @@ import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.overlay.FeatureFactory;

import java.util.function.Consumer;

/**
 * Controller for Screen flash notification.
 */
public class ScreenFlashNotificationPreferenceController extends TogglePreferenceController {
public class ScreenFlashNotificationPreferenceController extends
        TogglePreferenceController implements DefaultLifecycleObserver {

    private final FlashNotificationColorContentObserver mFlashNotificationColorContentObserver;

    private Fragment mParentFragment;
    private Preference mPreference;

    public ScreenFlashNotificationPreferenceController(Context context, String preferenceKey) {
        super(context, preferenceKey);
        mFlashNotificationColorContentObserver = new FlashNotificationColorContentObserver(
                new Handler(mContext.getMainLooper()));
    }

    public void setParentFragment(Fragment parentFragment) {
        this.mParentFragment = parentFragment;
    }

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        mFlashNotificationColorContentObserver.register(mContext);
    }

    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        mFlashNotificationColorContentObserver.unregister(mContext);
    }

    @Override
    public int getAvailabilityStatus() {
        return AVAILABLE;
@@ -100,14 +120,8 @@ public class ScreenFlashNotificationPreferenceController extends TogglePreferenc
                    Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR,
                    DEFAULT_SCREEN_FLASH_COLOR);

            final Consumer<Integer> consumer = color -> {
                Settings.System.putInt(mContext.getContentResolver(),
                        Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, color);
                refreshColorSummary();
            };

            ScreenFlashNotificationColorDialogFragment
                    .getInstance(initialColor, consumer)
                    .getInstance(initialColor)
                    .show(mParentFragment.getParentFragmentManager(),
                            ScreenFlashNotificationColorDialogFragment.class.getSimpleName());
            return true;
@@ -128,4 +142,37 @@ public class ScreenFlashNotificationPreferenceController extends TogglePreferenc
    private void refreshColorSummary() {
        if (mPreference != null) mPreference.setSummary(getSummary());
    }

    private final class FlashNotificationColorContentObserver extends ContentObserver {
        private final Uri mColorUri = Settings.System.getUriFor(
                Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR);

        FlashNotificationColorContentObserver(Handler handler) {
            super(handler);
        }

        /**
         * Register this observer to given {@link Context}, to be called from lifecycle
         * {@code onStart} method.
         */
        public void register(@NonNull Context context) {
            context.getContentResolver().registerContentObserver(
                    mColorUri, /* notifyForDescendants= */ false, this);
        }

        /**
         * Unregister this observer from given {@link Context}, to be called from lifecycle
         * {@code onStop} method.
         */
        public void unregister(@NonNull Context context) {
            context.getContentResolver().unregisterContentObserver(this);
        }

        @Override
        public void onChange(boolean selfChange, @Nullable Uri uri) {
            if (mColorUri.equals(uri)) {
                refreshColorSummary();
            }
        }
    }
}
+21 −14
Original line number Diff line number Diff line
@@ -37,10 +37,13 @@ import static org.robolectric.Shadows.shadowOf;

import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.provider.Settings;

import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.testing.FragmentScenario;
import androidx.lifecycle.Lifecycle;
import androidx.test.core.app.ApplicationProvider;

import com.android.settings.R;
import com.android.settings.testutils.FakeTimer;
@@ -56,23 +59,26 @@ import org.robolectric.util.ReflectionHelpers;

import java.util.List;
import java.util.Timer;
import java.util.function.Consumer;

@RunWith(RobolectricTestRunner.class)
public class ScreenFlashNotificationColorDialogFragmentTest {

    private static final int DEFAULT_COLOR = ROSE.mColorInt;

    private FragmentScenario<TestScreenFlashNotificationColorDialogFragment> mFragmentScenario;
    private ScreenFlashNotificationColorDialogFragment mDialogFragment;
    private AlertDialog mAlertDialog;
    private ColorSelectorLayout mColorSelectorLayout;
    private int mCurrentColor;

    @Before
    public void setUp() {
        mCurrentColor = ROSE.mColorInt;
        Settings.System.putInt(ApplicationProvider.getApplicationContext().getContentResolver(),
                Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, DEFAULT_COLOR);
        Bundle fragmentArgs = new Bundle();
        fragmentArgs.putInt(ScreenFlashNotificationColorDialogFragment.EXTRA_COLOR, DEFAULT_COLOR);
        mFragmentScenario = FragmentScenario.launch(
                TestScreenFlashNotificationColorDialogFragment.class,
                /* fragmentArgs= */ null,
                fragmentArgs,
                R.style.Theme_AlertDialog_SettingsLib,
                Lifecycle.State.INITIALIZED);
        setupFragment();
@@ -99,7 +105,7 @@ public class ScreenFlashNotificationColorDialogFragmentTest {
        performClickOnDialog(BUTTON_NEUTRAL);
        getTimerFromFragment().runOneTask();

        assertStartPreview(ROSE.mColorInt);
        assertStartPreview(DEFAULT_COLOR);
    }

    @Test
@@ -168,20 +174,26 @@ public class ScreenFlashNotificationColorDialogFragmentTest {
    }

    @Test
    public void clickColorAndClickNegative_assertColor() {
    public void clickColorAndClickNegative_assertDefaultColor() {
        checkColorButton(AZURE);
        performClickOnDialog(BUTTON_NEGATIVE);

        assertThat(getTimerFromFragment()).isNull();
        assertThat(mCurrentColor).isEqualTo(ROSE.mColorInt);
        assertThat(Settings.System.getInt(
                ApplicationProvider.getApplicationContext().getContentResolver(),
                Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, AZURE.mColorInt)).isEqualTo(
                DEFAULT_COLOR);
    }

    @Test
    public void clickColorAndClickPositive_assertColor() {
    public void clickColorAndClickPositive_assertSameColor() {
        checkColorButton(BLUE);
        performClickOnDialog(BUTTON_POSITIVE);

        assertThat(mCurrentColor).isEqualTo(BLUE.mColorInt);
        assertThat(Settings.System.getInt(
                ApplicationProvider.getApplicationContext().getContentResolver(),
                Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, DEFAULT_COLOR)).isEqualTo(
                BLUE.mColorInt);
    }

    private void checkColorButton(ScreenFlashNotificationColor color) {
@@ -201,11 +213,6 @@ public class ScreenFlashNotificationColorDialogFragmentTest {
    }

    private void setupFragment() {
        mFragmentScenario.onFragment(fragment -> {
            ReflectionHelpers.setField(fragment, "mCurrentColor", mCurrentColor);
            ReflectionHelpers.setField(fragment, "mConsumer",
                    (Consumer<Integer>) selectedColor -> mCurrentColor = selectedColor);
        });
        mFragmentScenario.moveToState(Lifecycle.State.RESUMED);

        mFragmentScenario.onFragment(fragment -> {
+5 −5
Original line number Diff line number Diff line
@@ -57,8 +57,6 @@ import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;

import java.util.function.Consumer;

@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
        ScreenFlashNotificationPreferenceControllerTest
@@ -83,7 +81,6 @@ public class ScreenFlashNotificationPreferenceControllerTest {
    private FragmentManager mFragmentManager;
    @Mock
    private ScreenFlashNotificationColorDialogFragment mDialogFragment;

    private ScreenFlashNotificationPreferenceController mController;
    private ContentResolver mContentResolver;

@@ -92,6 +89,7 @@ public class ScreenFlashNotificationPreferenceControllerTest {
        MockitoAnnotations.initMocks(this);
        FragmentActivity fragmentActivity = Robolectric.setupActivity(FragmentActivity.class);
        Context context = fragmentActivity.getApplicationContext();

        ShadowScreenFlashNotificationColorDialogFragment.setInstance(mDialogFragment);
        ShadowFlashNotificationsUtils.setColorDescriptionText(COLOR_DESCRIPTION_TEXT);

@@ -99,8 +97,9 @@ public class ScreenFlashNotificationPreferenceControllerTest {
        mController = new ScreenFlashNotificationPreferenceController(context, PREFERENCE_KEY);
        when(mPreferenceScreen.findPreference(PREFERENCE_KEY)).thenReturn(mPreference);
        when(mPreference.getKey()).thenReturn(PREFERENCE_KEY);
        mController.setParentFragment(mParentFragment);
        when(mParentFragment.getParentFragmentManager()).thenReturn(mFragmentManager);

        mController.setParentFragment(mParentFragment);
    }

    @After
@@ -181,6 +180,7 @@ public class ScreenFlashNotificationPreferenceControllerTest {
    @Test
    public void handlePreferenceTreeClick() {
        mController.handlePreferenceTreeClick(mPreference);

        verify(mDialogFragment).show(any(FragmentManager.class), anyString());
    }

@@ -194,7 +194,7 @@ public class ScreenFlashNotificationPreferenceControllerTest {

        @Implementation
        protected static ScreenFlashNotificationColorDialogFragment getInstance(
                int initialColor, Consumer<Integer> colorConsumer) {
                int initialColor) {
            return sInstance;
        }