Merge "Temprorarily opt out vrflinger_test from libcrt"
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index cf9d4c5..cc0a307 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -583,6 +583,21 @@
         }
         return error;
     }
+
+    virtual bool isColorManagementUsed() const {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::IS_COLOR_MANAGEMET_USED, data, &reply);
+        int32_t result = 0;
+        status_t err = reply.readInt32(&result);
+        if (err != NO_ERROR) {
+            ALOGE("ISurfaceComposer::isColorManagementUsed: error "
+                  "retrieving result: %s (%d)",
+                  strerror(-err), -err);
+            return false;
+        }
+        return result != 0;
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -920,6 +935,12 @@
             }
             return NO_ERROR;
         }
+        case IS_COLOR_MANAGEMET_USED: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            int32_t result = isColorManagementUsed() ? 1 : 0;
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
         default: {
             return BBinder::onTransact(code, data, reply, flags);
         }
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 781e062..35cb3be 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -282,6 +282,8 @@
 
     virtual status_t getCompositionPreference(ui::Dataspace* dataSpace,
                                               ui::PixelFormat* pixelFormat) const = 0;
+
+    virtual bool isColorManagementUsed() const = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -320,6 +322,7 @@
         GET_LAYER_DEBUG_INFO,
         CREATE_SCOPED_CONNECTION,
         GET_COMPOSITION_PREFERENCE,
+        IS_COLOR_MANAGEMET_USED,
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 500df05..25f762b 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -633,6 +633,8 @@
         return NO_ERROR;
     }
 
+    virtual bool isColorManagementUsed() const { return false; }
+
 protected:
     IBinder* onAsBinder() override { return nullptr; }
 
diff --git a/libs/vr/libbufferhub/buffer_hub_base.cpp b/libs/vr/libbufferhub/buffer_hub_base.cpp
index b4c5d42..68cc766 100644
--- a/libs/vr/libbufferhub/buffer_hub_base.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_base.cpp
@@ -123,17 +123,17 @@
   buffer_state_ = &metadata_header_->buffer_state;
   ALOGD_IF(TRACE,
            "BufferHubBase::ImportBuffer: id=%d, buffer_state=%" PRIx64 ".",
-           id(), buffer_state_->load());
+           id(), buffer_state_->load(std::memory_order_acquire));
   fence_state_ = &metadata_header_->fence_state;
   ALOGD_IF(TRACE,
            "BufferHubBase::ImportBuffer: id=%d, fence_state=%" PRIx64 ".", id(),
-           fence_state_->load());
+           fence_state_->load(std::memory_order_acquire));
   active_clients_bit_mask_ = &metadata_header_->active_clients_bit_mask;
   ALOGD_IF(
       TRACE,
       "BufferHubBase::ImportBuffer: id=%d, active_clients_bit_mask=%" PRIx64
       ".",
-      id(), active_clients_bit_mask_->load());
+      id(), active_clients_bit_mask_->load(std::memory_order_acquire));
 
   return 0;
 }
diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp
index a91e842..83d6951 100644
--- a/libs/vr/libbufferhub/consumer_buffer.cpp
+++ b/libs/vr/libbufferhub/consumer_buffer.cpp
@@ -38,7 +38,7 @@
   // Only check producer bit and this consumer buffer's particular consumer bit.
   // The buffer is can be acquired iff: 1) producer bit is set; 2) consumer bit
   // is not set.
