Merge "SF: adapt region sampling to display orientation" into qt-dev
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index d66066e..c80ae3b 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -128,6 +128,10 @@
             ],
         },
     },
+
+    // Needs to be wherever installd is as it's execed by
+    // installd.
+    required: [ "migrate_legacy_obb_data.sh" ],
 }
 
 // OTA chroot tool
@@ -254,3 +258,9 @@
         "otapreopt_slot",
     ],
 }
+
+// Script to migrate legacy obb data.
+sh_binary {
+    name: "migrate_legacy_obb_data.sh",
+    src: "migrate_legacy_obb_data.sh"
+}
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 1384285..caac2e8 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -2816,5 +2816,16 @@
     return ok();
 }
 
+binder::Status InstalldNativeService::migrateLegacyObbData() {
+    ENFORCE_UID(AID_SYSTEM);
+    // NOTE: The lint warning doesn't apply to the use of system(3) with
+    // absolute parse and no command line arguments.
+    if (system("/system/bin/migrate_legacy_obb_data.sh") != 0) { // NOLINT(cert-env33-c)
+        LOG(ERROR) << "Unable to migrate legacy obb data";
+    }
+
+    return ok();
+}
+
 }  // namespace installd
 }  // namespace android
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 0e91cb2..2b7bf33 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -155,6 +155,8 @@
             const std::string& codePath, const std::unique_ptr<std::string>& dexMetadata,
             bool* _aidl_return);
 
+    binder::Status migrateLegacyObbData();
+
 private:
     std::recursive_mutex mLock;
 
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 4610a66..26e9984 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -112,6 +112,8 @@
     void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
             int userId, long ceSnapshotInode, int snapshotId, int storageFlags);
 
+    void migrateLegacyObbData();
+
     const int FLAG_STORAGE_DE = 0x1;
     const int FLAG_STORAGE_CE = 0x2;
     const int FLAG_STORAGE_EXTERNAL = 0x4;
diff --git a/cmds/installd/migrate_legacy_obb_data.sh b/cmds/installd/migrate_legacy_obb_data.sh
new file mode 100644
index 0000000..4f8a1ec
--- /dev/null
+++ b/cmds/installd/migrate_legacy_obb_data.sh
@@ -0,0 +1,27 @@
+#!/system/bin/sh
+
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if ! test -d /data/media/obb ; then
+  log -p i -t migrate_legacy_obb_data "No legacy obb data to migrate."
+  exit 0
+fi
+
+log -p i -t migrate_legacy_obb_data "Migrating legacy obb data."
+rm -rf /data/media/0/Android/obb
+cp -F -p -R -P -d /data/media/obb /data/media/0/Android
+rm -rf /data/media/obb
+log -p i -t migrate_legacy_obb_data "Done."
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 3928bb9..9c311a3 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -274,8 +274,12 @@
         // This check is only done if a buffer has already been queued
         if (mCore->mBufferHasBeenQueued &&
                 dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
-            BQ_LOGE("%s: attempting to exceed the max dequeued buffer count "
-                    "(%d)", callerString, mCore->mMaxDequeuedBufferCount);
+            // Supress error logs when timeout is non-negative.
+            if (mDequeueTimeout < 0) {
+                BQ_LOGE("%s: attempting to exceed the max dequeued buffer "
+                        "count (%d)", callerString,
+                        mCore->mMaxDequeuedBufferCount);
+            }
             return INVALID_OPERATION;
         }
 
@@ -882,7 +886,7 @@
         item.mFence = acquireFence;
         item.mFenceTime = acquireFenceTime;
         item.mIsDroppable = mCore->mAsyncMode ||
