Display: make Colors settings entry preference reactive

Added `display_color_mode` listener to Colors preference. As a result,
it becomes reactive and updates its color mode value summary.

Flag: EXEMPT minor change
Bug: 397659800
Test: changed color mode using `adb` commands and verify that Colors
summary reacts and print correct color mode

Change-Id: I963768e3dbb43b547ec53e6445b2791ec0f57cff
This commit is contained in:
Vadym Omelnytskyi
2025-02-20 01:49:48 +00:00
parent a8f1da6994
commit cc96950d12
2 changed files with 102 additions and 3 deletions

View File

@@ -14,15 +14,37 @@
package com.android.settings.display; package com.android.settings.display;
import android.content.Context; import android.content.Context;
import android.database.ContentObserver;
import android.hardware.display.ColorDisplayManager; import android.hardware.display.ColorDisplayManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
public class ColorModePreferenceController extends BasePreferenceController { public class ColorModePreferenceController extends BasePreferenceController
implements LifecycleObserver {
private Preference mPreference;
private final ContentObserver mContentObserver = new ContentObserver(
new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange, @Nullable Uri uri) {
if (mPreference != null) {
updateState(mPreference);
}
}
};
public ColorModePreferenceController(@NonNull Context context, @NonNull String key) { public ColorModePreferenceController(@NonNull Context context, @NonNull String key) {
super(context, key); super(context, key);
@@ -36,11 +58,32 @@ public class ColorModePreferenceController extends BasePreferenceController {
AVAILABLE : DISABLED_FOR_USER; AVAILABLE : DISABLED_FOR_USER;
} }
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.DISPLAY_COLOR_MODE),
/* notifyForDescendants= */ false,
mContentObserver);
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
mContext.getContentResolver().unregisterContentObserver(mContentObserver);
}
@Override @Override
public CharSequence getSummary() { public CharSequence getSummary() {
return getColorModeName(); return getColorModeName();
} }
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
if (mPreference != null) {
updateState(mPreference);
}
}
@Override @Override
public void updateState(@Nullable Preference preference) { public void updateState(@Nullable Preference preference) {
if (preference == null) { if (preference == null) {

View File

@@ -15,10 +15,15 @@
*/ */
package com.android.settings.display package com.android.settings.display
import android.content.ContentResolver
import android.content.Context import android.content.Context
import android.database.ContentObserver
import android.hardware.display.ColorDisplayManager import android.hardware.display.ColorDisplayManager
import android.provider.Settings
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceScreen
import androidx.preference.PreferenceManager
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import com.android.settingslib.testutils.shadow.ShadowColorDisplayManager import com.android.settingslib.testutils.shadow.ShadowColorDisplayManager
@@ -31,22 +36,34 @@ import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config import org.robolectric.annotation.Config
import org.robolectric.shadow.api.Shadow import org.robolectric.shadow.api.Shadow
import org.robolectric.shadows.ShadowContentResolver
@RunWith(RobolectricTestRunner::class) @RunWith(RobolectricTestRunner::class)
@Config(shadows = [ShadowColorDisplayManager::class]) @Config(shadows = [ShadowColorDisplayManager::class, ShadowContentResolver::class])
class ColorModePreferenceControllerTest { class ColorModePreferenceControllerTest {
private lateinit var context: Context private lateinit var context: Context
private lateinit var preference: Preference private lateinit var preference: Preference
private lateinit var controller: ColorModePreferenceController private lateinit var controller: ColorModePreferenceController
private lateinit var shadowColorDisplayManager: ShadowColorDisplayManager private lateinit var shadowColorDisplayManager: ShadowColorDisplayManager
private lateinit var shadowContentResolver: ShadowContentResolver
@Before @Before
fun setup() { fun setup() {
context = ApplicationProvider.getApplicationContext() context = ApplicationProvider.getApplicationContext()
controller = ColorModePreferenceController(context, "test") controller = ColorModePreferenceController(context, "test")
preference = Preference(context) preference = Preference(context)
val preferenceManager = PreferenceManager(context)
val preferenceScreen = preferenceManager.createPreferenceScreen(context)
preference.setKey(controller.getPreferenceKey());
preferenceScreen.addPreference(preference)
shadowColorDisplayManager = Shadow.extract( shadowColorDisplayManager = Shadow.extract(
context.getSystemService(ColorDisplayManager::class.java)); context.getSystemService(ColorDisplayManager::class.java))
val contentResolver = context.getContentResolver();
shadowContentResolver = Shadow.extract(contentResolver)
controller.displayPreference(preferenceScreen)
} }
@Test @Test
@@ -80,4 +97,43 @@ class ColorModePreferenceControllerTest {
val naturalColorModeName = context.getString(R.string.color_mode_option_natural) val naturalColorModeName = context.getString(R.string.color_mode_option_natural)
assertThat(preference.summary.toString()).isEqualTo(naturalColorModeName) assertThat(preference.summary.toString()).isEqualTo(naturalColorModeName)
} }
@Test
fun onResume_verifyRegisterColorModeObserver() {
controller.onResume()
assertThat(shadowContentResolver.getContentObservers(
Settings.System.getUriFor(Settings.System.DISPLAY_COLOR_MODE)))
.hasSize(1)
}
@Test
fun onPause_verifyUnregisterColorModeObserver() {
controller.onResume()
controller.onPause()
assertThat(shadowContentResolver.getContentObservers(
Settings.System.getUriFor(Settings.System.DISPLAY_COLOR_MODE)))
.isEmpty()
}
@Test
fun contentObserver_onChange_updatesPreferenceSummary() {
controller.onResume()
assertThat(shadowContentResolver.getContentObservers(
Settings.System.getUriFor(Settings.System.DISPLAY_COLOR_MODE)))
.hasSize(1)
shadowColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL)
triggerOnChangeListener()
assertThat(preference.summary).isEqualTo(context.getString(R.string.color_mode_option_natural))
shadowColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC)
triggerOnChangeListener()
assertThat(preference.summary).isEqualTo(context.getString(R.string.color_mode_option_automatic))
}
private fun triggerOnChangeListener() {
shadowContentResolver.getContentObservers(
Settings.System.getUriFor(Settings.System.DISPLAY_COLOR_MODE))
.forEach {it.onChange(false, null)};
}
} }