Support multiple display configs for default display, DO NOT MERGE ANYWHERE

Bug: 196986384

Test: run emulator with multiple display configs,
switch config using 'service call SurfaceFlinger 1035 i32 <configId>'

Change-Id: I18fb06763a04ead67999f93bf5bf538777f93b19
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index 74f64c8..8a243c2 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -138,6 +138,9 @@
 // DMA for readback
 static const char kReadColorBufferDma[] = "ANDROID_EMU_read_color_buffer_dma";
 
+// HWC multiple display configs
+static const char kHWCMultiConfigs[] = "ANDROID_EMU_hwc_multi_configs";
+
 // Struct describing available emulator features
 struct EmulatorFeatureInfo {
 
@@ -166,7 +169,8 @@
         hasVulkanBatchedDescriptorSetUpdate(false),
         hasSyncBufferData(false),
         hasVulkanAsyncQsri(false),
-        hasReadColorBufferDma(false)
+        hasReadColorBufferDma(false),
+        hasHWCMultiConfigs(false)
     { }
 
     SyncImpl syncImpl;
@@ -194,6 +198,7 @@
     bool hasSyncBufferData;
     bool hasVulkanAsyncQsri;
     bool hasReadColorBufferDma;
+    bool hasHWCMultiConfigs;
 };
 
 enum HostConnectionType {
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index 6fd3318..8399f2a 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -674,6 +674,7 @@
         queryAndSetSyncBufferData(rcEnc);
         queryAndSetVulkanAsyncQsri(rcEnc);
         queryAndSetReadColorBufferDma(rcEnc);
+        queryAndSetHWCMultiConfigs(rcEnc);
         queryVersion(rcEnc);
         if (m_processPipe) {
             m_processPipe->processPipeInit(m_connectionType, rcEnc);
@@ -987,6 +988,13 @@
     }
 }
 
+void HostConnection::queryAndSetHWCMultiConfigs(ExtendedRCEncoderContext* rcEnc) {
+    std::string glExtensions = queryGLExtensions(rcEnc);
+    if (glExtensions.find(kHWCMultiConfigs) != std::string::npos) {
+        rcEnc->featureInfo()->hasHWCMultiConfigs = true;
+    }
+}
+
 GLint HostConnection::queryVersion(ExtendedRCEncoderContext* rcEnc) {
     GLint version = m_rcEnc->rcGetRendererVersion(m_rcEnc.get());
     return version;
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index 0f7c351..6bec6ac 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -77,6 +77,9 @@
     }
     bool hasSyncBufferData() const {
         return m_featureInfo.hasSyncBufferData; }
+    bool hasHWCMultiConfigs() const {
+        return m_featureInfo.hasHWCMultiConfigs;
+    }
     DmaImpl getDmaVersion() const { return m_featureInfo.dmaImpl; }
     void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
     void bindDmaDirectly(void* dmaPtr, uint64_t dmaPhysAddr) {
@@ -246,6 +249,7 @@
     void queryAndSetSyncBufferData(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVulkanAsyncQsri(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetReadColorBufferDma(ExtendedRCEncoderContext *rcEnc);
+    void queryAndSetHWCMultiConfigs(ExtendedRCEncoderContext* rcEnc);
     GLint queryVersion(ExtendedRCEncoderContext* rcEnc);
 
 private:
diff --git a/system/hwc2/Composer.h b/system/hwc2/Composer.h
index eea4f56..b0c3248 100644
--- a/system/hwc2/Composer.h
+++ b/system/hwc2/Composer.h
@@ -54,6 +54,7 @@
   // to the display.
   virtual HWC2::Error presentDisplay(Display* display,
                                      int32_t* outPresentFence) = 0;
+  virtual HWC2::Error onActiveConfigChange(Display* display) = 0;
 };
 
 }  // namespace android
diff --git a/system/hwc2/Device.cpp b/system/hwc2/Device.cpp
index ab30026..1f06f43 100644
--- a/system/hwc2/Device.cpp
+++ b/system/hwc2/Device.cpp
@@ -97,18 +97,17 @@
     return HWC2::Error::NoResources;
   }
 
-  std::vector<DisplayConfig> displayConfigs;
+  std::vector<DisplayMultiConfigs> displays;
 