-                (!mCore->mLegacyBufferDrop && mConsumerIsSurfaceFlinger) ||
+                (mConsumerIsSurfaceFlinger && mCore->mQueueBufferCanDrop) ||
                 (mCore->mLegacyBufferDrop && mCore->mQueueBufferCanDrop) ||
                 (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
         item.mSurfaceDamage = surfaceDamage;
@@ -1493,7 +1497,9 @@
     BQ_LOGV("setDequeueTimeout: %" PRId64, timeout);
 
     std::lock_guard<std::mutex> lock(mCore->mMutex);
-    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, false,
+    bool dequeueBufferCannotBlock =
+            timeout >= 0 ? false : mCore->mDequeueBufferCannotBlock;
+    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, dequeueBufferCannotBlock,
             mCore->mMaxBufferCount) - mCore->getMaxBufferCountLocked();
     if (!mCore->adjustAvailableSlotsLocked(delta)) {
         BQ_LOGE("setDequeueTimeout: BufferQueue failed to adjust the number of "
@@ -1502,11 +1508,9 @@
     }
 
     mDequeueTimeout = timeout;
-    if (timeout >= 0) {
-        mCore->mDequeueBufferCannotBlock = false;
-        if (timeout != 0) {
-            mCore->mQueueBufferCanDrop = false;
-        }
+    mCore->mDequeueBufferCannotBlock = dequeueBufferCannotBlock;
+    if (timeout > 0) {
+        mCore->mQueueBufferCanDrop = false;
     }
 
     VALIDATE_CONSISTENCY();
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 9c0ee99..690a85f 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -233,7 +233,8 @@
 
     // mLegacyBufferDrop indicates whether mQueueBufferCanDrop is in effect.
     // If this flag is set mQueueBufferCanDrop is working as explained. If not
-    // queueBuffer will not drop buffers unless consumer is SurfaceFlinger.
+    // queueBuffer will not drop buffers unless consumer is SurfaceFlinger and
+    // mQueueBufferCanDrop is set.
     bool mLegacyBufferDrop;
 
     // mDefaultBufferFormat can be set so it will override the buffer format
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 2a5a604..d02cb8e 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -84,6 +84,10 @@
     return a + alpha * (b - a);
 }
 
+inline static bool isPointerEvent(int32_t source) {
+    return (source & AINPUT_SOURCE_CLASS_POINTER) == AINPUT_SOURCE_CLASS_POINTER;
+}
+
 // --- InputMessage ---
 
 bool InputMessage::isValid(size_t actualSize) const {
@@ -637,6 +641,16 @@
                             mChannel->getName().c_str());
 #endif
                     break;
+                } else if (isPointerEvent(mMsg.body.motion.source) &&
+                        mMsg.body.motion.action == AMOTION_EVENT_ACTION_CANCEL) {
+                    // No need to process events that we are going to cancel anyways
+                    const size_t count = batch.samples.size();
+                    for (size_t i = 0; i < count; i++) {
+                        const InputMessage& msg = batch.samples.itemAt(i);
+                        sendFinishedSignal(msg.body.motion.seq, false);
+                    }
+                    batch.samples.removeItemsAt(0, count);
+                    mBatches.removeAt(batchIndex);
                 } else {
                     // We cannot append to the batch in progress, so we need to consume
                     // the previous batch right now and defer the new message until later.
@@ -759,8 +773,7 @@
 }
 
 void InputConsumer::updateTouchState(InputMessage& msg) {
-    if (!mResampleTouch ||
-            !(msg.body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
+    if (!mResampleTouch || !isPointerEvent(msg.body.motion.source)) {
         return;
     }
 
@@ -872,7 +885,7 @@
 void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
     const InputMessage* next) {
     if (!mResampleTouch
-            || !(event->getSource() & AINPUT_SOURCE_CLASS_POINTER)
+            || !(isPointerEvent(event->getSource()))
             || event->getAction() != AMOTION_EVENT_ACTION_MOVE) {
         return;
     }
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index eb970d9..8841a3b 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -71,6 +71,11 @@
     return false;
 }
 
+bool needsAndroidPEglMitigation() {
+    static const int32_t vndk_version = property_get_int32("ro.vndk.version", -1);
+    return vndk_version <= 28;
+}
+
 int egl_get_init_count(EGLDisplay dpy) {
     egl_display_t* eglDisplay = egl_display_t::get(dpy);
     return eglDisplay ? eglDisplay->getRefsCount() : 0;
@@ -384,6 +389,13 @@
             if (len) {
                 // NOTE: we could avoid the copy if we had strnstr.
                 const std::string ext(start, len);
+                // Mitigation for Android P vendor partitions: Adreno 530 driver shipped on
+                // some Android P vendor partitions this extension under the draft KHR name,
+                // but during Khronos review it was decided to demote it to EXT.
+                if (needsAndroidPEglMitigation() && ext == "EGL_EXT_image_gl_colorspace" &&
+                    findExtension(disp.queryString.extensions, "EGL_KHR_image_gl_colorspace")) {
+                    mExtensionString.append("EGL_EXT_image_gl_colorspace ");
+                }
                 if (findExtension(disp.queryString.extensions, ext.c_str(), len)) {
                     mExtensionString.append(ext + " ");
                 }
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 36856b7..e117314 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -43,6 +43,7 @@
 struct egl_connection_t;
 
 bool findExtension(const char* exts, const char* name, size_t nameLen = 0);
+bool needsAndroidPEglMitigation();
 
 // ----------------------------------------------------------------------------
 
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 34262f3..e996be6 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -1710,6 +1710,26 @@
     const egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_IMAGE_KHR;
 
+    std::vector<AttrType> strippedAttribs;
+    if (needsAndroidPEglMitigation()) {
+        // Mitigation for Android P vendor partitions: eglImageCreateKHR should accept
+        // EGL_GL_COLORSPACE_LINEAR_KHR, EGL_GL_COLORSPACE_SRGB_KHR and
+        // EGL_GL_COLORSPACE_DEFAULT_EXT if EGL_EXT_image_gl_colorspace is supported,
+        // but some drivers don't like the DEFAULT value and generate an error.
+        for (const AttrType *attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) {
+            if (attr[0] == EGL_GL_COLORSPACE_KHR &&
+                dp->haveExtension("EGL_EXT_image_gl_colorspace")) {
+                if (attr[1] != EGL_GL_COLORSPACE_LINEAR_KHR &&
+                    attr[1] != EGL_GL_COLORSPACE_SRGB_KHR) {
+                    continue;
+                }
+            }
+            strippedAttribs.push_back(attr[0]);
+            strippedAttribs.push_back(attr[1]);
+        }
+        strippedAttribs.push_back(EGL_NONE);
+    }
+
     ContextRef _c(dp.get(), ctx);
     egl_context_t* const c = _c.get();
 
@@ -1717,7 +1737,7 @@
     egl_connection_t* const cnx = &gEGLImpl;
     if (cnx->dso && eglCreateImageFunc) {
         result = eglCreateImageFunc(dp->disp.dpy, c ? c->context : EGL_NO_CONTEXT, target, buffer,
-                                    attrib_list);
+                                    needsAndroidPEglMitigation() ? strippedAttribs.data() : attrib_list);
     }
     return result;
 }
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index fcd4f29..717f317 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -45,7 +45,9 @@
 
 ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
 
-static status_t StatusFromResult(Result result) {
+namespace {
+
+status_t statusFromResult(Result result) {
     switch (result) {
         case Result::OK:
             return OK;
@@ -71,6 +73,8 @@
     INTERNAL_WAKE =  1 << 16,
 };
 
+}  // anonymous namespace
+
 void SensorsHalDeathReceivier::serviceDied(
         uint64_t /* cookie */,
         const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
@@ -105,7 +109,7 @@
     initializeSensorList();
 
     mIsDirectReportSupported =
-           (checkReturn(mSensors->unregisterDirectChannel(-1)) != Result::INVALID_OPERATION);
+            (checkReturnAndGetStatus(mSensors->unregisterDirectChannel(-1)) != INVALID_OPERATION);
 }
 
 void SensorDevice::initializeSensorList() {
@@ -122,7 +126,7 @@
                     convertToSensor(list[i], &sensor);
                     // Sanity check and clamp power if it is 0 (or close)
                     if (sensor.power < minPowerMa) {
-                        ALOGE("Reported power %f not deemed sane, clamping to %f",
+                        ALOGI("Reported power %f not deemed sane, clamping to %f",
                               sensor.power, minPowerMa);
                         sensor.power = minPowerMa;
                     }
@@ -217,10 +221,10 @@
                 mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
                 mWakeLockQueueFlag != nullptr);
 
-        status_t status = StatusFromResult(checkReturn(mSensors->initialize(
+        status_t status = checkReturnAndGetStatus(mSensors->initialize(
                 *mEventQueue->getDesc(),
                 *mWakeLockQueue->getDesc(),
-                new SensorsCallback())));
+                new SensorsCallback()));
 
         if (status != NO_ERROR) {
             connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
@@ -270,6 +274,8 @@
     bool didChange = false;
 
     if (oldSensorList.size() != newSensorList.size()) {
+        ALOGI("Sensor list size changed from %zu to %zu", oldSensorList.size(),
+              newSensorList.size());
         didChange = true;
     }
 
@@ -281,6 +287,7 @@
             if (prevSensor.handle == newSensor.handle) {
                 found = true;
                 if (!sensorIsEquivalent(prevSensor, newSensor)) {
+                    ALOGI("Sensor %s not equivalent to previous version", newSensor.name);
                     didChange = true;
                 }
             }
@@ -289,6 +296,7 @@
         if (!found) {
             // Could not find the new sensor in the old list of sensors, the lists must
             // have changed.
+            ALOGI("Sensor %s (handle %d) did not exist before", newSensor.name, newSensor.handle);
             didChange = true;
         }
     }
@@ -423,7 +431,7 @@
                         convertToSensorEvents(events, dynamicSensorsAdded, buffer);
                         err = (ssize_t)events.size();
                     } else {
-                        err = StatusFromResult(result);
+                        err = statusFromResult(result);
                     }
                 });
 
@@ -621,7 +629,7 @@
     if (actuateHardware) {
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
                  enabled);
-        err = StatusFromResult(checkReturn(mSensors->activate(handle, enabled)));
+        err = checkReturnAndGetStatus(mSensors->activate(handle, enabled));
         ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
                  strerror(-err));
 
@@ -694,9 +702,8 @@
     if (prevBestBatchParams != info.bestBatchParams) {
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH 0x%08x %" PRId64 " %" PRId64, handle,
                  info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
-        err = StatusFromResult(
-                checkReturn(mSensors->batch(
-                    handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch)));
+        err = checkReturnAndGetStatus(mSensors->batch(
+                handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch));
         if (err != NO_ERROR) {
             ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
                   mSensors.get(), handle, info.bestBatchParams.mTSample,
@@ -720,7 +727,7 @@
     if (mSensors == nullptr) return NO_INIT;
     if (isClientDisabled(ident)) return INVALID_OPERATION;
     ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
-    return StatusFromResult(checkReturn(mSensors->flush(handle)));
+    return checkReturnAndGetStatus(mSensors->flush(handle));
 }
 
 bool SensorDevice::isClientDisabled(void* ident) {
@@ -753,16 +760,14 @@
         const int sensor_handle = mActivationCount.keyAt(i);
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
                    sensor_handle);
-        status_t err = StatusFromResult(
-                checkReturn(mSensors->batch(
-                    sensor_handle,
-                    info.bestBatchParams.mTSample,
-                    info.bestBatchParams.mTBatch)));
+        status_t err = checkReturnAndGetStatus(mSensors->batch(
+                sensor_handle,
+                info.bestBatchParams.mTSample,
+                info.bestBatchParams.mTBatch));
         ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
 
         if (err == NO_ERROR) {
-            err = StatusFromResult(
-                    checkReturn(mSensors->activate(sensor_handle, 1 /* enabled */)));
+            err = checkReturnAndGetStatus(mSensors->activate(sensor_handle, 1 /* enabled */));
             ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
         }
 
@@ -810,14 +815,13 @@
     Event ev;
     convertFromSensorEvent(*injected_sensor_event, &ev);
 
-    return StatusFromResult(checkReturn(mSensors->injectSensorData(ev)));
+    return checkReturnAndGetStatus(mSensors->injectSensorData(ev));
 }
 
 status_t SensorDevice::setMode(uint32_t mode) {
     if (mSensors == nullptr) return NO_INIT;
-    return StatusFromResult(
-            checkReturn(mSensors->setOperationMode(
-                    static_cast<hardware::sensors::V1_0::OperationMode>(mode))));
+    return checkReturnAndGetStatus(mSensors->setOperationMode(
+            static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
 }
 
 int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
@@ -855,7 +859,7 @@
                 if (result == Result::OK) {
                     ret = channelHandle;
                 } else {
-                    ret = StatusFromResult(result);
+                    ret = statusFromResult(result);
                 }
             }));
     return ret;
