Merge "hwc: Handle validateAndSet failures in AD prepare call"
diff --git a/libhwcomposer/hwc_ad.cpp b/libhwcomposer/hwc_ad.cpp
index fdf6e67..49e7e2a 100644
--- a/libhwcomposer/hwc_ad.cpp
+++ b/libhwcomposer/hwc_ad.cpp
@@ -41,37 +41,6 @@
using namespace overlay::utils;
namespace qhwc {
-//Opens writeback framebuffer and returns fd.
-static int openWbFb() {
- int wbFd = -1;
- //Check opening which FB would connect LM to WB
- const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
- if(wbFbNum >= 0) {
- char wbFbPath[256];
- snprintf (wbFbPath, sizeof(wbFbPath),
- "/sys/class/graphics/fb%d", wbFbNum);
- //Opening writeback fb first time would create ad node if the device
- //supports adaptive display
- wbFd = open(wbFbPath, O_RDONLY);
- if(wbFd < 0) {
- ALOGE("%s: Failed to open /sys/class/graphics/fb%d with error %s",
- __func__, wbFbNum, strerror(errno));
- }
- } else {
- ALOGD_IF(DEBUG, "%s: No writeback available", __func__);
- }
- return wbFd;
-}
-
-static inline void closeWbFb(int& fd) {
- if(fd >= 0) {
- close(fd);
- fd = -1;
- } else {
- ALOGE("%s: Invalid fd %d", __func__, fd);
- }
-}
-
//Helper to write data to ad node
static void adWrite(const int& value) {
const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
@@ -124,32 +93,31 @@
return ret;
}
-AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) : mWbFd(-1),
- mDoable(false), mFeatureEnabled(false),
- mDest(overlay::utils::OV_INVALID) {
- int fd = openWbFb();
- if(fd >= 0) {
- //Values in ad node:
- //-1 means feature is disabled on device
- // 0 means feature exists but turned off, will be turned on by hwc
- // 1 means feature is turned on by hwc
- // Plus, we do this feature only on split primary displays.
- // Plus, we do this feature only if ro.qcom.ad=2
+AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) :
+ mTurnedOff(true), mFeatureEnabled(false),
+ mDest(overlay::utils::OV_INVALID)
+{
+ //Values in ad node:
+ //-1 means feature is disabled on device
+ // 0 means feature exists but turned off, will be turned on by hwc
+ // 1 means feature is turned on by hwc
+ // Plus, we do this feature only on split primary displays.
+ // Plus, we do this feature only if ro.qcom.ad=2
- char property[PROPERTY_VALUE_MAX];
- const int ENABLED = 2;
- int val = 0;
+ char property[PROPERTY_VALUE_MAX];
+ const int ENABLED = 2;
+ int val = 0;
- if(property_get("ro.qcom.ad", property, "0") > 0) {
- val = atoi(property);
- }
+ if(property_get("ro.qcom.ad", property, "0") > 0) {
+ val = atoi(property);
+ }
- if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
- val == ENABLED) {
- ALOGD_IF(DEBUG, "Assertive display feature supported");
- mFeatureEnabled = true;
- }
- closeWbFb(fd);
+ if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
+ val == ENABLED) {
+ ALOGD_IF(DEBUG, "Assertive display feature supported");
+ mFeatureEnabled = true;
+ // If feature exists but is turned off, set mTurnedOff to true
+ mTurnedOff = adRead() > 0 ? false : true;
}
}
@@ -168,17 +136,24 @@
}
}
+void AssertiveDisplay::turnOffAD() {
+ if(mFeatureEnabled) {
+ if(!mTurnedOff) {
+ const int off = 0;
+ adWrite(off);
+ mTurnedOff = true;
+ }
+ }
+ mDoable = false;
+}
+
bool AssertiveDisplay::prepare(hwc_context_t *ctx,
const hwc_rect_t& crop,
const Whf& whf,
const private_handle_t *hnd) {
if(!isDoable()) {
- if(isModeOn()) {
- //Cleanup one time during this switch
- const int off = 0;
- adWrite(off);
- closeWbFb(mWbFd);
- }
+ //Cleanup one time during this switch
+ turnOffAD();
return false;
}
@@ -246,27 +221,30 @@
}
mDest = dest;
- if(!isModeOn()) {
- mWbFd = openWbFb();
- if(mWbFd >= 0) {
- //write to sysfs, one time during this switch
- const int on = 1;
- adWrite(on);
- }
- }
-
- if(!ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK,
- mWbFd)) {
+ int wbFd = wb->getFbFd();
+ if(mFeatureEnabled && wbFd >= 0 &&
+ !ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK, wbFd))
+ {
ALOGE("%s: Failed to validate and set overlay for dpy %d"
,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
+ turnOffAD();
return false;
}
+ // Only turn on AD if there are no errors during configuration stage
+ // and if it was previously in OFF state.
+ if(mFeatureEnabled && mTurnedOff) {
+ //write to sysfs, one time during this switch
+ const int on = 1;
+ adWrite(on);
+ mTurnedOff = false;
+ }
+
return true;
}
bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) {
- if(!isDoable() || !isModeOn()) {
+ if(!isDoable()) {
return false;
}
diff --git a/libhwcomposer/hwc_ad.h b/libhwcomposer/hwc_ad.h
index 3bfde17..0be5f5d 100644
--- a/libhwcomposer/hwc_ad.h
+++ b/libhwcomposer/hwc_ad.h
@@ -50,17 +50,16 @@
mDest = overlay::utils::OV_INVALID;
}
bool isDoable() const { return mDoable; }
- bool isModeOn() const { return (mWbFd >= 0); }
int getDstFd() const;
uint32_t getDstOffset() const;
private:
- //State of feature turned on and off
- int mWbFd;
bool mDoable;
+ bool mTurnedOff;
//State of feature existence on certain devices and configs.
bool mFeatureEnabled;
overlay::utils::eDest mDest;
+ void turnOffAD();
};
}
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 8a717c0..7c67641 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1766,11 +1766,9 @@
int fd = hnd->fd;
int offset = (uint32_t)hnd->offset;
- if(ctx->mAD->isModeOn()) {
- if(ctx->mAD->draw(ctx, fd, offset)) {
- fd = ctx->mAD->getDstFd();
- offset = ctx->mAD->getDstOffset();
- }
+ if(ctx->mAD->draw(ctx, fd, offset)) {
+ fd = ctx->mAD->getDstFd();
+ offset = ctx->mAD->getDstOffset();
}
if(rot) {