diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 0816e8433e667..e9f10c190c0a4 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -1304,6 +1304,11 @@ public final class SurfaceControl implements Parcelable { * @hide */ public static final class DisplayConfig { + /** + * Invalid display config id. + */ + public static final int INVALID_DISPLAY_CONFIG_ID = -1; + public int width; public int height; public float xDpi; @@ -1313,6 +1318,14 @@ public final class SurfaceControl implements Parcelable { public long appVsyncOffsetNanos; public long presentationDeadlineNanos; + /** + * The config group ID this config is associated to. + * Configs in the same group are similar from vendor's perspective and switching between + * configs within the same group can be done seamlessly in most cases. + * @see: android.hardware.graphics.composer@2.4::IComposerClient::Attribute::CONFIG_GROUP + */ + public int configGroup; + @Override public String toString() { return "DisplayConfig{width=" + width @@ -1321,7 +1334,8 @@ public final class SurfaceControl implements Parcelable { + ", yDpi=" + yDpi + ", refreshRate=" + refreshRate + ", appVsyncOffsetNanos=" + appVsyncOffsetNanos - + ", presentationDeadlineNanos=" + presentationDeadlineNanos + "}"; + + ", presentationDeadlineNanos=" + presentationDeadlineNanos + + ", configGroup=" + configGroup + "}"; } } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index a9ef257359c27..b2ca0a7bcbe3d 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -91,6 +91,7 @@ static struct { jfieldID refreshRate; jfieldID appVsyncOffsetNanos; jfieldID presentationDeadlineNanos; + jfieldID configGroup; } gDisplayConfigClassInfo; static struct { @@ -874,6 +875,7 @@ static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz, jobject t config.appVsyncOffset); env->SetLongField(object, gDisplayConfigClassInfo.presentationDeadlineNanos, config.presentationDeadline); + env->SetIntField(object, gDisplayConfigClassInfo.configGroup, config.configGroup); env->SetObjectArrayElement(configArray, static_cast(c), object); env->DeleteLocalRef(object); } @@ -1614,6 +1616,7 @@ int register_android_view_SurfaceControl(JNIEnv* env) GetFieldIDOrDie(env, configClazz, "appVsyncOffsetNanos", "J"); gDisplayConfigClassInfo.presentationDeadlineNanos = GetFieldIDOrDie(env, configClazz, "presentationDeadlineNanos", "J"); + gDisplayConfigClassInfo.configGroup = GetFieldIDOrDie(env, configClazz, "configGroup", "I"); jclass rectClazz = FindClassOrDie(env, "android/graphics/Rect"); gRectClassInfo.bottom = GetFieldIDOrDie(env, rectClazz, "bottom", "I"); diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index e578ac1fcd42b..05a757bde1791 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -181,6 +181,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { private int mState = Display.STATE_UNKNOWN; private float mBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT; private int mDefaultModeId; + private int mDefaultConfigGroup; private int mActiveModeId; private boolean mActiveModeInvalid; private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs = @@ -332,15 +333,18 @@ final class LocalDisplayAdapter extends DisplayAdapter { // For a new display, we need to initialize the default mode ID. if (mDefaultModeId == NO_DISPLAY_MODE_ID) { mDefaultModeId = activeRecord.mMode.getModeId(); + mDefaultConfigGroup = configs[activeConfigId].configGroup; } else if (modesAdded && mActiveModeId != activeRecord.mMode.getModeId()) { Slog.d(TAG, "New display modes are added and the active mode has changed, " + "use active mode as default mode."); mActiveModeId = activeRecord.mMode.getModeId(); mDefaultModeId = activeRecord.mMode.getModeId(); - } else if (findDisplayConfigIdLocked(mDefaultModeId) < 0) { + mDefaultConfigGroup = configs[activeConfigId].configGroup; + } else if (findDisplayConfigIdLocked(mDefaultModeId, mDefaultConfigGroup) < 0) { Slog.w(TAG, "Default display mode no longer available, using currently" + " active mode as default."); mDefaultModeId = activeRecord.mMode.getModeId(); + mDefaultConfigGroup = configs[activeConfigId].configGroup; } // Determine whether the display mode specs' base mode is still there. @@ -754,7 +758,16 @@ final class LocalDisplayAdapter extends DisplayAdapter { // a valid mode. return; } - int baseConfigId = findDisplayConfigIdLocked(displayModeSpecs.baseModeId); + + // Find the config Id based on the desired mode specs. In case there is more than one + // config matching the mode spec, prefer the one that is in the default config group. + // For now the default config group is taken from the active config when we got the + // hotplug event for the display. In the future we might want to change the default + // config based on vendor requirements. + // Note: We prefer the default config group over the current one as this is the config + // group the vendor prefers. + int baseConfigId = findDisplayConfigIdLocked(displayModeSpecs.baseModeId, + mDefaultConfigGroup); if (baseConfigId < 0) { // When a display is hotplugged, it's possible for a mode to be removed that was // previously valid. Because of the way display changes are propagated through the @@ -906,17 +919,26 @@ final class LocalDisplayAdapter extends DisplayAdapter { pw.print("mSupportedColorModes=" + mSupportedColorModes.toString()); } - private int findDisplayConfigIdLocked(int modeId) { + private int findDisplayConfigIdLocked(int modeId, int configGroup) { + int matchingConfigId = SurfaceControl.DisplayConfig.INVALID_DISPLAY_CONFIG_ID; DisplayModeRecord record = mSupportedModes.get(modeId); if (record != null) { for (int i = 0; i < mDisplayConfigs.length; i++) { SurfaceControl.DisplayConfig config = mDisplayConfigs[i]; if (record.hasMatchingMode(config)) { - return i; + if (matchingConfigId + == SurfaceControl.DisplayConfig.INVALID_DISPLAY_CONFIG_ID) { + matchingConfigId = i; + } + + // Prefer to return a config that matches the configGroup + if (config.configGroup == configGroup) { + return i; + } } } } - return -1; + return matchingConfigId; } private int findMatchingModeIdLocked(int configId) {