@@ -894,12 +898,12 @@
     checkReturn(mSensors->configDirectReport(sensorHandle, channelHandle, rate,
             [&ret, rate] (auto result, auto token) {
                 if (rate == RateLevel::STOP) {
-                    ret = StatusFromResult(result);
+                    ret = statusFromResult(result);
                 } else {
                     if (result == Result::OK) {
                         ret = token;
                     } else {
-                        ret = StatusFromResult(result);
+                        ret = statusFromResult(result);
                     }
                 }
             }));
@@ -1008,7 +1012,7 @@
 }
 
 void SensorDevice::handleHidlDeath(const std::string & detail) {
-    if (!SensorDevice::getInstance().mSensors->supportsMessageQueues()) {
+    if (!mSensors->supportsMessageQueues()) {
         // restart is the only option at present.
         LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
     } else {
@@ -1016,5 +1020,10 @@
     }
 }
 
+status_t SensorDevice::checkReturnAndGetStatus(const Return<Result>& ret) {
+    checkReturn(ret);
+    return (!ret.isOk()) ? DEAD_OBJECT : statusFromResult(ret);
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index e8685c2..d2c6994 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -211,14 +211,14 @@
     status_t batchLocked(void* ident, int handle, int flags, int64_t samplingPeriodNs,
                          int64_t maxBatchReportLatencyNs);
 
-    static void handleHidlDeath(const std::string &detail);
+    void handleHidlDeath(const std::string &detail);
     template<typename T>
-    static Return<T> checkReturn(Return<T> &&ret) {
+    void checkReturn(const Return<T>& ret) {
         if (!ret.isOk()) {
             handleHidlDeath(ret.description());
         }
-        return std::move(ret);
     }
+    status_t checkReturnAndGetStatus(const Return<Result>& ret);
     //TODO(b/67425500): remove waiter after bug is resolved.
     sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 3012ed8..c463c4e 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -261,22 +261,6 @@
         mId(id),
         mIsConnected(false),
         mType(type) {
-    std::vector<Hwc2::DisplayCapability> tmpCapabilities;
-    auto error = static_cast<Error>(mComposer.getDisplayCapabilities(mId, &tmpCapabilities));
-    if (error == Error::None) {
-        for (auto capability : tmpCapabilities) {
-            mDisplayCapabilities.emplace(static_cast<DisplayCapability>(capability));
-        }
-    } else if (error == Error::Unsupported) {
-        if (capabilities.count(Capability::SkipClientColorTransform)) {
-            mDisplayCapabilities.emplace(DisplayCapability::SkipClientColorTransform);
-        }
-        bool dozeSupport = false;
-        error = static_cast<Error>(mComposer.getDozeSupport(mId, &dozeSupport));
-        if (error == Error::None && dozeSupport) {
-            mDisplayCapabilities.emplace(DisplayCapability::Doze);
-        }
-    }
     ALOGV("Created display %" PRIu64, id);
 }
 
@@ -660,6 +644,29 @@
 {
     auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
     auto intError = mComposer.setPowerMode(mId, intMode);
+
+    if (mode == PowerMode::On) {
+        std::call_once(mDisplayCapabilityQueryFlag, [this]() {
+            std::vector<Hwc2::DisplayCapability> tmpCapabilities;
+            auto error =
+                    static_cast<Error>(mComposer.getDisplayCapabilities(mId, &tmpCapabilities));
+            if (error == Error::None) {
+                for (auto capability : tmpCapabilities) {
+                    mDisplayCapabilities.emplace(static_cast<DisplayCapability>(capability));
+                }
+            } else if (error == Error::Unsupported) {
+                if (mCapabilities.count(Capability::SkipClientColorTransform)) {
+                    mDisplayCapabilities.emplace(DisplayCapability::SkipClientColorTransform);
+                }
+                bool dozeSupport = false;
+                error = static_cast<Error>(mComposer.getDozeSupport(mId, &dozeSupport));
+                if (error == Error::None && dozeSupport) {
+                    mDisplayCapabilities.emplace(DisplayCapability::Doze);
+                }
+            }
+        });
+    }
+
     return static_cast<Error>(intError);
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index e0a5ef1..b7cdf7f 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -356,6 +356,7 @@
     DisplayType mType;
     std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
     std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
+    std::once_flag mDisplayCapabilityQueryFlag;
     std::unordered_set<DisplayCapability> mDisplayCapabilities;
 };
 } // namespace impl
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
index b1bf4e2..5cf8eb1 100644
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ b/services/surfaceflinger/TransactionCompletedThread.cpp
@@ -219,6 +219,7 @@
 
     while (mKeepRunning) {
         mConditionVariable.wait(mMutex);
+        std::vector<ListenerStats> completedListenerStats;
 
         // For each listener
         auto completedTransactionsItr = mCompletedTransactions.begin();
@@ -264,11 +265,27 @@
             } else {
                 completedTransactionsItr++;
             }
+
+            completedListenerStats.push_back(std::move(listenerStats));
         }
 
         if (mPresentFence) {
             mPresentFence.clear();
         }
+
+        // If everyone else has dropped their reference to a layer and its listener is dead,
+        // we are about to cause the layer to be deleted. If this happens at the wrong time and
+        // we are holding mMutex, we will cause a deadlock.
+        //
+        // The deadlock happens because this thread is holding on to mMutex and when we delete
+        // the layer, it grabs SF's mStateLock. A different SF binder thread grabs mStateLock,
+        // then call's TransactionCompletedThread::run() which tries to grab mMutex.
+        //
+        // To avoid this deadlock, we need to unlock mMutex when dropping our last reference to
+        // to the layer.
+        mMutex.unlock();
+        completedListenerStats.clear();
+        mMutex.lock();
     }
 }
 
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 7c0ecb3..4f8ed1a 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -253,13 +253,16 @@
     static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_NORMAL;
 
     static void setupPreconditions(CompositionTest* test) {
-        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
-                                Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    setPowerMode(HWC_DISPLAY,
+                                 static_cast<Hwc2::IComposerClient::PowerMode>(
+                                         Derived::INIT_POWER_MODE)))
+                .WillOnce(Return(Error::NONE));
 
         FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, HWC2::DisplayType::Physical,
                                true /* isPrimary */)
                 .setCapabilities(&test->mDefaultCapabilities)
