diff --git a/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java b/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java index 5094154eb9b..2be843c21e8 100644 --- a/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java +++ b/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragment.java @@ -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 mConsumer; + private int mCurrentColor = DEFAULT_COLOR; private Timer mTimer = null; private Boolean mIsPreview = false; - static ScreenFlashNotificationColorDialogFragment getInstance(int initialColor, - Consumer 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( diff --git a/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceController.java b/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceController.java index bd54aca7d46..3ebcd1cbb01 100644 --- a/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceController.java +++ b/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceController.java @@ -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 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(); + } + } + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragmentTest.java index f3fa69dd208..ea48253653f 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationColorDialogFragmentTest.java @@ -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 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) selectedColor -> mCurrentColor = selectedColor); - }); mFragmentScenario.moveToState(Lifecycle.State.RESUMED); mFragmentScenario.onFragment(fragment -> { diff --git a/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceControllerTest.java index 95a9438b5ba..d7c1a0fe382 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ScreenFlashNotificationPreferenceControllerTest.java @@ -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 colorConsumer) { + int initialColor) { return sInstance; }