-  uint64_t buffer_state = buffer_state_->load();
+  uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
   if (!BufferHubDefs::IsBufferPosted(buffer_state, client_state_mask())) {
     ALOGE("ConsumerBuffer::LocalAcquire: not posted, id=%d state=%" PRIx64
           " client_state_mask=%" PRIx64 ".",
@@ -57,7 +57,7 @@
     out_meta->user_metadata_ptr = 0;
   }
 
-  uint64_t fence_state = fence_state_->load();
+  uint64_t fence_state = fence_state_->load(std::memory_order_acquire);
   // If there is an acquire fence from producer, we need to return it.
   if (fence_state & BufferHubDefs::kProducerStateBit) {
     *out_fence = shared_acquire_fence_.Duplicate();
@@ -118,7 +118,7 @@
     return error;
 
   // Check invalid state transition.
-  uint64_t buffer_state = buffer_state_->load();
+  uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
   if (!BufferHubDefs::IsBufferAcquired(buffer_state)) {
     ALOGE("ConsumerBuffer::LocalRelease: not acquired id=%d state=%" PRIx64 ".",
           id(), buffer_state);
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
index 1ea8302..09feb73 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
@@ -90,7 +90,9 @@
   int cid() const { return cid_; }
 
   // Returns the buffer buffer state.
-  uint64_t buffer_state() { return buffer_state_->load(); };
+  uint64_t buffer_state() {
+    return buffer_state_->load(std::memory_order_acquire);
+  };
 
   // A state mask which is unique to a buffer hub client among all its siblings
   // sharing the same concrete graphic buffer.
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
index 489692b..80a00be 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
@@ -40,7 +40,7 @@
   uint64_t old_state;
   uint64_t new_state;
   do {
-    old_state = buffer_state->load();
+    old_state = buffer_state->load(std::memory_order_acquire);
     new_state = (old_state & ~clear_mask) | set_mask;
   } while (!buffer_state->compare_exchange_weak(old_state, new_state));
 }
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index 3730e7d..10517c5 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -80,7 +80,7 @@
     return error;
 
   // Check invalid state transition.
-  uint64_t buffer_state = buffer_state_->load();
+  uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
   if (!BufferHubDefs::IsBufferGained(buffer_state)) {
     ALOGE("ProducerBuffer::LocalPost: not gained, id=%d state=%" PRIx64 ".",
           id(), buffer_state);
@@ -135,7 +135,7 @@
 
 int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta,
                               LocalHandle* out_fence, bool gain_posted_buffer) {
-  uint64_t buffer_state = buffer_state_->load();
+  uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
   ALOGD_IF(TRACE, "ProducerBuffer::LocalGain: buffer=%d, state=%" PRIx64 ".",
            id(), buffer_state);
 
@@ -168,7 +168,7 @@
     out_meta->user_metadata_ptr = 0;
   }
 
-  uint64_t fence_state = fence_state_->load();
+  uint64_t fence_state = fence_state_->load(std::memory_order_acquire);
   // If there is an release fence from consumer, we need to return it.
   if (fence_state & BufferHubDefs::kConsumerStateMask) {
     *out_fence = shared_release_fence_.Duplicate();
@@ -230,7 +230,7 @@
 
   // TODO(b/112338294) Keep here for reference. Remove it after new logic is
   // written.
-  /* uint64_t buffer_state = buffer_state_->load();
+  /* uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
   if (!BufferHubDefs::IsBufferGained(buffer_state)) {
     // Can only detach a ProducerBuffer when it's in gained state.
     ALOGW("ProducerBuffer::Detach: The buffer (id=%d, state=0x%" PRIx64
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 922be02..3d1eb14 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -275,10 +275,24 @@
     return (void*)hnd;
 }
 
-void Loader::close(void* driver)
+void Loader::close(egl_connection_t* cnx)
 {
-    driver_t* hnd = (driver_t*)driver;
+    driver_t* hnd = (driver_t*) cnx->dso;
     delete hnd;
+    cnx->dso = nullptr;
+
+    if (cnx->featureSo) {
+        dlclose(cnx->featureSo);
+        cnx->featureSo = nullptr;
+    }
+
+    cnx->angleDecided = false;
+    cnx->useAngle = false;
+
+    if (cnx->vendorEGL) {
+        dlclose(cnx->vendorEGL);
+        cnx->vendorEGL = nullptr;
+    }
 }
 
 void Loader::init_api(void* dso,
@@ -553,15 +567,9 @@
         property_get("ro.product.manufacturer", manufacturer, "UNSET");
         property_get("ro.product.model", model, "UNSET");
 
-        // Check if ANGLE is enabled. Workaround for b/118375731
-        // We suspect that loading & unloading a library somehow corrupts
-        // the process.
-        property_get("debug.angle.enable", prop, "0");
-        if (atoi(prop)) {
-            so = load_angle_from_namespace("feature_support", ns);
-        }
-        if (so) {
-            ALOGV("Temporarily loaded ANGLE's opt-in/out logic from namespace");
+        cnx->featureSo = load_angle_from_namespace("feature_support", ns);
+        if (cnx->featureSo) {
+            ALOGV("loaded ANGLE's opt-in/out logic from namespace");
             bool use_version0_API = false;
             bool use_version1_API = false;
             fpANGLEGetUtilityAPI ANGLEGetUtilityAPI =
@@ -605,14 +613,11 @@
                     ALOGW("Cannot find ANGLEUseForApplication in library");
                 }
             }
-            ALOGV("Close temporarily-loaded ANGLE opt-in/out logic");
-            dlclose(so);
-            so = nullptr;
         } else {
             // We weren't able to load and call the updateable opt-in/out logic.
             // If we can't load the library, there is no ANGLE available.
             use_angle = false;
-            ALOGV("Could not temporarily-load the ANGLE opt-in/out logic, cannot use ANGLE.");
+            ALOGV("Could not load the ANGLE opt-in/out logic, cannot use ANGLE.");
         }
         cnx->angleDecided = true;
     }
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 9cc73f3..392887d 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -51,7 +51,7 @@
     ~Loader();
 
     void* open(egl_connection_t* cnx);
-    void close(void* driver);
+    void close(egl_connection_t* cnx);
 
 private:
     Loader();
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 94af2e7..7cf58b4 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -275,8 +275,7 @@
 
         disp.dpy = dpy;
         if (dpy == EGL_NO_DISPLAY) {
-            loader.close(cnx->dso);
-            cnx->dso = nullptr;
+            loader.close(cnx);
         }
     }
 
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index e19fa38..cca0053 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -80,6 +80,7 @@
     bool                useAngle;
     EGLint              angleBackend;
     void*               vendorEGL;
+    void*               featureSo;
 };
 // clang-format on
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ab07bc6..fc8ca54 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -513,6 +513,10 @@
     return mDisplayTokens[id];
 }
 
+bool SurfaceFlinger::isColorManagementUsed() const {
+    return useColorManagement;
+}
+
 void SurfaceFlinger::bootFinished()
 {
     if (mStartPropertySetThread->join() != NO_ERROR) {
@@ -4744,6 +4748,7 @@
         case SET_TRANSACTION_STATE:
         // Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h
         case CREATE_SCOPED_CONNECTION:
+        case IS_COLOR_MANAGEMET_USED:
         case GET_COMPOSITION_PREFERENCE: {
             return OK;
         }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9e47b3f..73c9d95 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -462,6 +462,7 @@
     virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const;
     status_t getCompositionPreference(ui::Dataspace* outDataSpace,
                                       ui::PixelFormat* outPixelFormat) const override;
+    virtual bool isColorManagementUsed() const;
 
     /* ------------------------------------------------------------------------
      * DeathRecipient interface
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 43fa262..c219afd 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -451,6 +451,8 @@
 }
 
 void TimeStats::flushPowerTimeLocked() {
+    if (!mEnabled.load()) return;
+
     nsecs_t curTime = systemTime();
     // elapsedTime is in milliseconds.
     int64_t elapsedTime = (curTime - mPowerTime.prevTime) / 1000000;
@@ -500,10 +502,14 @@
         ALOGV("GlobalPresentFenceTime[%" PRId64 "]",
               mGlobalRecord.presentFences.front()->getSignalTime());
 
-        const int32_t presentToPresentMs = msBetween(mGlobalRecord.prevPresentTime, curPresentTime);
-        ALOGV("Global present2present[%d]", presentToPresentMs);
+        if (mGlobalRecord.prevPresentTime != 0) {
+            const int32_t presentToPresentMs =
+                    msBetween(mGlobalRecord.prevPresentTime, curPresentTime);
+            ALOGV("Global present2present[%d] prev[%" PRId64 "] curr[%" PRId64 "]",
+                  presentToPresentMs, mGlobalRecord.prevPresentTime, curPresentTime);
+            mTimeStats.presentToPresent.insert(presentToPresentMs);
+        }
 
-        mTimeStats.presentToPresent.insert(presentToPresentMs);
         mGlobalRecord.prevPresentTime = curPresentTime;
         mGlobalRecord.presentFences.pop_front();
     }
@@ -514,7 +520,15 @@
 
     ATRACE_CALL();
     std::lock_guard<std::mutex> lock(mMutex);
-    if (presentFence == nullptr) {
+    if (presentFence == nullptr || !presentFence->isValid()) {
+        mGlobalRecord.prevPresentTime = 0;
+        return;
+    }
+
+    if (mPowerTime.powerMode != HWC_POWER_MODE_NORMAL) {
+        // Try flushing the last present fence on HWC_POWER_MODE_NORMAL.
+        flushAvailableGlobalRecordsToStatsLocked();
+        mGlobalRecord.presentFences.clear();
         mGlobalRecord.prevPresentTime = 0;
         return;
     }
@@ -537,10 +551,10 @@
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mMutex);
-    ALOGD("Enabled");
     mEnabled.store(true);
     mTimeStats.statsStart = static_cast<int64_t>(std::time(0));
     mPowerTime.prevTime = systemTime();
+    ALOGD("Enabled");
 }
 
 void TimeStats::disable() {
@@ -549,16 +563,17 @@
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mMutex);
-    ALOGD("Disabled");
+    flushPowerTimeLocked();
     mEnabled.store(false);
     mTimeStats.statsEnd = static_cast<int64_t>(std::time(0));
+    ALOGD("Disabled");
 }
 
 void TimeStats::clear() {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mMutex);
-    ALOGD("Cleared");
+    mTimeStatsTracker.clear();
     mTimeStats.stats.clear();
     mTimeStats.statsStart = (mEnabled.load() ? static_cast<int64_t>(std::time(0)) : 0);
     mTimeStats.statsEnd = 0;
@@ -568,6 +583,9 @@
     mTimeStats.displayOnTime = 0;
     mTimeStats.presentToPresent.hist.clear();
     mPowerTime.prevTime = systemTime();
+    mGlobalRecord.prevPresentTime = 0;
+    mGlobalRecord.presentFences.clear();
+    ALOGD("Cleared");
 }
 
 bool TimeStats::isEnabled() {
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
index c701224..599ff5c 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
@@ -39,7 +39,7 @@
     if (delta < 0) return;
     // std::lower_bound won't work on out of range values
     if (delta > histogramConfig[HISTOGRAM_SIZE - 1]) {
-        hist[histogramConfig[HISTOGRAM_SIZE - 1]]++;
+        hist[histogramConfig[HISTOGRAM_SIZE - 1]] += delta / histogramConfig[HISTOGRAM_SIZE - 1];
         return;
     }
     auto iter = std::lower_bound(histogramConfig.begin(), histogramConfig.end(), delta);
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 3166a8c..c814142 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -30,6 +30,7 @@
 #include <gui/SurfaceComposerClient.h>
 #include <private/gui/ComposerService.h>
 
+#include <ui/ColorSpace.h>
 #include <ui/DisplayInfo.h>
 #include <ui/Rect.h>
 #include <utils/String8.h>
@@ -314,6 +315,10 @@
         ASSERT_EQ(NO_ERROR, mClient->initCheck()) << "failed to create SurfaceComposerClient";
 
         ASSERT_NO_FATAL_FAILURE(SetUpDisplay());
+
+        sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+        sp<IBinder> binder = sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
+        mColorManagementUsed = sf->isColorManagementUsed();
     }
 
     virtual void TearDown() {
@@ -470,6 +475,8 @@
     void setMatrixWithResizeHelper(uint32_t layerType);
 
     sp<SurfaceControl> mBlackBgSurface;
+    bool mColorManagementUsed;
+
 private:
     void SetUpDisplay() {
         mDisplay = mClient->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
@@ -2064,6 +2071,47 @@
     Transaction().setSidebandStream(layer, nullptr).apply();
 }
 
+class ColorTransformHelper {
+public:
+    static void DegammaColorSingle(half& s) {
+        if (s <= 0.03928f)
+            s = s / 12.92f;
+        else
+            s = pow((s + 0.055f) / 1.055f, 2.4f);
+    }
+
+    static void DegammaColor(half3& color) {
+        DegammaColorSingle(color.r);
+        DegammaColorSingle(color.g);
+        DegammaColorSingle(color.b);
+    }
+
+    static void GammaColorSingle(half& s) {
+        if (s <= 0.0031308f) {
+            s = s * 12.92f;
+        } else {
+            s = 1.055f * pow(s, (1.0f / 2.4f)) - 0.055f;
+        }
+    }
+
+    static void GammaColor(half3& color) {
+        GammaColorSingle(color.r);
+        GammaColorSingle(color.g);
+        GammaColorSingle(color.b);
+    }
+
+    static void applyMatrix(half3& color, const mat3& mat) {
+        half3 ret = half3(0);
+
+        for (int i = 0; i < 3; i++) {
+            for (int j = 0; j < 3; j++) {
+                ret[i] = ret[i] + color[j] * mat[j][i];
+            }
+        }
+        color = ret;
+    }
+};
+
 TEST_F(LayerTransactionTest, SetColorTransformBasic) {
     sp<SurfaceControl> colorLayer;
     ASSERT_NO_FATAL_FAILURE(
@@ -2076,19 +2124,35 @@
     }
 
     const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f);
-    const Color expected = {90, 90, 90, 255};
-    // this is handwavy, but the precison loss scaled by 255 (8-bit per
-    // channel) should be less than one
-    const uint8_t tolerance = 1;
+    half3 expected = color;
     mat3 matrix;
     matrix[0][0] = 0.3; matrix[1][0] = 0.59; matrix[2][0] = 0.11;
     matrix[0][1] = 0.3; matrix[1][1] = 0.59; matrix[2][1] = 0.11;
     matrix[0][2] = 0.3; matrix[1][2] = 0.59; matrix[2][2] = 0.11;
+
+    // degamma before applying the matrix
+    if (mColorManagementUsed) {
+        ColorTransformHelper::DegammaColor(expected);
+    }
+
+    ColorTransformHelper::applyMatrix(expected, matrix);
+
+    if (mColorManagementUsed) {
+        ColorTransformHelper::GammaColor(expected);
+    }
+
+    const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255),
+                                 uint8_t(expected.b * 255), 255};
+
+    // this is handwavy, but the precison loss scaled by 255 (8-bit per
+    // channel) should be less than one
+    const uint8_t tolerance = 1;
+
     Transaction().setColor(colorLayer, color)
         .setColorTransform(colorLayer, matrix, vec3()).apply();
     {
         SCOPED_TRACE("new color");
-        screenshot()->expectColor(Rect(0, 0, 32, 32), expected, tolerance);
+        screenshot()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance);
     }
 }
 
diff --git a/services/vr/bufferhubd/include/private/dvr/producer_channel.h b/services/vr/bufferhubd/include/private/dvr/producer_channel.h
index c4c2ad2..5868b09 100644
--- a/services/vr/bufferhubd/include/private/dvr/producer_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/producer_channel.h
@@ -42,7 +42,9 @@
 
   ~ProducerChannel() override;
 
-  uint64_t buffer_state() const { return buffer_state_->load(); }
+  uint64_t buffer_state() const {
+    return buffer_state_->load(std::memory_order_acquire);
+  }
 
   bool HandleMessage(Message& message) override;
   void HandleImpulse(Message& message) override;
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 476eca3..162065b 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -161,7 +161,8 @@
   ALOGD_IF(TRACE,
            "ProducerChannel::~ProducerChannel: channel_id=%d buffer_id=%d "
            "state=%" PRIx64 ".",
-           channel_id(), buffer_id(), buffer_state_->load());
+           channel_id(), buffer_id(),
+           buffer_state_->load(std::memory_order_acquire));
   for (auto consumer : consumer_channels_) {
     consumer->OnProducerClosed();
   }
@@ -177,7 +178,8 @@
 
   return BufferInfo(buffer_id(), consumer_channels_.size(), buffer_.width(),
                     buffer_.height(), buffer_.layer_count(), buffer_.format(),
-                    buffer_.usage(), pending_consumers_, buffer_state_->load(),
+                    buffer_.usage(), pending_consumers_,
+                    buffer_state_->load(std::memory_order_acquire),
                     signaled_mask, metadata_header_->queue_index);
 }
 
@@ -236,7 +238,7 @@
     Message& /*message*/) {
   ATRACE_NAME("ProducerChannel::OnGetBuffer");
   ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d, state=%" PRIx64 ".",
-           buffer_id(), buffer_state_->load());
+           buffer_id(), buffer_state_->load(std::memory_order_acquire));
   return {GetBuffer(BufferHubDefs::kProducerStateBit)};
 }
 