+                .setPowerMode(Derived::INIT_POWER_MODE)
                 .inject(&test->mFlinger, test->mComposer);
         Mock::VerifyAndClear(test->mComposer);
 
@@ -282,6 +285,13 @@
     }
 
     template <typename Case>
+    static void setupPreconditionCallExpectations(CompositionTest* test) {
+        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY, _))
+                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
+                                Return(Error::NONE)));
+    }
+
+    template <typename Case>
     static void setupCommonCompositionCallExpectations(CompositionTest* test) {
         EXPECT_CALL(*test->mComposer,
                     setColorTransform(HWC_DISPLAY, _, Hwc2::ColorTransform::IDENTITY))
@@ -393,6 +403,9 @@
     static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_OFF;
 
     template <typename Case>
+    static void setupPreconditionCallExpectations(CompositionTest*) {}
+
+    template <typename Case>
     static void setupCommonCompositionCallExpectations(CompositionTest* test) {
         EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
 
@@ -1022,6 +1035,7 @@
     using CompositionResult = CompositionResultCase;
 
     static void setupCommon(CompositionTest* test) {
+        Display::template setupPreconditionCallExpectations<ThisCase>(test);
         Display::setupPreconditions(test);
 
         auto layer = Layer::createLayer(test);
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 97f9e6a..5f58e7d 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -410,6 +410,7 @@
 
     // The HWC active configuration id
     static constexpr int HWC_ACTIVE_CONFIG_ID = 2001;
+    static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_NORMAL;
 
     static void injectPendingHotplugEvent(DisplayTransactionTest* test,
                                           HWC2::Connection connection) {
@@ -427,6 +428,7 @@
                 .setWidth(DisplayVariant::WIDTH)
                 .setHeight(DisplayVariant::HEIGHT)
                 .setActiveConfig(HWC_ACTIVE_CONFIG_ID)
+                .setPowerMode(INIT_POWER_MODE)
                 .inject(&test->mFlinger, test->mComposer);
     }
 
@@ -435,6 +437,10 @@
         EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
                 .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
                                 Return(Error::NONE)));
+        EXPECT_CALL(*test->mComposer,
+                    setPowerMode(HWC_DISPLAY_ID,
+                                 static_cast<Hwc2::IComposerClient::PowerMode>(INIT_POWER_MODE)))
+                .WillOnce(Return(Error::NONE));
         injectHwcDisplayWithNoDefaultCapabilities(test);
     }
 