-  HWC2::Error error = findDisplayConfigs(&displayConfigs);
+  HWC2::Error error = findDisplays(displays);
   if (error != HWC2::Error::None) {
     ALOGE("%s failed to find display configs", __FUNCTION__);
     return error;
   }
 
-  for (const DisplayConfig& displayConfig : displayConfigs) {
-    error = createDisplay(displayConfig.id, displayConfig.width,
-                          displayConfig.height, displayConfig.dpiX,
-                          displayConfig.dpiY, displayConfig.refreshRateHz);
+  for (const auto& iter: displays) {
+
+    error = createDisplay(iter.configs, iter.activeConfigId);
     if (error != HWC2::Error::None) {
       ALOGE("%s failed to create display from config", __FUNCTION__);
       return error;
@@ -118,9 +117,8 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error Device::createDisplay(uint32_t displayId, uint32_t width,
-                                  uint32_t height, uint32_t dpiX, uint32_t dpiY,
-                                  uint32_t refreshRateHz) {
+HWC2::Error Device::createDisplay(const std::vector<DisplayConfig>& configs,
+                                  int activeConfig) {
   DEBUG_LOG("%s", __FUNCTION__);
 
   if (!mComposer) {
@@ -128,13 +126,15 @@
     return HWC2::Error::NoResources;
   }
 
-  auto display = std::make_unique<Display>(*this, mComposer.get(), displayId);
+  uint32_t displayId = configs[0].id;
+  auto display = std::make_unique<Display>(*this, mComposer.get(),
+                                           displayId);
   if (display == nullptr) {
     ALOGE("%s failed to allocate display", __FUNCTION__);
     return HWC2::Error::NoResources;
   }
 
-  HWC2::Error error = display->init(width, height, dpiX, dpiY, refreshRateHz);
+  HWC2::Error error = display->init(configs, activeConfig);
   if (error != HWC2::Error::None) {
     ALOGE("%s failed to initialize display:%" PRIu32, __FUNCTION__, displayId);
     return error;
@@ -539,7 +539,11 @@
     display->unlock();
   }
   if (connected) {
-    createDisplay(id, width, height, dpiX, dpiY, refreshRate);
+    std::vector<DisplayConfig> config;
+    config.push_back({static_cast<int>(id), static_cast<int>(width),
+                      static_cast<int>(height), static_cast<int>(dpiX),
+                      static_cast<int>(dpiY), static_cast<int>(refreshRate)});
+    createDisplay(config, 0);
     ALOGD("callback hotplugConnect display %" PRIu32 " width %" PRIu32
           " height %" PRIu32 " dpiX %" PRIu32 " dpiY %" PRIu32 "fps %" PRIu32,
           id, width, height, dpiX, dpiY, refreshRate);
diff --git a/system/hwc2/Device.h b/system/hwc2/Device.h
index 7c990b9..b49d1a0 100644
--- a/system/hwc2/Device.h
+++ b/system/hwc2/Device.h
@@ -53,8 +53,8 @@
 
   HWC2::Error createDisplays();
 
-  HWC2::Error createDisplay(uint32_t displayId, uint32_t width, uint32_t height,
-                            uint32_t dpiX, uint32_t dpiY, uint32_t refreshRate);
+  HWC2::Error createDisplay(const std::vector<DisplayConfig>& configs,
+                            int activeConfig);
 
   Display* getDisplay(hwc2_display_t displayId);
 
diff --git a/system/hwc2/Display.cpp b/system/hwc2/Display.cpp
index 2feca77..f95992b 100644
--- a/system/hwc2/Display.cpp
+++ b/system/hwc2/Display.cpp
@@ -70,29 +70,34 @@
 
 Display::~Display() {}
 
-HWC2::Error Display::init(uint32_t width, uint32_t height, uint32_t dpiX,
-                          uint32_t dpiY, uint32_t refreshRateHz,
+HWC2::Error Display::init(const std::vector<DisplayConfig>& configs,
+                          int activeConfig,
                           const std::optional<std::vector<uint8_t>>& edid) {
   ALOGD("%s initializing display:%" PRIu64
         " width:%d height:%d dpiX:%d dpiY:%d refreshRateHz:%d",
-        __FUNCTION__, mId, width, height, dpiX, dpiY, refreshRateHz);
+        __FUNCTION__, mId, configs[activeConfig].width,
+        configs[activeConfig].height,
+        configs[activeConfig].dpiX,
+        configs[activeConfig].dpiY,
+        configs[activeConfig].refreshRateHz);
 
   std::unique_lock<std::recursive_mutex> lock(mStateMutex);
 
-  mVsyncPeriod = 1000 * 1000 * 1000 / refreshRateHz;
+  mVsyncPeriod = 1000 * 1000 * 1000 / configs[activeConfig].refreshRateHz;
   mVsyncThread->run("", ANDROID_PRIORITY_URGENT_DISPLAY);
 
-  hwc2_config_t configId = sNextConfigId++;
+  for (hwc2_config_t id = 0; id < configs.size(); id++) {
+    Config config(id);
+    config.setAttribute(HWC2::Attribute::VsyncPeriod,
+                        1000 * 1000 * 1000 / configs[id].refreshRateHz);
+    config.setAttribute(HWC2::Attribute::Width, configs[id].width);
+    config.setAttribute(HWC2::Attribute::Height, configs[id].height);
+    config.setAttribute(HWC2::Attribute::DpiX, configs[id].dpiX * 1000);
+    config.setAttribute(HWC2::Attribute::DpiY, configs[id].dpiY * 1000);
+    mConfigs.emplace(id, config);
+  }
+  mActiveConfigId = activeConfig;
 
-  Config config(configId);
-  config.setAttribute(HWC2::Attribute::VsyncPeriod, mVsyncPeriod);
-  config.setAttribute(HWC2::Attribute::Width, width);
-  config.setAttribute(HWC2::Attribute::Height, height);
-  config.setAttribute(HWC2::Attribute::DpiX, dpiX * 1000);
-  config.setAttribute(HWC2::Attribute::DpiY, dpiY * 1000);
-  mConfigs.emplace(configId, config);
-
-  mActiveConfigId = configId;
   mActiveColorMode = HAL_COLOR_MODE_NATIVE;
   mColorModes.emplace((android_color_mode_t)HAL_COLOR_MODE_NATIVE);
   mEdid = edid;
@@ -507,7 +512,14 @@
     return HWC2::Error::BadConfig;
   }
 
-  mActiveConfigId = configId;
+  if (mActiveConfigId != configId) {
+    if (mComposer == nullptr) {
+      ALOGE("%s: display:%" PRIu64 " missing composer", __FUNCTION__, mId);
+      return HWC2::Error::NoResources;
+    }
+    mActiveConfigId = configId;
+    return mComposer->onActiveConfigChange(this);
+  }
   return HWC2::Error::None;
 }
 
diff --git a/system/hwc2/Display.h b/system/hwc2/Display.h
index ee94756..c5385a8 100644
--- a/system/hwc2/Display.h
+++ b/system/hwc2/Display.h
@@ -29,6 +29,7 @@
 
 #include "Common.h"
 #include "Composer.h"
+#include "DisplayFinder.h"
 #include "FencedBuffer.h"
 #include "Layer.h"
 
@@ -53,9 +54,7 @@
   Display(Display&& display) = delete;
   Display& operator=(Display&& display) = delete;
 
-  HWC2::Error init(
-      uint32_t width, uint32_t height, uint32_t dpiX, uint32_t dpiY,
-      uint32_t refreshRateHz,
+  HWC2::Error init(const std::vector<DisplayConfig>& configs, int activeConfig,
       const std::optional<std::vector<uint8_t>>& edid = std::nullopt);
 
   HWC2::Error updateParameters(
diff --git a/system/hwc2/DisplayFinder.cpp b/system/hwc2/DisplayFinder.cpp
index 1a3c079..765ec50 100644
--- a/system/hwc2/DisplayFinder.cpp
+++ b/system/hwc2/DisplayFinder.cpp
@@ -30,7 +30,7 @@
   return android::base::GetProperty("ro.product.board", "") == "cutf";
 }
 
-HWC2::Error findCuttlefishDisplayConfigs(std::vector<DisplayConfig>* configs) {
+HWC2::Error findCuttlefishDisplays(std::vector<DisplayMultiConfigs>& displays) {
   DEBUG_LOG("%s", __FUNCTION__);
 
   // TODO: replace with initializing directly from DRM info.
@@ -38,18 +38,18 @@
 
   int displayId = 0;
   for (const auto& deviceDisplayConfig : deviceConfig.display_config()) {
-    DisplayConfig displayConfig = {
+    DisplayMultiConfigs display = {
         .id = displayId,
-        .width = deviceDisplayConfig.width(),
-        .height = deviceDisplayConfig.height(),
-        .dpiX = deviceDisplayConfig.dpi(),
-        .dpiY = deviceDisplayConfig.dpi(),
-        .refreshRateHz = deviceDisplayConfig.refresh_rate_hz(),
+        .activeConfigId = 0,
+        .configs = {{displayId,
+                     deviceDisplayConfig.width(),
+                     deviceDisplayConfig.width(),
+                     deviceDisplayConfig.dpi(),
+                     deviceDisplayConfig.dpi(),
+                     deviceDisplayConfig.refresh_rate_hz()}},
     };
-
+    displays.push_back(display);
     ++displayId;
-
-    configs->push_back(displayConfig);
   }
 
   return HWC2::Error::None;
@@ -71,33 +71,54 @@
   return static_cast<int>(vsyncPeriod);
 }
 
-HWC2::Error findGoldfishPrimaryDisplayConfig(
-    std::vector<DisplayConfig>* configs) {
+HWC2::Error findGoldfishPrimaryDisplay(std::vector<DisplayMultiConfigs>& displays) {
   DEBUG_LOG("%s", __FUNCTION__);
 
   DEFINE_AND_VALIDATE_HOST_CONNECTION
   hostCon->lock();
-  const int width = rcEnc->rcGetFBParam(rcEnc, FB_WIDTH);
-  const int height = rcEnc->rcGetFBParam(rcEnc, FB_HEIGHT);
-  const int dpiX = rcEnc->rcGetFBParam(rcEnc, FB_XDPI);
-  const int dpiY = rcEnc->rcGetFBParam(rcEnc, FB_YDPI);
-  hostCon->unlock();
+  int activeConfigId;
   const int refreshRateHz = getVsyncHzFromProperty();
+  DisplayMultiConfigs display;
+  display.id = 0;
+  if (rcEnc->hasHWCMultiConfigs()) {
+    int count= rcEnc->rcGetFBDisplayConfigsCount(rcEnc);
+    if (count <= 0) {
+      ALOGE("%s failed to allocate primary display, config count %d", __func__, count);
+      return HWC2::Error::NoResources;
+    }
+    display.activeConfigId = rcEnc->rcGetFBDisplayActiveConfig(rcEnc);
+    for(int configId = 0; configId < count; configId++) {
+      display.configs.push_back({
+                                0,
+                                rcEnc->rcGetFBDisplayConfigsParam(
+                                    rcEnc, configId, FB_WIDTH),
+                                rcEnc->rcGetFBDisplayConfigsParam(
+                                    rcEnc, configId, FB_HEIGHT),
+                                rcEnc->rcGetFBDisplayConfigsParam(
+                                    rcEnc, configId, FB_XDPI),
+                                rcEnc->rcGetFBDisplayConfigsParam(
+                                    rcEnc, configId, FB_YDPI),
+                                refreshRateHz,
+                                });
+    }
+  } else {
+    display.activeConfigId = 0;
+    display.configs.push_back({
+                              0,
+                              rcEnc->rcGetFBParam(rcEnc, FB_WIDTH),
+                              rcEnc->rcGetFBParam(rcEnc, FB_HEIGHT),
+                              rcEnc->rcGetFBParam(rcEnc, FB_XDPI),
+                              rcEnc->rcGetFBParam(rcEnc, FB_YDPI),
+                              refreshRateHz});
+  }
+  hostCon->unlock();
 
-  configs->push_back(DisplayConfig{
-      .id = 0,
-      .width = width,
-      .height = height,
-      .dpiX = dpiX,
-      .dpiY = dpiY,
-      .refreshRateHz = refreshRateHz,
-  });
+  displays.push_back(display);
 
   return HWC2::Error::None;
 }
 
-HWC2::Error findGoldfishSecondaryDisplayConfigs(
-    std::vector<DisplayConfig>* configs) {
+HWC2::Error findGoldfishSecondaryDisplays(std::vector<DisplayMultiConfigs>& displays) {
   DEBUG_LOG("%s", __FUNCTION__);
 
   static constexpr const char kExternalDisplayProp[] =
@@ -131,7 +152,10 @@
 
   int secondaryDisplayId = 1;
   while (!propIntParts.empty()) {
-    configs->push_back(DisplayConfig{
+    DisplayMultiConfigs display;
+    display.id = secondaryDisplayId;
+    display.activeConfigId = 0;
+    display.configs.push_back(DisplayConfig{
         .id = secondaryDisplayId,
         .width = propIntParts[1],
         .height = propIntParts[2],
@@ -139,6 +163,7 @@
         .dpiY = propIntParts[3],
         .refreshRateHz = 160,
     });
+    displays.push_back(display);
 
     ++secondaryDisplayId;
 
@@ -148,14 +173,14 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error findGoldfishDisplayConfigs(std::vector<DisplayConfig>* configs) {
-  HWC2::Error error = findGoldfishPrimaryDisplayConfig(configs);
+HWC2::Error findGoldfishDisplays(std::vector<DisplayMultiConfigs>& displays) {
+  HWC2::Error error = findGoldfishPrimaryDisplay(displays);
   if (error != HWC2::Error::None) {
     ALOGE("%s failed to find Goldfish primary display", __FUNCTION__);
     return error;
   }
 
-  error = findGoldfishSecondaryDisplayConfigs(configs);
+  error = findGoldfishSecondaryDisplays(displays);
   if (error != HWC2::Error::None) {
     ALOGE("%s failed to find Goldfish secondary displays", __FUNCTION__);
   }
@@ -165,11 +190,11 @@
 
 }  // namespace
 
-HWC2::Error findDisplayConfigs(std::vector<DisplayConfig>* configs) {
+HWC2::Error findDisplays(std::vector<DisplayMultiConfigs>& displays) {
   if (IsCuttlefish()) {
-    return findCuttlefishDisplayConfigs(configs);
+    return findCuttlefishDisplays(displays);
   } else {
-    return findGoldfishDisplayConfigs(configs);
+    return findGoldfishDisplays(displays);
   }
 }
 
diff --git a/system/hwc2/DisplayFinder.h b/system/hwc2/DisplayFinder.h
index 642fca2..44a09a6 100644
--- a/system/hwc2/DisplayFinder.h
+++ b/system/hwc2/DisplayFinder.h
@@ -32,8 +32,15 @@
   int refreshRateHz;
 };
 
-HWC2::Error findDisplayConfigs(std::vector<DisplayConfig>* configs);
+struct DisplayMultiConfigs {
+  int id;
+  int activeConfigId;
+  // Modes that this display can be configured to use.
+  std::vector<DisplayConfig> configs;
+};
+
+HWC2::Error findDisplays(std::vector<DisplayMultiConfigs>& displays);
 
 }  // namespace android
 
-#endif
\ No newline at end of file
+#endif
diff --git a/system/hwc2/GuestComposer.h b/system/hwc2/GuestComposer.h
index ff202cc..db6bf3e 100644
--- a/system/hwc2/GuestComposer.h
+++ b/system/hwc2/GuestComposer.h
@@ -57,6 +57,10 @@
   HWC2::Error presentDisplay(Display* display,
                              int32_t* outPresentFence) override;
 
+  HWC2::Error onActiveConfigChange(Display* /*display*/) override {
+    return HWC2::Error::None;
+  };
+
  private:
   struct DisplayConfig {
     int width;
diff --git a/system/hwc2/HostComposer.cpp b/system/hwc2/HostComposer.cpp
index f028818..9501bb6 100644
--- a/system/hwc2/HostComposer.cpp
+++ b/system/hwc2/HostComposer.cpp
@@ -198,15 +198,13 @@
     return error;
   }
 
-  auto it = mDisplayInfos.find(displayId);
-  if (it != mDisplayInfos.end()) {
-    ALOGE("%s: display:%" PRIu64 " already created?", __FUNCTION__, displayId);
-  }
-
   HostComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
 
   displayInfo.hostDisplayId = hostDisplayId;
 
+  if (displayInfo.compositionResultBuffer) {
+      FreeDisplayColorBuffer(displayInfo.compositionResultBuffer);
+  }
   displayInfo.compositionResultBuffer =
       AllocateDisplayColorBuffer(displayWidth, displayHeight);
   if (displayInfo.compositionResultBuffer == nullptr) {
@@ -682,4 +680,15 @@
   hostCon->unlock();
 }
 
+HWC2::Error HostComposer::onActiveConfigChange(Display* display) {
+  DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, display->getId());
+  HWC2::Error error = createHostComposerDisplayInfo(display, display->getId());
+  if (error != HWC2::Error::None) {
+    ALOGE("%s failed to update host info for display:%" PRIu64,
+          __FUNCTION__, display->getId());
+    return error;
+  }
+  return HWC2::Error::None;
+}
+
 }  // namespace android
diff --git a/system/hwc2/HostComposer.h b/system/hwc2/HostComposer.h
index c6c9082..f722ffc 100644
--- a/system/hwc2/HostComposer.h
+++ b/system/hwc2/HostComposer.h
@@ -53,6 +53,8 @@
   HWC2::Error presentDisplay(Display* display,
                              int32_t* outPresentFence) override;
 
+  HWC2::Error onActiveConfigChange(Display* display) override;
+
  private:
   HWC2::Error createHostComposerDisplayInfo(Display* display,
                                             uint32_t hostDisplayId);
diff --git a/system/renderControl_enc/renderControl_client_context.cpp b/system/renderControl_enc/renderControl_client_context.cpp
index eb5c921..27dd37e 100644
--- a/system/renderControl_enc/renderControl_client_context.cpp
+++ b/system/renderControl_enc/renderControl_client_context.cpp
@@ -75,6 +75,9 @@
 	rcCreateDisplayById = (rcCreateDisplayById_client_proc_t) getProc("rcCreateDisplayById", userData);
 	rcSetDisplayPoseDpi = (rcSetDisplayPoseDpi_client_proc_t) getProc("rcSetDisplayPoseDpi", userData);
 	rcReadColorBufferDMA = (rcReadColorBufferDMA_client_proc_t) getProc("rcReadColorBufferDMA", userData);
+	rcGetFBDisplayConfigsCount = (rcGetFBDisplayConfigsCount_client_proc_t) getProc("rcGetFBDisplayConfigsCount", userData);
+	rcGetFBDisplayConfigsParam = (rcGetFBDisplayConfigsParam_client_proc_t) getProc("rcGetFBDisplayConfigsParam", userData);
+	rcGetFBDisplayActiveConfig = (rcGetFBDisplayActiveConfig_client_proc_t) getProc("rcGetFBDisplayActiveConfig", userData);
 	return 0;
 }
 
diff --git a/system/renderControl_enc/renderControl_client_context.h b/system/renderControl_enc/renderControl_client_context.h
index 395e4bb..862a70d 100644
--- a/system/renderControl_enc/renderControl_client_context.h
+++ b/system/renderControl_enc/renderControl_client_context.h
@@ -75,6 +75,9 @@
 	rcCreateDisplayById_client_proc_t rcCreateDisplayById;
 	rcSetDisplayPoseDpi_client_proc_t rcSetDisplayPoseDpi;
 	rcReadColorBufferDMA_client_proc_t rcReadColorBufferDMA;
+	rcGetFBDisplayConfigsCount_client_proc_t rcGetFBDisplayConfigsCount;
+	rcGetFBDisplayConfigsParam_client_proc_t rcGetFBDisplayConfigsParam;
+	rcGetFBDisplayActiveConfig_client_proc_t rcGetFBDisplayActiveConfig;
 	virtual ~renderControl_client_context_t() {}
 
 	typedef renderControl_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/system/renderControl_enc/renderControl_client_proc.h b/system/renderControl_enc/renderControl_client_proc.h
index 2e52898..2c28127 100644
--- a/system/renderControl_enc/renderControl_client_proc.h
+++ b/system/renderControl_enc/renderControl_client_proc.h
@@ -77,6 +77,9 @@
 typedef int (renderControl_APIENTRY *rcCreateDisplayById_client_proc_t) (void * ctx, uint32_t);
 typedef int (renderControl_APIENTRY *rcSetDisplayPoseDpi_client_proc_t) (void * ctx, uint32_t, GLint, GLint, uint32_t, uint32_t, uint32_t);
 typedef int (renderControl_APIENTRY *rcReadColorBufferDMA_client_proc_t) (void * ctx, uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*, uint32_t);
+typedef int (renderControl_APIENTRY *rcGetFBDisplayConfigsCount_client_proc_t) (void * ctx);
+typedef int (renderControl_APIENTRY *rcGetFBDisplayConfigsParam_client_proc_t) (void * ctx, int, EGLint);
+typedef int (renderControl_APIENTRY *rcGetFBDisplayActiveConfig_client_proc_t) (void * ctx);
 
 
 #endif
diff --git a/system/renderControl_enc/renderControl_enc.cpp b/system/renderControl_enc/renderControl_enc.cpp
index 5efed5f..7fdcab9 100644
--- a/system/renderControl_enc/renderControl_enc.cpp
+++ b/system/renderControl_enc/renderControl_enc.cpp
@@ -2523,8 +2523,8 @@
 	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
 	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
 
-	// stream->readback(pixels, __size_pixels);
-	// if (useChecksum) checksumCalculator->addBuffer(pixels, __size_pixels);
+	// Skip readback for var pixels as it's DMA
+	// Skip checksum for var pixels as it's DMA
 
 	int retval;
 	stream->readback(&retval, 4);
@@ -2542,6 +2542,128 @@
 	return retval;
 }
 
+int rcGetFBDisplayConfigsCount_enc(void *self )
+{
+	AEMU_SCOPED_TRACE("rcGetFBDisplayConfigsCount encode");
+
+	renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
+	IOStream *stream = ctx->m_stream;
+	ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+	bool useChecksum = checksumCalculator->getVersion() > 0;
+
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_rcGetFBDisplayConfigsCount;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+
+	int retval;
+	stream->readback(&retval, 4);
+	if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
+	if (useChecksum) {
+		unsigned char *checksumBufPtr = NULL;
+		unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+		if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+		stream->readback(checksumBufPtr, checksumSize);
+		if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+			ALOGE("rcGetFBDisplayConfigsCount: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+	return retval;
+}
+
+int rcGetFBDisplayConfigsParam_enc(void *self , int configId, EGLint param)
+{
+	AEMU_SCOPED_TRACE("rcGetFBDisplayConfigsParam encode");
+
+	renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
+	IOStream *stream = ctx->m_stream;
+	ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+	bool useChecksum = checksumCalculator->getVersion() > 0;
+
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 4 + 4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_rcGetFBDisplayConfigsParam;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &configId, 4); ptr += 4;
+		memcpy(ptr, &param, 4); ptr += 4;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+
+	int retval;
+	stream->readback(&retval, 4);
+	if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
+	if (useChecksum) {
+		unsigned char *checksumBufPtr = NULL;
+		unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+		if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+		stream->readback(checksumBufPtr, checksumSize);
+		if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+			ALOGE("rcGetFBDisplayConfigsParam: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+	return retval;
+}
+
+int rcGetFBDisplayActiveConfig_enc(void *self )
+{
+	AEMU_SCOPED_TRACE("rcGetFBDisplayActiveConfig encode");
+
+	renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
+	IOStream *stream = ctx->m_stream;
+	ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+	bool useChecksum = checksumCalculator->getVersion() > 0;
+
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_rcGetFBDisplayActiveConfig;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+
+	int retval;
+	stream->readback(&retval, 4);
+	if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
+	if (useChecksum) {
+		unsigned char *checksumBufPtr = NULL;
+		unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+		if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+		stream->readback(checksumBufPtr, checksumSize);
+		if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+			ALOGE("rcGetFBDisplayActiveConfig: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+	return retval;
+}
+
 }  // namespace
 
 renderControl_encoder_context_t::renderControl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -2614,5 +2736,8 @@
 	this->rcCreateDisplayById = &rcCreateDisplayById_enc;
 	this->rcSetDisplayPoseDpi = &rcSetDisplayPoseDpi_enc;
 	this->rcReadColorBufferDMA = &rcReadColorBufferDMA_enc;
+	this->rcGetFBDisplayConfigsCount = &rcGetFBDisplayConfigsCount_enc;
+	this->rcGetFBDisplayConfigsParam = &rcGetFBDisplayConfigsParam_enc;
+	this->rcGetFBDisplayActiveConfig = &rcGetFBDisplayActiveConfig_enc;
 }
 
diff --git a/system/renderControl_enc/renderControl_entry.cpp b/system/renderControl_enc/renderControl_entry.cpp
index 5b2bedd..e756322 100644
--- a/system/renderControl_enc/renderControl_entry.cpp
+++ b/system/renderControl_enc/renderControl_entry.cpp
@@ -70,6 +70,9 @@
 	int rcCreateDisplayById(uint32_t displayId);
 	int rcSetDisplayPoseDpi(uint32_t displayId, GLint x, GLint y, uint32_t w, uint32_t h, uint32_t dpi);
 	int rcReadColorBufferDMA(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size);
+	int rcGetFBDisplayConfigsCount();
+	int rcGetFBDisplayConfigsParam(int configId, EGLint param);
+	int rcGetFBDisplayActiveConfig();
 };
 
 #ifndef GET_CONTEXT
@@ -468,3 +471,21 @@
 	return ctx->rcReadColorBufferDMA(ctx, colorbuffer, x, y, width, height, format, type, pixels, pixels_size);
 }
 
+int rcGetFBDisplayConfigsCount()
+{
+	GET_CONTEXT;
+	return ctx->rcGetFBDisplayConfigsCount(ctx);
+}
+
+int rcGetFBDisplayConfigsParam(int configId, EGLint param)
+{
+	GET_CONTEXT;
+	return ctx->rcGetFBDisplayConfigsParam(ctx, configId, param);
+}
+
+int rcGetFBDisplayActiveConfig()
+{
+	GET_CONTEXT;
+	return ctx->rcGetFBDisplayActiveConfig(ctx);
+}
+
diff --git a/system/renderControl_enc/renderControl_ftable.h b/system/renderControl_enc/renderControl_ftable.h
index 577cbae..9a0f9e9 100644
--- a/system/renderControl_enc/renderControl_ftable.h
+++ b/system/renderControl_enc/renderControl_ftable.h
@@ -73,6 +73,9 @@
 	{"rcCreateDisplayById", (void*)rcCreateDisplayById},
 	{"rcSetDisplayPoseDpi", (void*)rcSetDisplayPoseDpi},
 	{"rcReadColorBufferDMA", (void*)rcReadColorBufferDMA},
+	{"rcGetFBDisplayConfigsCount", (void*)rcGetFBDisplayConfigsCount},
+	{"rcGetFBDisplayConfigsParam", (void*)rcGetFBDisplayConfigsParam},
+	{"rcGetFBDisplayActiveConfig", (void*)rcGetFBDisplayActiveConfig},
 };
 static const int renderControl_num_funcs = sizeof(renderControl_funcs_by_name) / sizeof(struct _renderControl_funcs_by_name);
 
diff --git a/system/renderControl_enc/renderControl_opcodes.h b/system/renderControl_enc/renderControl_opcodes.h
index 00249d6..cf4ff82 100644
--- a/system/renderControl_enc/renderControl_opcodes.h
+++ b/system/renderControl_enc/renderControl_opcodes.h
@@ -68,7 +68,10 @@
 #define OP_rcCreateDisplayById 					10062
 #define OP_rcSetDisplayPoseDpi 					10063
 #define OP_rcReadColorBufferDMA 					10064
-#define OP_last 					10065
+#define OP_rcGetFBDisplayConfigsCount 					10065
+#define OP_rcGetFBDisplayConfigsParam 					10066
+#define OP_rcGetFBDisplayActiveConfig 					10067
+#define OP_last 					10068
 
 
 #endif