Merge "BufferQueue consumers: Add discardFreeBuffer method" into nyc-mr1-dev
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index ba0ce0a..674f760 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -823,7 +823,7 @@
     }
 
     inode_raw = inode;
-    if (setxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw), 0) != 0) {
+    if (setxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw), 0) != 0 && errno != EOPNOTSUPP) {
         PLOG(ERROR) << "Failed to write xattr " << inode_xattr << " at " << parent;
         return -1;
     } else {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 4ac58c5..c87ba72 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -467,6 +467,10 @@
 
     Mutex::Autolock _l(mDisplayLock);
     auto displayId = displayDevice.getHwcDisplayId();
+    if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+        ALOGV("Skipping HWComposer prepare for non-HWC display");
+        return NO_ERROR;
+    }
     if (!isValidDisplay(displayId)) {
         return BAD_INDEX;
     }
@@ -560,6 +564,11 @@
 }
 
 bool HWComposer::hasDeviceComposition(int32_t displayId) const {
+    if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+        // Displays without a corresponding HWC display are never composed by
+        // the device
+        return false;
+    }
     if (!isValidDisplay(displayId)) {
         ALOGE("hasDeviceComposition: Invalid display %d", displayId);
         return false;
@@ -568,6 +577,11 @@
 }
 
 bool HWComposer::hasClientComposition(int32_t displayId) const {
+    if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+        // Displays without a corresponding HWC display are always composed by
+        // the client
+        return true;
+    }
     if (!isValidDisplay(displayId)) {
         ALOGE("hasClientComposition: Invalid display %d", displayId);
         return true;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 30a4d79..4d04072 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1058,8 +1058,13 @@
 }
 
 HWC2::Composition Layer::getCompositionType(int32_t hwcId) const {
+    if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+        // If we're querying the composition type for a display that does not
+        // have a HWC counterpart, then it will always be Client
+        return HWC2::Composition::Client;
+    }
     if (mHwcLayers.count(hwcId) == 0) {
-        ALOGE("getCompositionType called without a valid HWC layer");
+        ALOGE("getCompositionType called with an invalid HWC layer");
         return HWC2::Composition::Invalid;
     }
     return mHwcLayers.at(hwcId).compositionType;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4d82c1ca..e2bd19f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1063,7 +1063,13 @@
     postComposition(refreshStartTime);
 
     mPreviousPresentFence = mHwc->getRetireFence(HWC_DISPLAY_PRIMARY);
-    mHadClientComposition = mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY);
+
+    mHadClientComposition = false;
+    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+        const sp<DisplayDevice>& displayDevice = mDisplays[displayId];
+        mHadClientComposition = mHadClientComposition ||
+                mHwc->hasClientComposition(displayDevice->getHwcDisplayId());
+    }
 
     // Release any buffers which were replaced this frame
     for (auto& layer : mLayersWithQueuedFrames) {
@@ -3603,6 +3609,14 @@
     // create a surface (because we're a producer, and we need to
     // dequeue/queue a buffer)
     sp<Surface> sur = new Surface(producer, false);
+
+    // Put the screenshot Surface into async mode so that
+    // Layer::headFenceHasSignaled will always return true and we'll latch the
+    // first buffer regardless of whether or not its acquire fence has
+    // signaled. This is needed to avoid a race condition in the rotation
+    // animation. See b/30209608
+    sur->setAsyncMode(true);
+
     ANativeWindow* window = sur.get();
 
     status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);