@@ -467,9 +473,6 @@
                     getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
                                         IComposerClient::Attribute::DPI_Y, _))
                 .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
-        EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
-                .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
-                                Return(Error::NONE)));
 
         if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
             EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
@@ -1891,10 +1894,6 @@
     Case::Display::setupFramebufferConsumerBufferQueueCallExpectations(this);
     Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
 
-    EXPECT_CALL(*mComposer, getDisplayCapabilities(Case::Display::HWC_DISPLAY_ID, _))
-            .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
-                            Return(Error::NONE)));
-
     EXPECT_CALL(*surface, query(NATIVE_WINDOW_WIDTH, _))
             .WillRepeatedly(DoAll(SetArgPointee<1>(Case::Display::WIDTH), Return(NO_ERROR)));
     EXPECT_CALL(*surface, query(NATIVE_WINDOW_HEIGHT, _))
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index df14e7e..64d34ee 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -386,6 +386,7 @@
         static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
         static constexpr int32_t DEFAULT_DPI = 320;
         static constexpr int32_t DEFAULT_ACTIVE_CONFIG = 0;
+        static constexpr int32_t DEFAULT_POWER_MODE = 2;
 
         FakeHwcDisplayInjector(DisplayId displayId, HWC2::DisplayType hwcDisplayType,
                                bool isPrimary)