@@ -304,8 +306,8 @@
     return ErrorStatus(ENOMEM);
   }
 
-  if (!producer_owns_ &&
-      !BufferHubDefs::IsBufferReleased(buffer_state_->load())) {
+  if (!producer_owns_ && !BufferHubDefs::IsBufferReleased(
+                             buffer_state_->load(std::memory_order_acquire))) {
     // Signal the new consumer when adding it to a posted producer.
     if (consumer->OnProducerPosted())
       pending_consumers_++;
@@ -406,7 +408,7 @@
   ALOGD_IF(TRACE, "ProducerChannel::OnProducerDetach: buffer_id=%d",
            buffer_id());
 
-  uint64_t buffer_state = buffer_state_->load();
+  uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
   if (!BufferHubDefs::IsBufferGained(buffer_state)) {
     // Can only detach a BufferProducer when it's in gained state.
     ALOGW(
@@ -506,7 +508,7 @@
     ALOGD_IF(TRACE,
              "ProducerChannel::OnConsumerRelease: releasing last consumer: "
              "buffer_id=%d state=%" PRIx64 ".",
-             buffer_id(), buffer_state_->load());
+             buffer_id(), buffer_state_->load(std::memory_order_acquire));
 
     if (orphaned_consumer_bit_mask_) {
       ALOGW(
@@ -521,11 +523,12 @@
     SignalAvailable();
   }
 
-  ALOGE_IF(pending_consumers_ &&
-               BufferHubDefs::IsBufferReleased(buffer_state_->load()),
-           "ProducerChannel::OnConsumerRelease: buffer state inconsistent: "
-           "pending_consumers=%d, buffer buffer is in releaed state.",
-           pending_consumers_);
+  ALOGE_IF(
+      pending_consumers_ && BufferHubDefs::IsBufferReleased(
+                                buffer_state_->load(std::memory_order_acquire)),
+      "ProducerChannel::OnConsumerRelease: buffer state inconsistent: "
+      "pending_consumers=%d, buffer buffer is in releaed state.",
+      pending_consumers_);
   return {};
 }
 
@@ -564,7 +567,8 @@
       "buffer_id=%d client_state_mask=%" PRIx64 " queue_index=%" PRIu64
       " buffer_state=%" PRIx64 " fence_state=%" PRIx64 ".",
       buffer_id(), client_state_mask, metadata_header_->queue_index,
-      buffer_state_->load(), fence_state_->load());
+      buffer_state_->load(std::memory_order_acquire),
+      fence_state_->load(std::memory_order_acquire));
 }
 
 void ProducerChannel::AddConsumer(ConsumerChannel* channel) {
@@ -579,7 +583,7 @@
   active_clients_bit_mask_->fetch_and(~channel->client_state_mask(),
                                       std::memory_order_release);
 
-  const uint64_t buffer_state = buffer_state_->load();
+  const uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
   if (BufferHubDefs::IsBufferPosted(buffer_state) ||
       BufferHubDefs::IsBufferAcquired(buffer_state)) {
     // The consumer client is being destoryed without releasing. This could
@@ -592,7 +596,8 @@
       BufferHubDefs::IsBufferGained(buffer_state)) {
     // The consumer is being close while it is suppose to signal a release
     // fence. Signal the dummy fence here.
-    if (fence_state_->load() & channel->client_state_mask()) {
+    if (fence_state_->load(std::memory_order_acquire) &
+        channel->client_state_mask()) {
       epoll_event event;
       event.events = EPOLLIN;
       event.data.u64 = channel->client_state_mask();