summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/display/feature/DisplayManagerFlags.java10
-rw-r--r--services/core/java/com/android/server/display/feature/display_flags.aconfig8
-rw-r--r--services/core/java/com/android/server/display/plugin/PluginManager.java30
-rw-r--r--services/core/java/com/android/server/display/plugin/PluginStorage.java23
-rw-r--r--services/core/java/com/android/server/display/plugin/PluginType.java10
-rw-r--r--services/core/java/com/android/server/display/plugin/PluginsProvider.java4
-rw-r--r--services/core/java/com/android/server/display/plugin/types/HdrBoostOverride.java59
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/plugin/PluginManagerTest.kt8
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/plugin/PluginStorageTest.kt14
9 files changed, 153 insertions, 13 deletions
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index b9ce8c93dbde..373287d76442 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -245,6 +245,12 @@ public class DisplayManagerFlags {
Flags.FLAG_ENABLE_PLUGIN_MANAGER,
Flags::enablePluginManager
);
+
+ private final FlagState mEnableHdrOverridePluginTypeFlagState = new FlagState(
+ Flags.FLAG_ENABLE_HDR_OVERRIDE_PLUGIN_TYPE,
+ Flags::enableHdrOverridePluginType
+ );
+
private final FlagState mDisplayListenerPerformanceImprovementsFlagState = new FlagState(
Flags.FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS,
Flags::displayListenerPerformanceImprovements
@@ -550,6 +556,10 @@ public class DisplayManagerFlags {
return mEnablePluginManagerFlagState.isEnabled();
}
+ public boolean isHdrOverrideEnabled() {
+ return mEnableHdrOverridePluginTypeFlagState.isEnabled();
+ }
+
/**
* @return {@code true} if the flag for display listener performance improvements is enabled
*/
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index 63cd2d73336a..bbd0e41e9af7 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -454,6 +454,14 @@ flag {
}
flag {
+ name: "enable_hdr_override_plugin_type"
+ namespace: "display_manager"
+ description: "Enable hdr override plugin type"
+ bug: "389873155"
+ is_fixed_read_only: true
+}
+
+flag {
name: "enable_display_content_mode_management"
namespace: "lse_desktop_experience"
description: "Enable switching the content mode of connected displays between mirroring and extened. Also change the default content mode to extended mode."
diff --git a/services/core/java/com/android/server/display/plugin/PluginManager.java b/services/core/java/com/android/server/display/plugin/PluginManager.java
index cb0a4574361a..a8c4e7eaeb66 100644
--- a/services/core/java/com/android/server/display/plugin/PluginManager.java
+++ b/services/core/java/com/android/server/display/plugin/PluginManager.java
@@ -30,7 +30,9 @@ import dalvik.system.PathClassLoader;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Responsible for loading Plugins. Plugins and PluginSupplier are loaded from
@@ -43,7 +45,6 @@ public class PluginManager {
"com.android.server.display.plugin.PluginsProviderImpl";
private static final String TAG = "PluginManager";
- private final DisplayManagerFlags mFlags;
private final PluginStorage mPluginStorage;
private final List<Plugin> mPlugins;
@@ -53,10 +54,11 @@ public class PluginManager {
@VisibleForTesting
PluginManager(Context context, DisplayManagerFlags flags, Injector injector) {
- mFlags = flags;
- mPluginStorage = injector.getPluginStorage();
- if (mFlags.isPluginManagerEnabled()) {
- mPlugins = Collections.unmodifiableList(injector.loadPlugins(context, mPluginStorage));
+ Set<PluginType<?>> enabledTypes = injector.getEnabledPluginTypes(flags);
+ mPluginStorage = injector.getPluginStorage(enabledTypes);
+ if (flags.isPluginManagerEnabled()) {
+ mPlugins = Collections.unmodifiableList(injector.loadPlugins(
+ context, mPluginStorage, enabledTypes));
Slog.d(TAG, "loaded Plugins:" + mPlugins);
} else {
mPlugins = List.of();
@@ -110,11 +112,21 @@ public class PluginManager {
}
static class Injector {
- PluginStorage getPluginStorage() {
- return new PluginStorage();
+
+ Set<PluginType<?>> getEnabledPluginTypes(DisplayManagerFlags flags) {
+ Set<PluginType<?>> enabledTypes = new HashSet<>();
+ if (flags.isHdrOverrideEnabled()) {
+ enabledTypes.add(PluginType.HDR_BOOST_OVERRIDE);
+ }
+ return enabledTypes;
+ }
+
+ PluginStorage getPluginStorage(Set<PluginType<?>> enabledTypes) {
+ return new PluginStorage(enabledTypes);
}
- List<Plugin> loadPlugins(Context context, PluginStorage storage) {
+ List<Plugin> loadPlugins(Context context, PluginStorage storage,
+ Set<PluginType<?>> enabledTypes) {
String providerJarPath = context
.getString(com.android.internal.R.string.config_pluginsProviderJarPath);
Slog.d(TAG, "loading plugins from:" + providerJarPath);
@@ -129,7 +141,7 @@ public class PluginManager {
Class<? extends PluginsProvider> cp = pathClassLoader.loadClass(PROVIDER_IMPL_CLASS)
.asSubclass(PluginsProvider.class);
PluginsProvider provider = cp.getDeclaredConstructor().newInstance();
- return provider.getPlugins(context, storage);
+ return provider.getPlugins(context, storage, enabledTypes);
} catch (ClassNotFoundException e) {
Slog.e(TAG, "loading failed: " + PROVIDER_IMPL_CLASS + " is not found in"
+ providerJarPath, e);
diff --git a/services/core/java/com/android/server/display/plugin/PluginStorage.java b/services/core/java/com/android/server/display/plugin/PluginStorage.java
index 5102c2709329..d17fbe21deeb 100644
--- a/services/core/java/com/android/server/display/plugin/PluginStorage.java
+++ b/services/core/java/com/android/server/display/plugin/PluginStorage.java
@@ -24,6 +24,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import java.io.PrintWriter;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -62,6 +63,12 @@ public class PluginStorage {
updateValue(type, GLOBAL_ID, value);
}
+ private final Set<PluginType<?>> mEnabledTypes;
+
+ PluginStorage(Set<PluginType<?>> enabledTypes) {
+ mEnabledTypes = Collections.unmodifiableSet(enabledTypes);
+ }
+
/**
* Updates value in storage and forwards it to corresponding listeners for specific display.
* Should be called by OEM Plugin implementation in order to communicate with Framework
@@ -71,6 +78,10 @@ public class PluginStorage {
*/
@KeepForApi
public <T> void updateValue(PluginType<T> type, String uniqueDisplayId, @Nullable T value) {
+ if (isTypeDisabled(type)) {
+ Slog.d(TAG, "updateValue ignored for disabled type=" + type.mName);
+ return;
+ }
Slog.d(TAG, "updateValue, type=" + type.mName + "; value=" + value
+ "; displayId=" + uniqueDisplayId);
Set<PluginManager.PluginChangeListener<T>> localListeners;
@@ -119,6 +130,10 @@ public class PluginStorage {
*/
<T> void addListener(PluginType<T> type, String uniqueDisplayId,
PluginManager.PluginChangeListener<T> listener) {
+ if (isTypeDisabled(type)) {
+ Slog.d(TAG, "addListener ignored for disabled type=" + type.mName);
+ return;
+ }
if (GLOBAL_ID.equals(uniqueDisplayId)) {
Slog.d(TAG, "addListener ignored for GLOBAL_ID, type=" + type.mName);
return;
@@ -141,6 +156,10 @@ public class PluginStorage {
*/
<T> void removeListener(PluginType<T> type, String uniqueDisplayId,
PluginManager.PluginChangeListener<T> listener) {
+ if (isTypeDisabled(type)) {
+ Slog.d(TAG, "removeListener ignored for disabled type=" + type.mName);
+ return;
+ }
if (GLOBAL_ID.equals(uniqueDisplayId)) {
Slog.d(TAG, "removeListener ignored for GLOBAL_ID, type=" + type.mName);
return;
@@ -183,6 +202,10 @@ public class PluginStorage {
}
}
+ private boolean isTypeDisabled(PluginType<?> type) {
+ return !mEnabledTypes.contains(type);
+ }
+
@GuardedBy("mLock")
@SuppressWarnings("unchecked")
private <T> ListenersContainer<T> getListenersContainerLocked(PluginType<T> type) {
diff --git a/services/core/java/com/android/server/display/plugin/PluginType.java b/services/core/java/com/android/server/display/plugin/PluginType.java
index fb60833d259e..e4d2f854ea48 100644
--- a/services/core/java/com/android/server/display/plugin/PluginType.java
+++ b/services/core/java/com/android/server/display/plugin/PluginType.java
@@ -18,6 +18,7 @@ package com.android.server.display.plugin;
import com.android.internal.annotations.Keep;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.plugin.types.HdrBoostOverride;
/**
* Represent customisation entry point to Framework. OEM and Framework team should define
@@ -28,6 +29,15 @@ import com.android.internal.annotations.VisibleForTesting;
*/
@Keep
public class PluginType<T> {
+ /*
+ * PluginType for HDR boost override. If set, system will use overridden value instead
+ * system default parameters. To switch back to default system behaviour, Plugin should set
+ * this type value to null.
+ * Value change will trigger whole power state recalculation, so plugins should not update
+ * value for this type too often.
+ */
+ public static final PluginType<HdrBoostOverride> HDR_BOOST_OVERRIDE = new PluginType<>(
+ HdrBoostOverride.class, "hdr_boost_override");
final Class<T> mType;
final String mName;
diff --git a/services/core/java/com/android/server/display/plugin/PluginsProvider.java b/services/core/java/com/android/server/display/plugin/PluginsProvider.java
index 9ad85f67bc8b..ec74c860ca58 100644
--- a/services/core/java/com/android/server/display/plugin/PluginsProvider.java
+++ b/services/core/java/com/android/server/display/plugin/PluginsProvider.java
@@ -22,6 +22,7 @@ import android.content.Context;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import java.util.List;
+import java.util.Set;
/**
* Interface that OEMs should implement in order to supply Plugins to PluginManager
@@ -32,5 +33,6 @@ public interface PluginsProvider {
* Provides list of Plugins to PluginManager
*/
@NonNull
- List<Plugin> getPlugins(Context context, PluginStorage storage);
+ List<Plugin> getPlugins(
+ Context context, PluginStorage storage, Set<PluginType<?>> enabledTypes);
}
diff --git a/services/core/java/com/android/server/display/plugin/types/HdrBoostOverride.java b/services/core/java/com/android/server/display/plugin/types/HdrBoostOverride.java
new file mode 100644
index 000000000000..22e024da5f52
--- /dev/null
+++ b/services/core/java/com/android/server/display/plugin/types/HdrBoostOverride.java
@@ -0,0 +1,59 @@
+/*
+ * 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.server.display.plugin.types;
+
+import android.annotation.FloatRange;
+import android.os.PowerManager;
+
+import com.android.server.display.DisplayBrightnessState;
+
+/**
+ * HDR boost override value.
+ * @param sdrHdrRatio - HDR to SDR multiplier, if < 1 HDR boost is off.
+ * @param maxHdrBrightness - Brightness max when boosted. Value in range from BRIGHTNESS_MIN to
+ * BRIGHTNESS_MAX. If not used should be set to PowerManager.BRIGHTNESS_MAX
+ * @param customTransitionRate - Custom transition rate for transitioning to new HDR brightness.
+ * If not used should be set to
+ * DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET
+ */
+public record HdrBoostOverride(
+ @FloatRange(from = 0)
+ float sdrHdrRatio,
+ @FloatRange(from = PowerManager.BRIGHTNESS_MIN, to = PowerManager.BRIGHTNESS_MAX)
+ float maxHdrBrightness,
+ float customTransitionRate) {
+ /**
+ * Constant for HDR boost off. Plugins should use this constant instead of creating new objects
+ */
+ private static final HdrBoostOverride HDR_OFF = new HdrBoostOverride(0,
+ PowerManager.BRIGHTNESS_MAX, DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET);
+
+ /**
+ * Create HdrBoostOverride for HDR boost off
+ */
+ public static HdrBoostOverride forHdrOff() {
+ return HDR_OFF;
+ }
+
+ /**
+ * Create HdrBoostOverride for sdr-hdr ration override
+ */
+ public static HdrBoostOverride forSdrHdrRatio(float sdrHdrRatio) {
+ return new HdrBoostOverride(sdrHdrRatio,
+ PowerManager.BRIGHTNESS_MAX, DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET);
+ }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginManagerTest.kt b/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginManagerTest.kt
index d9224eaf66ca..0466e7572c2e 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginManagerTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginManagerTest.kt
@@ -87,11 +87,15 @@ class PluginManagerTest {
val mockPlugin1 = mock<Plugin>()
val mockPlugin2 = mock<Plugin>()
- override fun getPluginStorage(): PluginStorage {
+ override fun getPluginStorage(enabledTypes: Set<PluginType<*>>): PluginStorage {
return mockStorage
}
- override fun loadPlugins(context: Context?, storage: PluginStorage?): List<Plugin> {
+ override fun loadPlugins(
+ context: Context?,
+ storage: PluginStorage?,
+ enabledTypes: Set<PluginType<*>>
+ ): List<Plugin> {
return listOf(mockPlugin1, mockPlugin2)
}
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginStorageTest.kt b/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginStorageTest.kt
index 8eb3e9fbf9b0..2b06126588d6 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginStorageTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/plugin/PluginStorageTest.kt
@@ -29,7 +29,7 @@ private val DISPLAY_ID_2 = "display_2"
@SmallTest
class PluginStorageTest {
- val storage = PluginStorage()
+ var storage = PluginStorage(setOf(TEST_PLUGIN_TYPE1, TEST_PLUGIN_TYPE2))
@Test
fun testUpdateValue() {
@@ -93,6 +93,18 @@ class PluginStorageTest {
}
@Test
+ fun testDisabledPluginType() {
+ storage = PluginStorage(setOf(TEST_PLUGIN_TYPE2))
+ val type1Value = "value1"
+ val testChangeListener = TestPluginChangeListener<String>()
+ storage.updateValue(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, type1Value)
+
+ storage.addListener(TEST_PLUGIN_TYPE1, DISPLAY_ID_1, testChangeListener)
+
+ assertThat(testChangeListener.receivedValue).isNull()
+ }
+
+ @Test
fun testUpdateGlobal_noDisplaySpecificValue() {
val type1Value = "value1"
val testChangeListener1 = TestPluginChangeListener<String>()