@@ -431,6 +432,11 @@
             return *this;
         }
 
+        auto& setPowerMode(int mode) {
+            mPowerMode = mode;
+            return *this;
+        }
+
         void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
             static const std::unordered_set<HWC2::Capability> defaultCapabilities;
             if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities;
@@ -450,6 +456,7 @@
             config.setDpiY(mDpiY);
             display->mutableConfigs().emplace(mActiveConfig, config.build());
             display->mutableIsConnected() = true;
+            display->setPowerMode(static_cast<HWC2::PowerMode>(mPowerMode));
 
             flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = display.get();
 
@@ -474,6 +481,7 @@
         int32_t mDpiX = DEFAULT_DPI;
         int32_t mDpiY = DEFAULT_DPI;
         int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG;
+        int32_t mPowerMode = DEFAULT_POWER_MODE;
         const std::unordered_set<HWC2::Capability>* mCapabilities = nullptr;
     };
 
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
index 7d73f06..268e4bd 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
@@ -13,12 +13,6 @@
  public:
   // VirtualTouchpad implementation:
   static std::unique_ptr<VirtualTouchpad> Create();
-  status_t Attach() override;
-  status_t Detach() override;
-  status_t Touch(int touchpad, float x, float y, float pressure) override;
-  status_t ButtonState(int touchpad, int buttons) override;
-  status_t Scroll(int touchpad, float x, float y) override;
-  void dumpInternal(String8& result) override;
 
  protected:
   VirtualTouchpadClient() {}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index e5f40aa..a8949d3 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -55,6 +55,22 @@
     // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
     VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
 
