From 7f7da32569f8e0b3d383a40b95f8ac1d55afd801 Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Fri, 2 May 2014 15:26:25 -0700 Subject: [PATCH] Enable changing display configuration This allows querying and switching display device configurations through the ISurfaceComposer/SurfaceComposerClient interface. Bug: 14320401 Change-Id: I8c22165698950e5da32204c1c4da92122f91a715 --- include/gui/ISurfaceComposer.h | 17 +- include/gui/SurfaceComposerClient.h | 17 +- include/ui/DisplayInfo.h | 1 - libs/gui/ISurfaceComposer.cpp | 65 +++++- libs/gui/SurfaceComposerClient.cpp | 32 ++- .../DisplayHardware/HWComposer.cpp | 190 ++++++++++-------- .../DisplayHardware/HWComposer.h | 28 ++- services/surfaceflinger/SurfaceFlinger.cpp | 93 +++++---- services/surfaceflinger/SurfaceFlinger.h | 5 +- 9 files changed, 308 insertions(+), 140 deletions(-) diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index efde5db6a..804221106 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -113,9 +113,18 @@ public: */ virtual void unblank(const sp& display) = 0; - /* returns information about a display + /* returns information for each configuration of the given display * intended to be used to get information about built-in displays */ - virtual status_t getDisplayInfo(const sp& display, DisplayInfo* info) = 0; + virtual status_t getDisplayConfigs(const sp& display, + Vector* configs) = 0; + + /* indicates which of the configurations returned by getDisplayInfo is + * currently active */ + virtual int getActiveConfig(const sp& display) = 0; + + /* specifies which configuration (of those returned by getDisplayInfo) + * should be used */ + virtual status_t setActiveConfig(const sp& display, int id) = 0; /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. @@ -158,7 +167,9 @@ public: AUTHENTICATE_SURFACE, BLANK, UNBLANK, - GET_DISPLAY_INFO, + GET_DISPLAY_CONFIGS, + GET_ACTIVE_CONFIG, + SET_ACTIVE_CONFIG, CONNECT_DISPLAY, CAPTURE_SCREEN, CLEAR_ANIMATION_FRAME_STATS, diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 6a53ccbea..c2192afd7 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -66,8 +66,21 @@ public: status_t linkToComposerDeath(const sp& recipient, void* cookie = NULL, uint32_t flags = 0); - // Get information about a display - static status_t getDisplayInfo(const sp& display, DisplayInfo* info); + // Get a list of supported configurations for a given display + static status_t getDisplayConfigs(const sp& display, + Vector* configs); + + // Get the DisplayInfo for the currently-active configuration + static status_t getDisplayInfo(const sp& display, + DisplayInfo* info); + + // Get the index of the current active configuration (relative to the list + // returned by getDisplayInfo) + static int getActiveConfig(const sp& display); + + // Set a new active configuration using an index relative to the list + // returned by getDisplayInfo + static status_t setActiveConfig(const sp& display, int id); /* triggers screen off and waits for it to complete */ static void blankDisplay(const sp& display); diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h index 2853e063f..3b5cd6d83 100644 --- a/include/ui/DisplayInfo.h +++ b/include/ui/DisplayInfo.h @@ -33,7 +33,6 @@ struct DisplayInfo { float density; uint8_t orientation; bool secure; - uint8_t reserved[2]; }; /* Display orientations as defined in Surface.java and ISurfaceComposer.h. */ diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index c06724442..58a2ae2c4 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -220,13 +220,43 @@ public: remote()->transact(BnSurfaceComposer::UNBLANK, data, &reply); } - virtual status_t getDisplayInfo(const sp& display, DisplayInfo* info) + virtual status_t getDisplayConfigs(const sp& display, + Vector* configs) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::GET_DISPLAY_INFO, data, &reply); - memcpy(info, reply.readInplace(sizeof(DisplayInfo)), sizeof(DisplayInfo)); + remote()->transact(BnSurfaceComposer::GET_DISPLAY_CONFIGS, data, &reply); + status_t result = reply.readInt32(); + if (result == NO_ERROR) { + size_t numConfigs = static_cast(reply.readInt32()); + configs->clear(); + configs->resize(numConfigs); + for (size_t c = 0; c < numConfigs; ++c) { + memcpy(&(configs->editItemAt(c)), + reply.readInplace(sizeof(DisplayInfo)), + sizeof(DisplayInfo)); + } + } + return result; + } + + virtual int getActiveConfig(const sp& display) + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(display); + remote()->transact(BnSurfaceComposer::GET_ACTIVE_CONFIG, data, &reply); + return reply.readInt32(); + } + + virtual status_t setActiveConfig(const sp& display, int id) + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(display); + data.writeInt32(id); + remote()->transact(BnSurfaceComposer::SET_ACTIVE_CONFIG, data, &reply); return reply.readInt32(); } @@ -357,12 +387,33 @@ status_t BnSurfaceComposer::onTransact( unblank(display); return NO_ERROR; } - case GET_DISPLAY_INFO: { + case GET_DISPLAY_CONFIGS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - DisplayInfo info; + Vector configs; sp display = data.readStrongBinder(); - status_t result = getDisplayInfo(display, &info); - memcpy(reply->writeInplace(sizeof(DisplayInfo)), &info, sizeof(DisplayInfo)); + status_t result = getDisplayConfigs(display, &configs); + reply->writeInt32(result); + if (result == NO_ERROR) { + reply->writeInt32(static_cast(configs.size())); + for (size_t c = 0; c < configs.size(); ++c) { + memcpy(reply->writeInplace(sizeof(DisplayInfo)), + &configs[c], sizeof(DisplayInfo)); + } + } + return NO_ERROR; + } + case GET_ACTIVE_CONFIG: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp display = data.readStrongBinder(); + int id = getActiveConfig(display); + reply->writeInt32(id); + return NO_ERROR; + } + case SET_ACTIVE_CONFIG: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp display = data.readStrongBinder(); + int id = data.readInt32(); + status_t result = setActiveConfig(display, id); reply->writeInt32(result); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index b7af4152c..1dffdb201 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -623,10 +623,36 @@ void SurfaceComposerClient::setDisplayProjection(const sp& token, // ---------------------------------------------------------------------------- -status_t SurfaceComposerClient::getDisplayInfo( - const sp& display, DisplayInfo* info) +status_t SurfaceComposerClient::getDisplayConfigs( + const sp& display, Vector* configs) { - return ComposerService::getComposerService()->getDisplayInfo(display, info); + return ComposerService::getComposerService()->getDisplayConfigs(display, configs); +} + +status_t SurfaceComposerClient::getDisplayInfo(const sp& display, + DisplayInfo* info) { + Vector configs; + status_t result = getDisplayConfigs(display, &configs); + if (result != NO_ERROR) { + return result; + } + + int activeId = getActiveConfig(display); + if (activeId < 0) { + ALOGE("No active configuration found"); + return NAME_NOT_FOUND; + } + + *info = configs[activeId]; + return NO_ERROR; +} + +int SurfaceComposerClient::getActiveConfig(const sp& display) { + return ComposerService::getComposerService()->getActiveConfig(display); +} + +status_t SurfaceComposerClient::setActiveConfig(const sp& display, int id) { + return ComposerService::getComposerService()->setActiveConfig(display, id); } void SurfaceComposerClient::blankDisplay(const sp& token) { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index c4ea8cca2..4dccc2268 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -170,20 +170,15 @@ HWComposer::HWComposer( DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]); disp.connected = true; - disp.width = mFbDev->width; - disp.height = mFbDev->height; disp.format = mFbDev->format; - disp.xdpi = mFbDev->xdpi; - disp.ydpi = mFbDev->ydpi; - if (disp.refresh == 0) { - disp.refresh = nsecs_t(1e9 / mFbDev->fps); - ALOGW("getting VSYNC period from fb HAL: %lld", disp.refresh); - } - if (disp.refresh == 0) { - disp.refresh = nsecs_t(1e9 / 60.0); - ALOGW("getting VSYNC period from thin air: %lld", - mDisplayData[HWC_DISPLAY_PRIMARY].refresh); - } + DisplayConfig config = DisplayConfig(); + config.width = mFbDev->width; + config.height = mFbDev->height; + config.xdpi = mFbDev->xdpi; + config.ydpi = mFbDev->ydpi; + config.refresh = nsecs_t(1e9 / mFbDev->fps); + disp.configs.push_back(config); + disp.currentConfig = 0; } else if (mHwc) { // here we're guaranteed to have at least HWC 1.1 for (size_t i =0 ; igetDisplayConfigs(mHwc, disp, &config, &numConfigs); + const size_t MAX_NUM_CONFIGS = 128; + uint32_t configs[MAX_NUM_CONFIGS] = {0}; + size_t numConfigs = MAX_NUM_CONFIGS; + status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs); if (err != NO_ERROR) { // this can happen if an unpluggable display is not connected mDisplayData[disp].connected = false; return err; } - err = mHwc->getDisplayAttributes(mHwc, disp, config, DISPLAY_ATTRIBUTES, values); - if (err != NO_ERROR) { - // we can't get this display's info. turn it off. - mDisplayData[disp].connected = false; - return err; - } - - int32_t w = 0, h = 0; - for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) { - switch (DISPLAY_ATTRIBUTES[i]) { - case HWC_DISPLAY_VSYNC_PERIOD: - mDisplayData[disp].refresh = nsecs_t(values[i]); - break; - case HWC_DISPLAY_WIDTH: - mDisplayData[disp].width = values[i]; - break; - case HWC_DISPLAY_HEIGHT: - mDisplayData[disp].height = values[i]; - break; - case HWC_DISPLAY_DPI_X: - mDisplayData[disp].xdpi = values[i] / 1000.0f; - break; - case HWC_DISPLAY_DPI_Y: - mDisplayData[disp].ydpi = values[i] / 1000.0f; - break; - default: - ALOG_ASSERT(false, "unknown display attribute[%d] %#x", - i, DISPLAY_ATTRIBUTES[i]); - break; + mDisplayData[disp].currentConfig = 0; + for (size_t c = 0; c < numConfigs; ++c) { + err = mHwc->getDisplayAttributes(mHwc, disp, configs[c], + DISPLAY_ATTRIBUTES, values); + if (err != NO_ERROR) { + // we can't get this display's info. turn it off. + mDisplayData[disp].connected = false; + return err; } + + DisplayConfig config = DisplayConfig(); + for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) { + switch (DISPLAY_ATTRIBUTES[i]) { + case HWC_DISPLAY_VSYNC_PERIOD: + config.refresh = nsecs_t(values[i]); + break; + case HWC_DISPLAY_WIDTH: + config.width = values[i]; + break; + case HWC_DISPLAY_HEIGHT: + config.height = values[i]; + break; + case HWC_DISPLAY_DPI_X: + config.xdpi = values[i] / 1000.0f; + break; + case HWC_DISPLAY_DPI_Y: + config.ydpi = values[i] / 1000.0f; + break; + default: + ALOG_ASSERT(false, "unknown display attribute[%d] %#x", + i, DISPLAY_ATTRIBUTES[i]); + break; + } + } + + if (config.xdpi == 0.0f || config.ydpi == 0.0f) { + float dpi = getDefaultDensity(config.height); + config.xdpi = dpi; + config.ydpi = dpi; + } + + mDisplayData[disp].configs.push_back(config); } // FIXME: what should we set the format to? mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888; mDisplayData[disp].connected = true; - if (mDisplayData[disp].xdpi == 0.0f || mDisplayData[disp].ydpi == 0.0f) { - float dpi = getDefaultDensity(h); - mDisplayData[disp].xdpi = dpi; - mDisplayData[disp].ydpi = dpi; - } return NO_ERROR; } @@ -400,10 +403,12 @@ status_t HWComposer::setVirtualDisplayProperties(int32_t id, !mAllocatedDisplayIDs.hasBit(id)) { return BAD_INDEX; } - mDisplayData[id].width = w; - mDisplayData[id].height = h; + size_t configId = mDisplayData[id].currentConfig; mDisplayData[id].format = format; - mDisplayData[id].xdpi = mDisplayData[id].ydpi = getDefaultDensity(h); + DisplayConfig& config = mDisplayData[id].configs.editItemAt(configId); + config.width = w; + config.height = h; + config.xdpi = config.ydpi = getDefaultDensity(h); return NO_ERROR; } @@ -414,6 +419,8 @@ int32_t HWComposer::allocateDisplayId() { int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit(); mAllocatedDisplayIDs.markBit(id); mDisplayData[id].connected = true; + mDisplayData[id].configs.resize(1); + mDisplayData[id].currentConfig = 0; return id; } @@ -430,31 +437,21 @@ status_t HWComposer::freeDisplayId(int32_t id) { return NO_ERROR; } -nsecs_t HWComposer::getRefreshPeriod(int disp) const { - return mDisplayData[disp].refresh; -} - nsecs_t HWComposer::getRefreshTimestamp(int disp) const { // this returns the last refresh timestamp. // if the last one is not available, we estimate it based on // the refresh period and whatever closest timestamp we have. Mutex::Autolock _l(mLock); nsecs_t now = systemTime(CLOCK_MONOTONIC); - return now - ((now - mLastHwVSync[disp]) % mDisplayData[disp].refresh); + size_t configId = mDisplayData[disp].currentConfig; + return now - ((now - mLastHwVSync[disp]) % + mDisplayData[disp].configs[configId].refresh); } sp HWComposer::getDisplayFence(int disp) const { return mDisplayData[disp].lastDisplayFence; } -uint32_t HWComposer::getWidth(int disp) const { - return mDisplayData[disp].width; -} - -uint32_t HWComposer::getHeight(int disp) const { - return mDisplayData[disp].height; -} - uint32_t HWComposer::getFormat(int disp) const { if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) { return HAL_PIXEL_FORMAT_RGBA_8888; @@ -463,16 +460,41 @@ uint32_t HWComposer::getFormat(int disp) const { } } +bool HWComposer::isConnected(int disp) const { + return mDisplayData[disp].connected; +} + +uint32_t HWComposer::getWidth(int disp) const { + size_t currentConfig = mDisplayData[disp].currentConfig; + return mDisplayData[disp].configs[currentConfig].width; +} + +uint32_t HWComposer::getHeight(int disp) const { + size_t currentConfig = mDisplayData[disp].currentConfig; + return mDisplayData[disp].configs[currentConfig].height; +} + float HWComposer::getDpiX(int disp) const { - return mDisplayData[disp].xdpi; + size_t currentConfig = mDisplayData[disp].currentConfig; + return mDisplayData[disp].configs[currentConfig].xdpi; } float HWComposer::getDpiY(int disp) const { - return mDisplayData[disp].ydpi; + size_t currentConfig = mDisplayData[disp].currentConfig; + return mDisplayData[disp].configs[currentConfig].ydpi; } -bool HWComposer::isConnected(int disp) const { - return mDisplayData[disp].connected; +nsecs_t HWComposer::getRefreshPeriod(int disp) const { + size_t currentConfig = mDisplayData[disp].currentConfig; + return mDisplayData[disp].configs[currentConfig].refresh; +} + +const Vector& HWComposer::getConfigs(int disp) const { + return mDisplayData[disp].configs; +} + +size_t HWComposer::getCurrentConfig(int disp) const { + return mDisplayData[disp].currentConfig; } void HWComposer::eventControl(int disp, int event, int enabled) { @@ -536,7 +558,10 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1]; memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t)); - const hwc_rect_t r = { 0, 0, (int) disp.width, (int) disp.height }; + const DisplayConfig& currentConfig = + disp.configs[disp.currentConfig]; + const hwc_rect_t r = { 0, 0, + (int) currentConfig.width, (int) currentConfig.height }; disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET; disp.framebufferTarget->hints = 0; disp.framebufferTarget->flags = 0; @@ -546,8 +571,10 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) { disp.framebufferTarget->sourceCropf.left = 0; disp.framebufferTarget->sourceCropf.top = 0; - disp.framebufferTarget->sourceCropf.right = disp.width; - disp.framebufferTarget->sourceCropf.bottom = disp.height; + disp.framebufferTarget->sourceCropf.right = + currentConfig.width; + disp.framebufferTarget->sourceCropf.bottom = + currentConfig.height; } else { disp.framebufferTarget->sourceCrop = r; } @@ -1050,9 +1077,14 @@ void HWComposer::dump(String8& result) const { const Vector< sp >& visibleLayersSortedByZ = mFlinger->getLayerSortedByZForHwcDisplay(i); - result.appendFormat( - " Display[%zd] : %ux%u, xdpi=%f, ydpi=%f, refresh=%" PRId64 "\n", - i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh); + + result.appendFormat(" Display[%zd] configurations (* current):\n", i); + for (size_t c = 0; c < disp.configs.size(); ++c) { + const DisplayConfig& config(disp.configs[c]); + result.appendFormat(" %s%zd: %ux%u, xdpi=%f, ydpi=%f, refresh=%" PRId64 "\n", + c == disp.currentConfig ? "* " : "", c, config.width, config.height, + config.xdpi, config.ydpi, config.refresh); + } if (disp.list) { result.appendFormat( @@ -1181,9 +1213,9 @@ bool HWComposer::VSyncThread::threadLoop() { } HWComposer::DisplayData::DisplayData() -: width(0), height(0), format(HAL_PIXEL_FORMAT_RGBA_8888), - xdpi(0.0f), ydpi(0.0f), - refresh(0), +: configs(), + currentConfig(0), + format(HAL_PIXEL_FORMAT_RGBA_8888), connected(false), hasFbComp(false), hasOvComp(false), capacity(0), list(NULL), diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 9218bf609..32d4a0cc3 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -247,17 +247,31 @@ public: void eventControl(int disp, int event, int enabled); + struct DisplayConfig { + uint32_t width; + uint32_t height; + float xdpi; + float ydpi; + nsecs_t refresh; + }; + // Query display parameters. Pass in a display index (e.g. // HWC_DISPLAY_PRIMARY). - nsecs_t getRefreshPeriod(int disp) const; nsecs_t getRefreshTimestamp(int disp) const; sp getDisplayFence(int disp) const; + uint32_t getFormat(int disp) const; + bool isConnected(int disp) const; + + // These return the values for the current config of a given display index. + // To get the values for all configs, use getConfigs below. uint32_t getWidth(int disp) const; uint32_t getHeight(int disp) const; - uint32_t getFormat(int disp) const; float getDpiX(int disp) const; float getDpiY(int disp) const; - bool isConnected(int disp) const; + nsecs_t getRefreshPeriod(int disp) const; + + const Vector& getConfigs(int disp) const; + size_t getCurrentConfig(int disp) const; status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h, uint32_t format); @@ -306,16 +320,12 @@ private: status_t setFramebufferTarget(int32_t id, const sp& acquireFence, const sp& buf); - struct DisplayData { DisplayData(); ~DisplayData(); - uint32_t width; - uint32_t height; + Vector configs; + size_t currentConfig; uint32_t format; // pixel format from FB hal, for pre-hwc-1.1 - float xdpi; - float ydpi; - nsecs_t refresh; bool connected; bool hasFbComp; bool hasOvComp; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a3465200b..46e192ecb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -502,7 +502,12 @@ bool SurfaceFlinger::authenticateSurfaceTexture( return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0; } -status_t SurfaceFlinger::getDisplayInfo(const sp& display, DisplayInfo* info) { +status_t SurfaceFlinger::getDisplayConfigs(const sp& display, + Vector* configs) { + if (configs == NULL) { + return BAD_VALUE; + } + int32_t type = NAME_NOT_FOUND; for (int i=0 ; i& display, DisplayInfo* return type; } - const HWComposer& hwc(getHwComposer()); - float xdpi = hwc.getDpiX(type); - float ydpi = hwc.getDpiY(type); - // TODO: Not sure if display density should handled by SF any longer class Density { static int getDensityFromProperty(char const* propName) { @@ -536,41 +537,63 @@ status_t SurfaceFlinger::getDisplayInfo(const sp& display, DisplayInfo* return getDensityFromProperty("ro.sf.lcd_density"); } }; - if (type == DisplayDevice::DISPLAY_PRIMARY) { - // The density of the device is provided by a build property - float density = Density::getBuildDensity() / 160.0f; - if (density == 0) { - // the build doesn't provide a density -- this is wrong! - // use xdpi instead - ALOGE("ro.sf.lcd_density must be defined as a build property"); - density = xdpi / 160.0f; - } - if (Density::getEmuDensity()) { - // if "qemu.sf.lcd_density" is specified, it overrides everything - xdpi = ydpi = density = Density::getEmuDensity(); - density /= 160.0f; - } - info->density = density; + configs->clear(); - // TODO: this needs to go away (currently needed only by webkit) - sp hw(getDefaultDisplayDevice()); - info->orientation = hw->getOrientation(); - } else { - // TODO: where should this value come from? - static const int TV_DENSITY = 213; - info->density = TV_DENSITY / 160.0f; - info->orientation = 0; + const Vector& hwConfigs = + getHwComposer().getConfigs(type); + for (size_t c = 0; c < hwConfigs.size(); ++c) { + const HWComposer::DisplayConfig& hwConfig = hwConfigs[c]; + DisplayInfo info = DisplayInfo(); + + float xdpi = hwConfig.xdpi; + float ydpi = hwConfig.ydpi; + + if (type == DisplayDevice::DISPLAY_PRIMARY) { + // The density of the device is provided by a build property + float density = Density::getBuildDensity() / 160.0f; + if (density == 0) { + // the build doesn't provide a density -- this is wrong! + // use xdpi instead + ALOGE("ro.sf.lcd_density must be defined as a build property"); + density = xdpi / 160.0f; + } + if (Density::getEmuDensity()) { + // if "qemu.sf.lcd_density" is specified, it overrides everything + xdpi = ydpi = density = Density::getEmuDensity(); + density /= 160.0f; + } + info.density = density; + + // TODO: this needs to go away (currently needed only by webkit) + sp hw(getDefaultDisplayDevice()); + info.orientation = hw->getOrientation(); + } else { + // TODO: where should this value come from? + static const int TV_DENSITY = 213; + info.density = TV_DENSITY / 160.0f; + info.orientation = 0; + } + + info.w = hwConfig.width; + info.h = hwConfig.height; + info.xdpi = xdpi; + info.ydpi = ydpi; + info.fps = float(1e9 / hwConfig.refresh); + + // All non-virtual displays are currently considered secure. + info.secure = true; + + configs->push_back(info); } - info->w = hwc.getWidth(type); - info->h = hwc.getHeight(type); - info->xdpi = xdpi; - info->ydpi = ydpi; - info->fps = float(1e9 / hwc.getRefreshPeriod(type)); + return NO_ERROR; +} - // All non-virtual displays are currently considered secure. - info->secure = true; +int SurfaceFlinger::getActiveConfig(const sp& display) { + return 0; +} +status_t SurfaceFlinger::setActiveConfig(const sp& display, int id) { return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 717ee666d..0b868e202 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -209,7 +209,10 @@ private: virtual void blank(const sp& display); // called when screen is turning back on virtual void unblank(const sp& display); - virtual status_t getDisplayInfo(const sp& display, DisplayInfo* info); + virtual status_t getDisplayConfigs(const sp& display, + Vector* configs); + virtual int getActiveConfig(const sp& display); + virtual status_t setActiveConfig(const sp& display, int id); virtual status_t clearAnimationFrameStats(); virtual status_t getAnimationFrameStats(FrameStats* outStats) const;