+int TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform) {
+    switch (transform) {
+        // TODO: See TODO in TranslateNativeToVulkanTransform
+        case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_180;
+        case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_270;
+        case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+        case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
+        default:
+            return 0;
+    }
+}
+
 VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) {
     // Native and Vulkan transforms are isomorphic, but are represented
     // differently. Vulkan transforms are built up of an optional horizontal
@@ -210,10 +226,12 @@
 struct Swapchain {
     Swapchain(Surface& surface_,
               uint32_t num_images_,
-              VkPresentModeKHR present_mode)
+              VkPresentModeKHR present_mode,
+              int pre_transform_)
         : surface(surface_),
           num_images(num_images_),
           mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR),
+          pre_transform(pre_transform_),
           frame_timestamps_enabled(false),
           shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
                  present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
@@ -235,6 +253,7 @@
     Surface& surface;
     uint32_t num_images;
     bool mailbox_mode;
+    int pre_transform;
     bool frame_timestamps_enabled;
     int64_t refresh_duration;
     bool shared;
@@ -1237,9 +1256,9 @@
                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     if (!mem)
         return VK_ERROR_OUT_OF_HOST_MEMORY;
-    Swapchain* swapchain =
-        new (mem) Swapchain(surface, num_images, create_info->presentMode);
-
+    Swapchain* swapchain = new (mem)
+        Swapchain(surface, num_images, create_info->presentMode,
+                  TranslateVulkanToNativeTransform(create_info->preTransform));
     // -- Dequeue all buffers and create a VkImage for each --
     // Any failures during or after this must cancel the dequeued buffers.
 
@@ -1713,6 +1732,19 @@
                 ReleaseSwapchainImage(device, window, fence, img);
                 OrphanSwapchain(device, &swapchain);
             }
+            int window_transform_hint;
+            err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
+                                &window_transform_hint);
+            if (err != 0) {
+                ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
+                      strerror(-err), err);
+                swapchain_result = WorstPresentResult(
+                    swapchain_result, VK_ERROR_SURFACE_LOST_KHR);
+            }
+            if (swapchain.pre_transform != window_transform_hint) {
+                swapchain_result =
+                    WorstPresentResult(swapchain_result, VK_SUBOPTIMAL_KHR);
+            }
         } else {
             ReleaseSwapchainImage(device, nullptr, fence, img);
             swapchain_result = VK_ERROR_OUT_OF_DATE_KHR;