Merge "Moving /oat folder creation to installd." am: 58c115fb7f am: 0db247d996 am: fdd81785f2
am: 7d8313c0f1

Change-Id: Iebd7b1d3ed8d1b3a62678311fd21ce58928da19c
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 1a932c3..4f7cdf3 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,13 +4,16 @@
 [Builtin Hooks Options]
 # Only turn on clang-format check for the following subfolders.
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+               include/input/
                libs/binder/ndk/
                libs/graphicsenv/
                libs/gui/
+               libs/input/
                libs/renderengine/
                libs/ui/
                libs/vr/
                services/bufferhub/
+               services/inputflinger/
                services/surfaceflinger/
                services/vr/
 
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 26e9984..d99bcc8 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -127,4 +127,6 @@
 
     const int FLAG_USE_QUOTA = 0x1000;
     const int FLAG_FORCE = 0x2000;
+
+    const int FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES = 0x20000;
 }
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index ef2ad99..abb8368 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -130,7 +130,7 @@
 /**
  * Returns a sync fence that signals when the transaction has been presented.
  * The recipient of the callback takes ownership of the fence and is responsible for closing
- * it.
+ * it. If a device does not support present fences, a -1 will be returned.
  */
 int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface_transaction_stats)
                                                __INTRODUCED_IN(29);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 458961b..c389d18 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -616,7 +616,7 @@
     return err == NO_ERROR;
 }
 
-uid_t Parcel::readCallingWorkSourceUid()
+uid_t Parcel::readCallingWorkSourceUid() const
 {
     if (!mRequestHeaderPresent) {
         return IPCThreadState::kUnsetWorkSource;
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 0cdabb0..0046e3a 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -399,7 +399,7 @@
     bool                replaceCallingWorkSourceUid(uid_t uid);
     // Returns the work source provided by the caller. This can only be trusted for trusted calling
     // uid.
-    uid_t               readCallingWorkSourceUid();
+    uid_t               readCallingWorkSourceUid() const;
     void                readRequestHeaders() const;
 
 private:
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 5fd4a95..41cbde1 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -23,6 +23,7 @@
 #include <inttypes.h>
 
 #include <mutex>
+#include <optional>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -62,19 +63,20 @@
 static std::set<uint32_t> gAllFreqs;
 static unique_fd gMapFd;
 
-static bool readNumbersFromFile(const std::string &path, std::vector<uint32_t> *out) {
+static std::optional<std::vector<uint32_t>> readNumbersFromFile(const std::string &path) {
     std::string data;
 
-    if (!android::base::ReadFileToString(path, &data)) return false;
+    if (!android::base::ReadFileToString(path, &data)) return {};
 
     auto strings = android::base::Split(data, " \n");
+    std::vector<uint32_t> ret;
     for (const auto &s : strings) {
         if (s.empty()) continue;
         uint32_t n;
-        if (!android::base::ParseUint(s, &n)) return false;
-        out->emplace_back(n);
+        if (!android::base::ParseUint(s, &n)) return {};
+        ret.emplace_back(n);
     }
-    return true;
+    return ret;
 }
 
 static int isPolicyFile(const struct dirent *d) {
@@ -111,20 +113,22 @@
         for (const auto &name : {"available", "boost"}) {
             std::string path =
                     StringPrintf("%s/%s/scaling_%s_frequencies", basepath, policy.c_str(), name);
-            if (!readNumbersFromFile(path, &freqs)) return false;
+            auto nums = readNumbersFromFile(path);
+            if (!nums) return false;
+            freqs.insert(freqs.end(), nums->begin(), nums->end());
         }
         std::sort(freqs.begin(), freqs.end());
         gPolicyFreqs.emplace_back(freqs);
 
         for (auto freq : freqs) gAllFreqs.insert(freq);
 
-        std::vector<uint32_t> cpus;
         std::string path = StringPrintf("%s/%s/%s", basepath, policy.c_str(), "related_cpus");
-        if (!readNumbersFromFile(path, &cpus)) return false;
-        gPolicyCpus.emplace_back(cpus);
+        auto cpus = readNumbersFromFile(path);
+        if (!cpus) return false;
+        gPolicyCpus.emplace_back(*cpus);
     }
 
-    gMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times")};
+    gMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map")};
     if (gMapFd < 0) return false;
 
     gInitialized = true;
@@ -151,17 +155,15 @@
 }
 
 // Retrieve the times in ns that uid spent running at each CPU frequency and store in freqTimes.
-// Returns false on error. Otherwise, returns true and populates freqTimes with a vector of vectors
-// using the format:
+// Return contains no value on error, otherwise it contains a vector of vectors using the format:
 // [[t0_0, t0_1, ...],
 //  [t1_0, t1_1, ...], ...]
 // where ti_j is the ns that uid spent running on the ith cluster at that cluster's jth lowest freq.
-bool getUidCpuFreqTimes(uint32_t uid, std::vector<std::vector<uint64_t>> *freqTimes) {
-    if (!gInitialized && !initGlobals()) return false;
+std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid) {
+    if (!gInitialized && !initGlobals()) return {};
     time_key_t key = {.uid = uid, .freq = 0};
 
-    freqTimes->clear();
-    freqTimes->resize(gNPolicies);
+    std::vector<std::vector<uint64_t>> out(gNPolicies);
     std::vector<uint32_t> idxs(gNPolicies, 0);
 
     val_t value;
@@ -172,32 +174,32 @@
             if (errno == ENOENT)
                 memset(&value.ar, 0, sizeof(value.ar));
             else
-                return false;
+                return {};
         }
         for (uint32_t i = 0; i < gNPolicies; ++i) {
             if (idxs[i] == gPolicyFreqs[i].size() || freq != gPolicyFreqs[i][idxs[i]]) continue;
             uint64_t time = 0;
             for (uint32_t cpu : gPolicyCpus[i]) time += value.ar[cpu];
             idxs[i] += 1;
-            (*freqTimes)[i].emplace_back(time);
+            out[i].emplace_back(time);
         }
     }
 
-    return true;
+    return out;
 }
 
 // Retrieve the times in ns that each uid spent running at each CPU freq and store in freqTimeMap.
-// Returns false on error. Otherwise, returns true and populates freqTimeMap with a map from uids to
-// vectors of vectors using the format:
+// Return contains no value on error, otherwise it contains a map from uids to vectors of vectors
+// using the format:
 // { uid0 -> [[t0_0_0, t0_0_1, ...], [t0_1_0, t0_1_1, ...], ...],
 //   uid1 -> [[t1_0_0, t1_0_1, ...], [t1_1_0, t1_1_1, ...], ...], ... }
 // where ti_j_k is the ns uid i spent running on the jth cluster at the cluster's kth lowest freq.
-bool getUidsCpuFreqTimes(
-        std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> *freqTimeMap) {
-    if (!gInitialized && !initGlobals()) return false;
+std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>>
+getUidsCpuFreqTimes() {
+    if (!gInitialized && !initGlobals()) return {};
 
-    int fd = bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times");
-    if (fd < 0) return false;
+    int fd = bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map");
+    if (fd < 0) return {};
     BpfMap<time_key_t, val_t> m(fd);
 
     std::vector<std::unordered_map<uint32_t, uint32_t>> policyFreqIdxs;
@@ -206,25 +208,26 @@
         for (size_t j = 0; j < gPolicyFreqs[i].size(); ++j) freqIdxs[gPolicyFreqs[i][j]] = j;
         policyFreqIdxs.emplace_back(freqIdxs);
     }
-
-    auto fn = [freqTimeMap, &policyFreqIdxs](const time_key_t &key, const val_t &val,
+    std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> map;
+    auto fn = [&map, &policyFreqIdxs](const time_key_t &key, const val_t &val,
                                              const BpfMap<time_key_t, val_t> &) {
-        if (freqTimeMap->find(key.uid) == freqTimeMap->end()) {
-            (*freqTimeMap)[key.uid].resize(gNPolicies);
+        if (map.find(key.uid) == map.end()) {
+            map[key.uid].resize(gNPolicies);
             for (uint32_t i = 0; i < gNPolicies; ++i) {
-                (*freqTimeMap)[key.uid][i].resize(gPolicyFreqs[i].size(), 0);
+                map[key.uid][i].resize(gPolicyFreqs[i].size(), 0);
             }
         }
 
         for (size_t policy = 0; policy < gNPolicies; ++policy) {
             for (const auto &cpu : gPolicyCpus[policy]) {
                 auto freqIdx = policyFreqIdxs[policy][key.freq];
-                (*freqTimeMap)[key.uid][policy][freqIdx] += val.ar[cpu];
+                map[key.uid][policy][freqIdx] += val.ar[cpu];
             }
         }
         return android::netdutils::status::ok;
     };
-    return isOk(m.iterateWithValue(fn));
+    if (isOk(m.iterateWithValue(fn))) return map;
+    return {};
 }
 
 // Clear all time in state data for a given uid. Returns false on error, true otherwise.
diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h
index 9f6103e..d7b4587 100644
--- a/libs/cputimeinstate/cputimeinstate.h
+++ b/libs/cputimeinstate/cputimeinstate.h
@@ -23,8 +23,9 @@
 namespace bpf {
 
 bool startTrackingUidCpuFreqTimes();
-bool getUidCpuFreqTimes(unsigned int uid, std::vector<std::vector<uint64_t>> *freqTimes);
-bool getUidsCpuFreqTimes(std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> *tisMap);
+std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid);
+std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>>
+    getUidsCpuFreqTimes();
 bool clearUidCpuFreqTimes(unsigned int uid);
 
 } // namespace bpf
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index 9837865..d4b8738 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -12,45 +12,46 @@
 using std::vector;
 
 TEST(TimeInStateTest, SingleUid) {
-    vector<vector<uint64_t>> times;
-    ASSERT_TRUE(getUidCpuFreqTimes(0, &times));
-    EXPECT_FALSE(times.empty());
+    auto times = getUidCpuFreqTimes(0);
+    ASSERT_TRUE(times.has_value());
+    EXPECT_FALSE(times->empty());
 }
 
 TEST(TimeInStateTest, AllUid) {
     vector<size_t> sizes;
-    std::unordered_map<uint32_t, vector<vector<uint64_t>>> map;
-    ASSERT_TRUE(getUidsCpuFreqTimes(&map));
+    auto map = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map.has_value());
 
-    ASSERT_FALSE(map.empty());
+    ASSERT_FALSE(map->empty());
 
-    auto firstEntry = map.begin()->second;
+    auto firstEntry = map->begin()->second;
     for (const auto &subEntry : firstEntry) sizes.emplace_back(subEntry.size());
 
-    for (const auto &vec : map) {
+    for (const auto &vec : *map) {
         ASSERT_EQ(vec.second.size(), sizes.size());
         for (size_t i = 0; i < vec.second.size(); ++i) ASSERT_EQ(vec.second[i].size(), sizes[i]);
     }
 }
 
 TEST(TimeInStateTest, RemoveUid) {
-    vector<vector<uint64_t>> times, times2;
-    ASSERT_TRUE(getUidCpuFreqTimes(0, &times));
-    ASSERT_FALSE(times.empty());
+    auto times = getUidCpuFreqTimes(0);
+    ASSERT_TRUE(times.has_value());
+    ASSERT_FALSE(times->empty());
 
     uint64_t sum = 0;
-    for (size_t i = 0; i < times.size(); ++i) {
-        for (auto x : times[i]) sum += x;
+    for (size_t i = 0; i < times->size(); ++i) {
+        for (auto x : (*times)[i]) sum += x;
     }
     ASSERT_GT(sum, (uint64_t)0);
 
     ASSERT_TRUE(clearUidCpuFreqTimes(0));
 
-    ASSERT_TRUE(getUidCpuFreqTimes(0, &times2));
-    ASSERT_EQ(times2.size(), times.size());
-    for (size_t i = 0; i < times.size(); ++i) {
-        ASSERT_EQ(times2[i].size(), times[i].size());
-        for (size_t j = 0; j < times[i].size(); ++j) ASSERT_LE(times2[i][j], times[i][j]);
+    auto times2 = getUidCpuFreqTimes(0);
+    ASSERT_TRUE(times2.has_value());
+    ASSERT_EQ(times2->size(), times->size());
+    for (size_t i = 0; i < times->size(); ++i) {
+        ASSERT_EQ((*times2)[i].size(), (*times)[i].size());
+        for (size_t j = 0; j < (*times)[i].size(); ++j) ASSERT_LE((*times2)[i][j], (*times)[i][j]);
     }
 }
 
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 34575f5..b2a7557 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -15,6 +15,10 @@
     name: "libgui_headers",
     vendor_available: true,
     export_include_dirs: ["include"],
+
+    // we must build this module to get the required header as that is generated
+    export_shared_lib_headers: [ "android.hidl.token@1.0-utils" ],
+    shared_libs: [ "android.hidl.token@1.0-utils" ],
 }
 
 cc_library_shared {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 9c311a3..b9a4749 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1132,9 +1132,6 @@
         case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
             value = static_cast<int32_t>(mCore->mConsumerIsProtected);
             break;
-        case NATIVE_WINDOW_MAX_BUFFER_COUNT:
-            value = static_cast<int32_t>(mCore->mMaxBufferCount);
-            break;
         default:
             return BAD_VALUE;
     }
@@ -1199,6 +1196,7 @@
                     static_cast<uint32_t>(mCore->mQueue.size());
             output->nextFrameNumber = mCore->mFrameCounter + 1;
             output->bufferReplaced = false;
+            output->maxBufferCount = mCore->mMaxBufferCount;
 
             if (listener != nullptr) {
                 // Set up a death notification so that we can disconnect
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0e03b7d..9db0a7c 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -1141,12 +1141,8 @@
 
 // ----------------------------------------------------------------------------
 constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() {
-    return sizeof(width) +
-            sizeof(height) +
-            sizeof(transformHint) +
-            sizeof(numPendingBuffers) +
-            sizeof(nextFrameNumber) +
-            sizeof(bufferReplaced);
+    return sizeof(width) + sizeof(height) + sizeof(transformHint) + sizeof(numPendingBuffers) +
+            sizeof(nextFrameNumber) + sizeof(bufferReplaced) + sizeof(maxBufferCount);
 }
 
 size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const {
@@ -1170,6 +1166,7 @@
     FlattenableUtils::write(buffer, size, numPendingBuffers);
     FlattenableUtils::write(buffer, size, nextFrameNumber);
     FlattenableUtils::write(buffer, size, bufferReplaced);
+    FlattenableUtils::write(buffer, size, maxBufferCount);
 
     return frameTimestamps.flatten(buffer, size, fds, count);
 }
@@ -1187,6 +1184,7 @@
     FlattenableUtils::read(buffer, size, numPendingBuffers);
     FlattenableUtils::read(buffer, size, nextFrameNumber);
     FlattenableUtils::read(buffer, size, bufferReplaced);
+    FlattenableUtils::read(buffer, size, maxBufferCount);
 
     return frameTimestamps.unflatten(buffer, size, fds, count);
 }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e6eb327..2e8a5d0 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -96,6 +96,7 @@
     mConnectedToCpu = false;
     mProducerControlledByApp = controlledByApp;
     mSwapIntervalZero = false;
+    mMaxBufferCount = 0;
 }
 
 Surface::~Surface() {
@@ -961,6 +962,10 @@
                 *value = static_cast<int>(mDataSpace);
                 return NO_ERROR;
             }
+            case NATIVE_WINDOW_MAX_BUFFER_COUNT: {
+                *value = mMaxBufferCount;
+                return NO_ERROR;
+            }
         }
     }
     return mGraphicBufferProducer->query(what, value);
@@ -1298,6 +1303,7 @@
         mDefaultWidth = output.width;
         mDefaultHeight = output.height;
         mNextFrameNumber = output.nextFrameNumber;
+        mMaxBufferCount = output.maxBufferCount;
 
         // Ignore transform hint if sticky transform is set or transform to display inverse flag is
         // set. Transform hint should be ignored if the client is expected to always submit buffers
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index d6f88fc..c59fddf 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -322,10 +322,99 @@
         mTransactionNestCount(other.mTransactionNestCount),
         mAnimation(other.mAnimation),
         mEarlyWakeup(other.mEarlyWakeup),
+        mContainsBuffer(other.mContainsBuffer),
         mDesiredPresentTime(other.mDesiredPresentTime) {
     mDisplayStates = other.mDisplayStates;
     mComposerStates = other.mComposerStates;
     mInputWindowCommands = other.mInputWindowCommands;
+    mListenerCallbacks = other.mListenerCallbacks;
+}
+
+std::unique_ptr<SurfaceComposerClient::Transaction>
+SurfaceComposerClient::Transaction::createFromParcel(const Parcel* parcel) {
+    auto transaction = std::make_unique<Transaction>();
+    if (transaction->readFromParcel(parcel) == NO_ERROR) {
+        return transaction;
+    }
+    return nullptr;
+}
+
+status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) {
+    const uint32_t forceSynchronous = parcel->readUint32();
+    const uint32_t transactionNestCount = parcel->readUint32();
+    const bool animation = parcel->readBool();
+    const bool earlyWakeup = parcel->readBool();
+    const bool containsBuffer = parcel->readBool();
+    const int64_t desiredPresentTime = parcel->readInt64();
+
+    size_t count = static_cast<size_t>(parcel->readUint32());
+    if (count > parcel->dataSize()) {
+        return BAD_VALUE;
+    }
+    SortedVector<DisplayState> displayStates;
+    displayStates.setCapacity(count);
+    for (size_t i = 0; i < count; i++) {
+        DisplayState displayState;
+        if (displayState.read(*parcel) == BAD_VALUE) {
+            return BAD_VALUE;
+        }
+        displayStates.add(displayState);
+    }
+
+    count = static_cast<size_t>(parcel->readUint32());
+    if (count > parcel->dataSize()) {
+        return BAD_VALUE;
+    }
+    std::unordered_map<sp<SurfaceControl>, ComposerState, SCHash> composerStates;
+    composerStates.reserve(count);
+    for (size_t i = 0; i < count; i++) {
+        sp<SurfaceControl> surfaceControl = SurfaceControl::readFromParcel(parcel);
+
+        ComposerState composerState;
+        if (composerState.read(*parcel) == BAD_VALUE) {
+            return BAD_VALUE;
+        }
+        composerStates[surfaceControl] = composerState;
+    }
+
+    InputWindowCommands inputWindowCommands;
+    inputWindowCommands.read(*parcel);
+
+    // Parsing was successful. Update the object.
+    mForceSynchronous = forceSynchronous;
+    mTransactionNestCount = transactionNestCount;
+    mAnimation = animation;
+    mEarlyWakeup = earlyWakeup;
+    mContainsBuffer = containsBuffer;
+    mDesiredPresentTime = desiredPresentTime;
+    mDisplayStates = displayStates;
+    mComposerStates = composerStates;
+    mInputWindowCommands = inputWindowCommands;
+    // listener callbacks contain function pointer addresses and may not be safe to parcel.
+    mListenerCallbacks.clear();
+    return NO_ERROR;
+}
+
+status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const {
+    parcel->writeUint32(mForceSynchronous);
+    parcel->writeUint32(mTransactionNestCount);
+    parcel->writeBool(mAnimation);
+    parcel->writeBool(mEarlyWakeup);
+    parcel->writeBool(mContainsBuffer);
+    parcel->writeInt64(mDesiredPresentTime);
+    parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size()));
+    for (auto const& displayState : mDisplayStates) {
+        displayState.write(*parcel);
+    }
+
+    parcel->writeUint32(static_cast<uint32_t>(mComposerStates.size()));
+    for (auto const& [surfaceControl, composerState] : mComposerStates) {
+        surfaceControl->writeToParcel(parcel);
+        composerState.write(*parcel);
+    }
+
+    mInputWindowCommands.write(*parcel);
+    return NO_ERROR;
 }
 
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
@@ -336,7 +425,6 @@
             mComposerStates[kv.first].state.merge(kv.second.state);
         }
     }
-    other.mComposerStates.clear();
 
     for (auto const& state : other.mDisplayStates) {
         ssize_t index = mDisplayStates.indexOf(state);
@@ -346,7 +434,6 @@
             mDisplayStates.editItemAt(static_cast<size_t>(index)).merge(state);
         }
     }
-    other.mDisplayStates.clear();
 
     for (const auto& [listener, callbackInfo] : other.mListenerCallbacks) {
         auto& [callbackIds, surfaceControls] = callbackInfo;
@@ -357,17 +444,27 @@
                 .surfaceControls.insert(std::make_move_iterator(surfaceControls.begin()),
                                         std::make_move_iterator(surfaceControls.end()));
     }
-    other.mListenerCallbacks.clear();
 
     mInputWindowCommands.merge(other.mInputWindowCommands);
-    other.mInputWindowCommands.clear();
 
     mContainsBuffer = other.mContainsBuffer;
-    other.mContainsBuffer = false;
-
+    other.clear();
     return *this;
 }
 
+void SurfaceComposerClient::Transaction::clear() {
+    mComposerStates.clear();
+    mDisplayStates.clear();
+    mListenerCallbacks.clear();
+    mInputWindowCommands.clear();
+    mContainsBuffer = false;
+    mForceSynchronous = 0;
+    mTransactionNestCount = 0;
+    mAnimation = false;
+    mEarlyWakeup = false;
+    mDesiredPresentTime = -1;
+}
+
 void SurfaceComposerClient::doDropReferenceTransaction(const sp<IBinder>& handle,
         const sp<ISurfaceComposerClient>& client) {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
@@ -623,6 +720,7 @@
     layer_state_t* s = getLayerState(sc);
     if (!s) {
         mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eRelativeLayerChanged;
     s->what &= ~layer_state_t::eLayerChanged;
@@ -1052,6 +1150,7 @@
     layer_state_t* s = getLayerState(sc);
     if (!s) {
         mStatus = BAD_INDEX;
+        return *this;
     }
     s->what |= layer_state_t::eDetachChildren;
 
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 55488da..b9defdd 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -71,14 +71,6 @@
     release();
 }
 
-void SurfaceControl::destroy()
-{
-    if (isValid()) {
-        SurfaceComposerClient::Transaction().reparent(this, nullptr).apply();
-    }
-    release();
-}
-
 void SurfaceControl::release()
 {
     // Trigger an IPC now, to make sure things
@@ -186,8 +178,7 @@
     parcel->writeStrongBinder(IGraphicBufferProducer::asBinder(mGraphicBufferProducer));
 }
 
-sp<SurfaceControl> SurfaceControl::readFromParcel(Parcel* parcel)
-{
+sp<SurfaceControl> SurfaceControl::readFromParcel(const Parcel* parcel) {
     sp<IBinder> client = parcel->readStrongBinder();
     sp<IBinder> handle = parcel->readStrongBinder();
     if (client == nullptr || handle == nullptr)
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 3dde8c8..6e002dd 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -412,6 +412,7 @@
         uint64_t nextFrameNumber{0};
         FrameEventHistoryDelta frameTimestamps;
         bool bufferReplaced{false};
+        int maxBufferCount{0};
     };
 
     virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 0c471bb..80469df 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -465,6 +465,7 @@
 
     bool mReportRemovedBuffers = false;
     std::vector<sp<GraphicBuffer>> mRemovedBuffers;
+    int mMaxBufferCount;
 };
 
 } // namespace android
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 0e17c7b..4dda97f 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -285,7 +285,7 @@
         std::unordered_set<sp<SurfaceControl>, SCHash> surfaceControls;
     };
 
-    class Transaction {
+    class Transaction : Parcelable {
         std::unordered_map<sp<SurfaceControl>, ComposerState, SCHash> mComposerStates;
         SortedVector<DisplayState > mDisplayStates;
         std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash>
@@ -325,6 +325,15 @@
         virtual ~Transaction() = default;
         Transaction(Transaction const& other);
 
+        // Factory method that creates a new Transaction instance from the parcel.
+        static std::unique_ptr<Transaction> createFromParcel(const Parcel* parcel);
+
+        status_t writeToParcel(Parcel* parcel) const override;
+        status_t readFromParcel(const Parcel* parcel) override;
+
+        // Clears the contents of the transaction without applying it.
+        void clear();
+
         status_t apply(bool synchronous = false);
         // Merge another transaction in to this one, clearing other
         // as if it had been applied.
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index 23bfc02..ae4a146 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -44,7 +44,7 @@
 class SurfaceControl : public RefBase
 {
 public:
-    static sp<SurfaceControl> readFromParcel(Parcel* parcel);
+    static sp<SurfaceControl> readFromParcel(const Parcel* parcel);
     void writeToParcel(Parcel* parcel);
 
     static bool isValid(const sp<SurfaceControl>& surface) {
@@ -81,7 +81,7 @@
     status_t getLayerFrameStats(FrameStats* outStats) const;
 
     sp<SurfaceComposerClient> getClient() const;
-    
+
     explicit SurfaceControl(const sp<SurfaceControl>& other);
 
     SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 119e888..98dc1e6 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -169,6 +169,18 @@
     ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 }
 
+TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    mConsumer->consumerConnect(dc, false);
+    int bufferCount = 50;
+    mConsumer->setMaxBufferCount(bufferCount);
+
+    IGraphicBufferProducer::QueueBufferOutput output;
+    mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
+    ASSERT_EQ(output.maxBufferCount, bufferCount);
+}
+
 TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
     createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp
index d33ecfb..c9de37d 100644
--- a/libs/gui/tests/RegionSampling_test.cpp
+++ b/libs/gui/tests/RegionSampling_test.cpp
@@ -297,4 +297,70 @@
     composer->removeRegionSamplingListener(grayListener);
 }
 
+TEST_F(RegionSamplingTest, DISABLED_TestIfInvalidInputParameters) {
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<Listener> listener = new Listener();
+    const Rect sampleArea{100, 100, 200, 200};
+    // Invalid input sampleArea
+    EXPECT_EQ(BAD_VALUE,
+              composer->addRegionSamplingListener(Rect::INVALID_RECT, mTopLayer->getHandle(),
+                                                  listener));
+    listener->reset();
+    // Invalid input binder
+    EXPECT_EQ(NO_ERROR, composer->addRegionSamplingListener(sampleArea, NULL, listener));
+    // Invalid input listener
+    EXPECT_EQ(BAD_VALUE,
+              composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), NULL));
+    EXPECT_EQ(BAD_VALUE, composer->removeRegionSamplingListener(NULL));
+    // remove the listener
+    composer->removeRegionSamplingListener(listener);
+}
+
+TEST_F(RegionSamplingTest, DISABLED_TestCallbackAfterRemoveListener) {
+    fill_render(rgba_green);
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<Listener> listener = new Listener();
+    const Rect sampleArea{100, 100, 200, 200};
+    composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+    fill_render(rgba_green);
+
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_green, error_margin);
+
+    listener->reset();
+    composer->removeRegionSamplingListener(listener);
+    fill_render(rgba_green);
+    EXPECT_FALSE(listener->wait_event(100ms))
+            << "callback should stop after remove the region sampling listener";
+}
+
+TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromMovingLayer) {
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<Listener> listener = new Listener();
+    Rect sampleArea{100, 100, 200, 200};
+
+    // Test: listener in (100, 100). See layer before move, no layer after move.
+    fill_render(rgba_blue);
+    composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_blue, error_margin);
+    listener->reset();
+    SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply();
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_gray, error_margin);
+    composer->removeRegionSamplingListener(listener);
+
+    // Test: listener offset to (600, 600). No layer before move, see layer after move.
+    fill_render(rgba_green);
+    sampleArea.offsetTo(600, 600);
+    composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_gray, error_margin);
+    listener->reset();
+    SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply();
+    EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
+    EXPECT_NEAR(listener->luma(), luma_green, error_margin);
+    composer->removeRegionSamplingListener(listener);
+}
+
 } // namespace android::test
diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp
index 0c22bfe..56900c1 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -38,29 +38,29 @@
 KeyMap::~KeyMap() {
 }
 
-status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,
+status_t KeyMap::load(const InputDeviceIdentifier& deviceIdentifier,
         const PropertyMap* deviceConfiguration) {
     // Use the configured key layout if available.
     if (deviceConfiguration) {
         String8 keyLayoutName;
         if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
                 keyLayoutName)) {
-            status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName.c_str());
+            status_t status = loadKeyLayout(deviceIdentifier, keyLayoutName.c_str());
             if (status == NAME_NOT_FOUND) {
                 ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
                         "it was not found.",
-                        deviceIdenfifier.name.c_str(), keyLayoutName.string());
+                        deviceIdentifier.name.c_str(), keyLayoutName.string());
             }
         }
 
         String8 keyCharacterMapName;
         if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
                 keyCharacterMapName)) {
-            status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName.c_str());
+            status_t status = loadKeyCharacterMap(deviceIdentifier, keyCharacterMapName.c_str());
             if (status == NAME_NOT_FOUND) {
                 ALOGE("Configuration for keyboard device '%s' requested keyboard character "
                         "map '%s' but it was not found.",
-                        deviceIdenfifier.name.c_str(), keyLayoutName.string());
+                        deviceIdentifier.name.c_str(), keyCharacterMapName.string());
             }
         }
 
@@ -70,25 +70,25 @@
     }
 
     // Try searching by device identifier.
-    if (probeKeyMap(deviceIdenfifier, "")) {
+    if (probeKeyMap(deviceIdentifier, "")) {
         return OK;
     }
 
     // Fall back on the Generic key map.
     // TODO Apply some additional heuristics here to figure out what kind of
     //      generic key map to use (US English, etc.) for typical external keyboards.
-    if (probeKeyMap(deviceIdenfifier, "Generic")) {
+    if (probeKeyMap(deviceIdentifier, "Generic")) {
         return OK;
     }
 
     // Try the Virtual key map as a last resort.
-    if (probeKeyMap(deviceIdenfifier, "Virtual")) {
+    if (probeKeyMap(deviceIdentifier, "Virtual")) {
         return OK;
     }
 
     // Give up!
     ALOGE("Could not determine key map for device '%s' and no default key maps were found!",
-            deviceIdenfifier.name.c_str());
+            deviceIdentifier.name.c_str());
     return NAME_NOT_FOUND;
 }
 
diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp
index 115e866..7823e36 100644
--- a/libs/vr/libbufferhub/consumer_buffer.cpp
+++ b/libs/vr/libbufferhub/consumer_buffer.cpp
@@ -52,12 +52,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s Failed to acquire the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to acquire the buffer and modify the buffer state to "
-        "%" PRIx32 ". About to try again if the buffer is still posted.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
     if (!BufferHubDefs::isClientPosted(current_buffer_state,
                                        client_state_mask())) {
       ALOGE(
@@ -152,12 +146,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s: Failed to release the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to release the buffer and modify the buffer state to "
-        "%" PRIx32 ". About to try again.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
     // The failure of compare_exchange_weak updates current_buffer_state.
     updated_buffer_state = current_buffer_state & (~client_state_mask());
   }
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index 3d88ba5..aa9d072 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -96,13 +96,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s: Failed to post the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to post the buffer and modify the buffer state to "
-        "%" PRIx32
-        ". About to try again if the buffer is still gained by this client.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
     if (!BufferHubDefs::isClientGained(current_buffer_state,
                                        client_state_mask())) {
       ALOGE(
@@ -186,15 +179,6 @@
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
-    ALOGD(
-        "%s: Failed to gain the buffer. Current buffer state was changed to "
-        "%" PRIx32
-        " when trying to gain the buffer and modify the buffer state to "
-        "%" PRIx32
-        ". About to try again if the buffer is still not read by other "
-        "clients.",
-        __FUNCTION__, current_buffer_state, updated_buffer_state);
-
     if (BufferHubDefs::isAnyClientAcquired(current_buffer_state) ||
         BufferHubDefs::isAnyClientGained(current_buffer_state) ||
         (BufferHubDefs::isAnyClientPosted(
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index abc7a72..8144c8a 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -162,7 +162,7 @@
         "libEGL_getProcAddress",
         "libEGL_blobCache",
     ],
-    ldflags: ["-Wl,--exclude-libs=ALL"],
+    ldflags: ["-Wl,--exclude-libs=ALL,--Bsymbolic-functions"],
     export_include_dirs: ["EGL/include"],
 }
 
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index ce56272..af02314 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -28,7 +28,6 @@
 #include <sys/limits.h>
 #include <sys/inotify.h>
 #include <sys/ioctl.h>
-#include <sys/utsname.h>
 #include <unistd.h>
 
 #define LOG_TAG "EventHub"
@@ -94,14 +93,6 @@
     return out;
 }
 
-static void getLinuxRelease(int* major, int* minor) {
-    struct utsname info;
-    if (uname(&info) || sscanf(info.release, "%d.%d", major, minor) <= 0) {
-        *major = 0, *minor = 0;
-        ALOGE("Could not get linux version: %s", strerror(errno));
-    }
-}
-
 /**
  * Return true if name matches "v4l-touch*"
  */
@@ -292,11 +283,6 @@
     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
             errno);
-
-    int major, minor;
-    getLinuxRelease(&major, &minor);
-    // EPOLLWAKEUP was introduced in kernel 3.5
-    mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);
 }
 
 EventHub::~EventHub(void) {
@@ -1487,28 +1473,13 @@
         }
     }
 
-    std::string wakeMechanism = "EPOLLWAKEUP";
-    if (!mUsingEpollWakeup) {
-#ifndef EVIOCSSUSPENDBLOCK
-        // uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels
-        // will use an epoll flag instead, so as long as we want to support
-        // this feature, we need to be prepared to define the ioctl ourselves.
-#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
-#endif
-        if (ioctl(device->fd, EVIOCSSUSPENDBLOCK, 1)) {
-            wakeMechanism = "<none>";
-        } else {
-            wakeMechanism = "EVIOCSSUSPENDBLOCK";
-        }
-    }
     // Tell the kernel that we want to use the monotonic clock for reporting timestamps
     // associated with input events.  This is important because the input system
     // uses the timestamps extensively and assumes they were recorded using the monotonic
     // clock.
     int clockId = CLOCK_MONOTONIC;
     bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
-    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.c_str(),
-          toString(usingClockIoctl));
+    ALOGI("usingClockIoctl=%s", toString(usingClockIoctl));
 }
 
 void EventHub::openVideoDeviceLocked(const std::string& devicePath) {
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 63a20ef..eb4e8f2 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -479,8 +479,6 @@
     size_t mPendingEventCount;
     size_t mPendingEventIndex;
     bool mPendingINotify;
-
-    bool mUsingEpollWakeup;
 };
 
 }; // namespace android
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 5b298b4..6e953f4 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -149,7 +149,7 @@
         "Scheduler/DispSyncSource.cpp",
         "Scheduler/EventControlThread.cpp",
         "Scheduler/EventThread.cpp",
-        "Scheduler/IdleTimer.cpp",
+        "Scheduler/OneShotTimer.cpp",
         "Scheduler/LayerHistory.cpp",
         "Scheduler/LayerInfo.cpp",
         "Scheduler/MessageQueue.cpp",
diff --git a/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h b/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h
new file mode 100644
index 0000000..6741cc9
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <android-base/stringprintf.h>
+#include <gmock/gmock.h>
+
+namespace {
+
+using android::base::StringAppendF;
+using FloatRect = android::FloatRect;
+
+void dumpFloatRect(const FloatRect& rect, std::string& result, const char* name) {
+    StringAppendF(&result, "%s (%f %f %f %f) ", name, rect.left, rect.top, rect.right, rect.bottom);
+}
+
+// Checks for a region match
+MATCHER_P(FloatRectEq, expected, "") {
+    std::string buf;
+    buf.append("FloatRects are not equal\n");
+    dumpFloatRect(expected, buf, "expected rect");
+    dumpFloatRect(arg, buf, "actual rect");
+    *result_listener << buf;
+
+    const float TOLERANCE = 1e-3f;
+    return (std::fabs(expected.left - arg.left) < TOLERANCE) &&
+            (std::fabs(expected.top - arg.top) < TOLERANCE) &&
+            (std::fabs(expected.right - arg.right) < TOLERANCE) &&
+            (std::fabs(expected.bottom - arg.bottom) < TOLERANCE);
+}
+
+} // namespace
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 2060c5a..ae906cd 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -21,6 +21,7 @@
 #include <compositionengine/mock/Output.h>
 #include <gtest/gtest.h>
 
+#include "FloatRectMatcher.h"
 #include "MockHWC2.h"
 #include "MockHWComposer.h"
 #include "RectMatcher.h"
@@ -106,6 +107,114 @@
 }
 
 /*
+ * OutputLayer::calculateOutputSourceCrop()
+ */
+
+struct OutputLayerSourceCropTest : public OutputLayerTest {
+    OutputLayerSourceCropTest() {
+        // Set reasonable default values for a simple case. Each test will
+        // set one specific value to something different.
+        mLayerState.frontEnd.geomUsesSourceCrop = true;
+        mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080};
+        mLayerState.frontEnd.geomActiveTransparentRegion = Region{};
+        mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f};
+        mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT};
+        mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080};
+        mLayerState.frontEnd.geomBufferTransform = TR_IDENT;
+
+        mOutputState.viewport = Rect{0, 0, 1920, 1080};
+    }
+
+    FloatRect calculateOutputSourceCrop() {
+        mLayerState.frontEnd.geomInverseLayerTransform =
+                mLayerState.frontEnd.geomLayerTransform.inverse();
+
+        return mOutputLayer.calculateOutputSourceCrop();
+    }
+};
+
+TEST_F(OutputLayerSourceCropTest, computesEmptyIfSourceCropNotUsed) {
+    mLayerState.frontEnd.geomUsesSourceCrop = false;
+
+    const FloatRect expected{};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, correctForSimpleDefaultCase) {
+    const FloatRect expected{0.f, 0.f, 1920.f, 1080.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewport) {
+    mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f};
+
+    const FloatRect expected{0.f, 0.f, 1920.f, 1080.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewportRotated) {
+    mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f};
+    mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080);
+
+    const FloatRect expected{0.f, 0.f, 1080.f, 1080.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformedBuffer) {
+    struct Entry {
+        uint32_t bufferInvDisplay;
+        uint32_t buffer;
+        uint32_t display;
+        FloatRect expected;
+    };
+    // Not an exhaustive list of cases, but hopefully enough.
+    const std::array<Entry, 12> testData = {
+            // clang-format off
+            //             inv      buffer      display     expected
+            /*  0 */ Entry{false,   TR_IDENT,   TR_IDENT,   FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  1 */ Entry{false,   TR_IDENT,   TR_ROT_90,  FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  2 */ Entry{false,   TR_IDENT,   TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  3 */ Entry{false,   TR_IDENT,   TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+
+            /*  4 */ Entry{true,    TR_IDENT,   TR_IDENT,   FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  5 */ Entry{true,    TR_IDENT,   TR_ROT_90,  FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  6 */ Entry{true,    TR_IDENT,   TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  7 */ Entry{true,    TR_IDENT,   TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+
+            /*  8 */ Entry{false,   TR_IDENT,   TR_IDENT,   FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /*  9 */ Entry{false,   TR_ROT_90,  TR_ROT_90,  FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /* 10 */ Entry{false,   TR_ROT_180, TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+            /* 11 */ Entry{false,   TR_ROT_270, TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
+
+            // clang-format on
+    };
+
+    for (size_t i = 0; i < testData.size(); i++) {
+        const auto& entry = testData[i];
+
+        mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay;
+        mLayerState.frontEnd.geomBufferTransform = entry.buffer;
+        mOutputState.orientation = entry.display;
+
+        EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(entry.expected)) << "entry " << i;
+    }
+}
+
+TEST_F(OutputLayerSourceCropTest, geomContentCropAffectsCrop) {
+    mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 960, 540};
+
+    const FloatRect expected{0.f, 0.f, 960.f, 540.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+TEST_F(OutputLayerSourceCropTest, viewportAffectsCrop) {
+    mOutputState.viewport = Rect{0, 0, 960, 540};
+
+    const FloatRect expected{0.f, 0.f, 960.f, 540.f};
+    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+}
+
+/*
  * OutputLayer::calculateOutputDisplayFrame()
  */
 
@@ -163,7 +272,7 @@
     EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
 }
 
-TEST_F(OutputLayerDisplayFrameTest, geomLayerSnapToBoundsAffectsFrame) {
+TEST_F(OutputLayerDisplayFrameTest, geomLayerBoundsAffectsFrame) {
     mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f};
     const Rect expected{0, 0, 960, 540};
     EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
@@ -242,6 +351,159 @@
     }
 }
 
+TEST_F(OutputLayerTest,
+       calculateOutputRelativeBufferTransformTestWithOfBufferUsesDisplayInverseTransform) {
+    mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = true;
+
+    struct Entry {
+        uint32_t layer;
+        uint32_t buffer;
+        uint32_t display;
+        uint32_t expected;
+    };
+    // Not an exhaustive list of cases, but hopefully enough.
+    const std::array<Entry, 24> testData = {
+            // clang-format off
+            //             layer       buffer      display     expected
+            /*  0 */ Entry{TR_IDENT,   TR_IDENT,   TR_IDENT,   TR_IDENT},
+            /*  1 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_90,  TR_IDENT},
+            /*  2 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_180, TR_IDENT},
+            /*  3 */ Entry{TR_IDENT,   TR_IDENT,   TR_ROT_270, TR_IDENT},
+
+            /*  4 */ Entry{TR_IDENT,   TR_FLP_H,   TR_IDENT,   TR_FLP_H},
+            /*  5 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
+            /*  6 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_180, TR_FLP_H},
+            /*  7 */ Entry{TR_IDENT,   TR_FLP_H,   TR_ROT_270, TR_FLP_H},
+
+            /*  8 */ Entry{TR_IDENT,   TR_FLP_V,   TR_IDENT,   TR_FLP_V},
+            /*  9 */ Entry{TR_IDENT,   TR_ROT_90,  TR_ROT_90,  TR_ROT_90},
+            /* 10 */ Entry{TR_IDENT,   TR_ROT_180, TR_ROT_180, TR_ROT_180},
+            /* 11 */ Entry{TR_IDENT,   TR_ROT_270, TR_ROT_270, TR_ROT_270},
+
+            /* 12 */ Entry{TR_ROT_90,  TR_IDENT,   TR_IDENT,   TR_IDENT},
+            /* 13 */ Entry{TR_ROT_90,  TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
+            /* 14 */ Entry{TR_ROT_90,  TR_IDENT,   TR_ROT_180, TR_IDENT},
+            /* 15 */ Entry{TR_ROT_90,  TR_FLP_H,   TR_ROT_270, TR_FLP_H},
+
+            /* 16 */ Entry{TR_ROT_180, TR_FLP_H,   TR_IDENT,   TR_FLP_H},
+            /* 17 */ Entry{TR_ROT_180, TR_IDENT,   TR_ROT_90,  TR_IDENT},
+            /* 18 */ Entry{TR_ROT_180, TR_FLP_H,   TR_ROT_180, TR_FLP_H},
+            /* 19 */ Entry{TR_ROT_180, TR_IDENT,   TR_ROT_270, TR_IDENT},
+
+            /* 20 */ Entry{TR_ROT_270, TR_IDENT,   TR_IDENT,   TR_IDENT},
+            /* 21 */ Entry{TR_ROT_270, TR_FLP_H,   TR_ROT_90,  TR_FLP_H},
+            /* 22 */ Entry{TR_ROT_270, TR_FLP_H,   TR_ROT_180, TR_FLP_H},
+            /* 23 */ Entry{TR_ROT_270, TR_IDENT,   TR_ROT_270, TR_IDENT},
+            // clang-format on
+    };
+
+    for (size_t i = 0; i < testData.size(); i++) {
+        const auto& entry = testData[i];
+
+        mLayerState.frontEnd.geomLayerTransform = ui::Transform{entry.layer};
+        mLayerState.frontEnd.geomBufferTransform = entry.buffer;
+        mOutputState.orientation = entry.display;
+
+        auto actual = mOutputLayer.calculateOutputRelativeBufferTransform();
+        EXPECT_EQ(entry.expected, actual) << "entry " << i;
+    }
+}
+
+/*
+ * OutputLayer::updateCompositionState()
+ */
+
+struct OutputLayerPartialMockForUpdateCompositionState : public impl::OutputLayer {
+    OutputLayerPartialMockForUpdateCompositionState(const compositionengine::Output& output,
+                                                    std::shared_ptr<compositionengine::Layer> layer,
+                                                    sp<compositionengine::LayerFE> layerFE)
+          : impl::OutputLayer(output, layer, layerFE) {}
+    // Mock everything called by updateCompositionState to simplify testing it.
+    MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect());
+    MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect());
+    MOCK_CONST_METHOD0(calculateOutputRelativeBufferTransform, uint32_t());
+};
+
+struct OutputLayerUpdateCompositionStateTest : public OutputLayerTest {
+public:
+    OutputLayerUpdateCompositionStateTest() {
+        EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState));
+        EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState));
+    }
+
+    ~OutputLayerUpdateCompositionStateTest() = default;
+
+    void setupGeometryChildCallValues() {
+        EXPECT_CALL(mOutputLayer, calculateOutputSourceCrop()).WillOnce(Return(kSourceCrop));
+        EXPECT_CALL(mOutputLayer, calculateOutputDisplayFrame()).WillOnce(Return(kDisplayFrame));
+        EXPECT_CALL(mOutputLayer, calculateOutputRelativeBufferTransform())
+                .WillOnce(Return(mBufferTransform));
+    }
+
+    void validateComputedGeometryState() {
+        const auto& state = mOutputLayer.getState();
+        EXPECT_EQ(kSourceCrop, state.sourceCrop);
+        EXPECT_EQ(kDisplayFrame, state.displayFrame);
+        EXPECT_EQ(static_cast<Hwc2::Transform>(mBufferTransform), state.bufferTransform);
+    }
+
+    const FloatRect kSourceCrop{1.f, 2.f, 3.f, 4.f};
+    const Rect kDisplayFrame{11, 12, 13, 14};
+    uint32_t mBufferTransform{21};
+
+    using OutputLayer = OutputLayerPartialMockForUpdateCompositionState;
+    StrictMock<OutputLayer> mOutputLayer{mOutput, mLayer, mLayerFE};
+};
+
+TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) {
+    mLayerState.frontEnd.isSecure = true;
+    mOutputState.isSecure = true;
+
+    setupGeometryChildCallValues();
+
+    mOutputLayer.updateCompositionState(true);
+
+    validateComputedGeometryState();
+
+    EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest,
+       alsoSetsForceCompositionIfSecureLayerOnNonsecureOutput) {
+    mLayerState.frontEnd.isSecure = true;
+    mOutputState.isSecure = false;
+
+    setupGeometryChildCallValues();
+
+    mOutputLayer.updateCompositionState(true);
+
+    validateComputedGeometryState();
+
+    EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest,
+       alsoSetsForceCompositionIfUnsupportedBufferTransform) {
+    mLayerState.frontEnd.isSecure = true;
+    mOutputState.isSecure = true;
+
+    mBufferTransform = ui::Transform::ROT_INVALID;
+
+    setupGeometryChildCallValues();
+
+    mOutputLayer.updateCompositionState(true);
+
+    validateComputedGeometryState();
+
+    EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
+}
+
+TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) {
+    mOutputLayer.updateCompositionState(false);
+
+    EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition);
+}
+
 /*
  * OutputLayer::writeStateToHWC()
  */
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index bda7e43..b2df91d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -430,7 +430,7 @@
         auto& parentState = parent->getDrawingState();
         const int parentType = parentState.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
         const int parentAppId = parentState.metadata.getInt32(METADATA_OWNER_UID, 0);
-        if (parentType >= 0 || parentAppId >= 0) {
+        if (parentType > 0 && parentAppId > 0) {
             type = parentType;
             appId = parentAppId;
         }
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index 3c6fcf3..ac7339c 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -27,7 +27,7 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
 #include <utils/StrongPointer.h>
-#include "Scheduler/IdleTimer.h"
+#include "Scheduler/OneShotTimer.h"
 
 namespace android {
 
@@ -107,7 +107,7 @@
     SurfaceFlinger& mFlinger;
     Scheduler& mScheduler;
     const TimingTunables mTunables;
-    scheduler::IdleTimer mIdleTimer;
+    scheduler::OneShotTimer mIdleTimer;
 
     std::unique_ptr<SamplingOffsetCallback> const mPhaseCallback;
 
diff --git a/services/surfaceflinger/Scheduler/IdleTimer.cpp b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
similarity index 88%
rename from services/surfaceflinger/Scheduler/IdleTimer.cpp
rename to services/surfaceflinger/Scheduler/OneShotTimer.cpp
index 37fdfc7..4870a3b 100644
--- a/services/surfaceflinger/Scheduler/IdleTimer.cpp
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "IdleTimer.h"
+#include "OneShotTimer.h"
 
 #include <chrono>
 #include <thread>
@@ -22,23 +22,23 @@
 namespace android {
 namespace scheduler {
 
-IdleTimer::IdleTimer(const Interval& interval, const ResetCallback& resetCallback,
-                     const TimeoutCallback& timeoutCallback)
+OneShotTimer::OneShotTimer(const Interval& interval, const ResetCallback& resetCallback,
+                           const TimeoutCallback& timeoutCallback)
       : mInterval(interval), mResetCallback(resetCallback), mTimeoutCallback(timeoutCallback) {}
 
-IdleTimer::~IdleTimer() {
+OneShotTimer::~OneShotTimer() {
     stop();
 }
 
-void IdleTimer::start() {
+void OneShotTimer::start() {
     {
         std::lock_guard<std::mutex> lock(mMutex);
         mState = TimerState::RESET;
     }
-    mThread = std::thread(&IdleTimer::loop, this);
+    mThread = std::thread(&OneShotTimer::loop, this);
 }
 
-void IdleTimer::stop() {
+void OneShotTimer::stop() {
     {
         std::lock_guard<std::mutex> lock(mMutex);
         mState = TimerState::STOPPED;
@@ -49,7 +49,7 @@
     }
 }
 
-void IdleTimer::loop() {
+void OneShotTimer::loop() {
     while (true) {
         bool triggerReset = false;
         bool triggerTimeout = false;
@@ -100,7 +100,7 @@
     }
 } // namespace scheduler
 
-void IdleTimer::reset() {
+void OneShotTimer::reset() {
     {
         std::lock_guard<std::mutex> lock(mMutex);
         mState = TimerState::RESET;
diff --git a/services/surfaceflinger/Scheduler/IdleTimer.h b/services/surfaceflinger/Scheduler/OneShotTimer.h
similarity index 93%
rename from services/surfaceflinger/Scheduler/IdleTimer.h
rename to services/surfaceflinger/Scheduler/OneShotTimer.h
index 2646688..fd1aa02 100644
--- a/services/surfaceflinger/Scheduler/IdleTimer.h
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.h
@@ -29,15 +29,15 @@
  * Class that sets off a timer for a given interval, and fires a callback when the
  * interval expires.
  */
-class IdleTimer {
+class OneShotTimer {
 public:
     using Interval = std::chrono::milliseconds;
     using ResetCallback = std::function<void()>;
     using TimeoutCallback = std::function<void()>;
 
-    IdleTimer(const Interval& interval, const ResetCallback& resetCallback,
-              const TimeoutCallback& timeoutCallback);
-    ~IdleTimer();
+    OneShotTimer(const Interval& interval, const ResetCallback& resetCallback,
+                 const TimeoutCallback& timeoutCallback);
+    ~OneShotTimer();
 
     // Initializes and turns on the idle timer.
     void start();
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index bb24f73..e393f1b 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -38,9 +38,9 @@
 #include "DispSyncSource.h"
 #include "EventControlThread.h"
 #include "EventThread.h"
-#include "IdleTimer.h"
 #include "InjectVSyncSource.h"
 #include "LayerInfo.h"
+#include "OneShotTimer.h"
 #include "SchedulerUtils.h"
 #include "SurfaceFlingerProperties.h"
 
@@ -86,34 +86,29 @@
 
     if (mSetIdleTimerMs > 0) {
         if (mSupportKernelTimer) {
-            mIdleTimer =
-                    std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(
-                                                                   mSetIdleTimerMs),
-                                                           [this] { resetKernelTimerCallback(); },
-                                                           [this] {
-                                                               expiredKernelTimerCallback();
-                                                           });
+            mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
+                    std::chrono::milliseconds(mSetIdleTimerMs),
+                    [this] { resetKernelTimerCallback(); },
+                    [this] { expiredKernelTimerCallback(); });
         } else {
-            mIdleTimer = std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(
-                                                                        mSetIdleTimerMs),
-                                                                [this] { resetTimerCallback(); },
-                                                                [this] { expiredTimerCallback(); });
+            mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
+                    std::chrono::milliseconds(mSetIdleTimerMs), [this] { resetTimerCallback(); },
+                    [this] { expiredTimerCallback(); });
         }
         mIdleTimer->start();
     }
 
     if (mSetTouchTimerMs > 0) {
         // Touch events are coming to SF every 100ms, so the timer needs to be higher than that
-        mTouchTimer =
-                std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(mSetTouchTimerMs),
-                                                       [this] { resetTouchTimerCallback(); },
-                                                       [this] { expiredTouchTimerCallback(); });
+        mTouchTimer = std::make_unique<scheduler::OneShotTimer>(
+                std::chrono::milliseconds(mSetTouchTimerMs), [this] { resetTouchTimerCallback(); },
+                [this] { expiredTouchTimerCallback(); });
         mTouchTimer->start();
     }
 }
 
 Scheduler::~Scheduler() {
-    // Ensure the IdleTimer thread is joined before we start destroying state.
+    // Ensure the OneShotTimer threads are joined before we start destroying state.
     mTouchTimer.reset();
     mIdleTimer.reset();
 }
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index eaad37c..a307760 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -26,9 +26,9 @@
 #include "DispSync.h"
 #include "EventControlThread.h"
 #include "EventThread.h"
-#include "IdleTimer.h"
 #include "InjectVSyncSource.h"
 #include "LayerHistory.h"
+#include "OneShotTimer.h"
 #include "RefreshRateConfigs.h"
 #include "SchedulerUtils.h"
 
@@ -273,14 +273,14 @@
     // Timer that records time between requests for next vsync. If the time is higher than a given
     // interval, a callback is fired. Set this variable to >0 to use this feature.
     int64_t mSetIdleTimerMs = 0;
-    std::unique_ptr<scheduler::IdleTimer> mIdleTimer;
+    std::unique_ptr<scheduler::OneShotTimer> mIdleTimer;
     // Enables whether to use idle timer callbacks that support the kernel
     // timer.
     bool mSupportKernelTimer;
 
     // Timer used to monitor touch events.
     int64_t mSetTouchTimerMs = 0;
-    std::unique_ptr<scheduler::IdleTimer> mTouchTimer;
+    std::unique_ptr<scheduler::OneShotTimer> mTouchTimer;
 
     std::mutex mCallbackLock;
     ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 459cd0a..e5896f9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1801,6 +1801,12 @@
     mVsyncModulator.onRefreshed(mHadClientComposition);
 
     mLayersWithQueuedFrames.clear();
+    if (mVisibleRegionsDirty) {
+        mVisibleRegionsDirty = false;
+        if (mTracingEnabled) {
+            mTracing.notify("visibleRegionsDirty");
+        }
+    }
 }
 
 
@@ -1810,9 +1816,6 @@
 
     if (mVisibleRegionsDirty) {
         computeLayerBounds();
-        if (mTracingEnabled) {
-            mTracing.notify("visibleRegionsDirty");
-        }
     }
 
     for (auto& layer : mLayersPendingRefresh) {
@@ -2214,7 +2217,6 @@
     // rebuild the visible layer list per screen
     if (CC_UNLIKELY(mVisibleRegionsDirty)) {
         ATRACE_NAME("rebuildLayerStacks VR Dirty");
-        mVisibleRegionsDirty = false;
         invalidateHwcGeometry();
 
         for (const auto& pair : mDisplays) {
@@ -3931,6 +3933,11 @@
 
     sp<Layer> layer(client->getLayerUser(s.surface));
     if (layer == nullptr) {
+        for (auto& listenerCallback : listenerCallbacks) {
+            mTransactionCompletedThread.addUnpresentedCallbackHandle(
+                    new CallbackHandle(listenerCallback.transactionCompletedListener,
+                                       listenerCallback.callbackIds, s.surface));
+        }
         return 0;
     }
 
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index decabd5..a8ec764 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -36,7 +36,7 @@
 prop {
     api_name: "vsync_event_phase_offset_ns"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
 }
@@ -44,7 +44,7 @@
 prop {
     api_name: "vsync_sf_event_phase_offset_ns"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
 }
@@ -53,7 +53,7 @@
 prop {
     api_name: "use_context_priority"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_context_priority"
 }
@@ -62,7 +62,7 @@
 prop {
     api_name: "max_frame_buffer_acquired_buffers"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
 }
@@ -80,7 +80,7 @@
 prop {
     api_name: "has_wide_color_display"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.has_wide_color_display"
 }
@@ -90,7 +90,7 @@
 prop {
     api_name: "running_without_sync_framework"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.running_without_sync_framework"
 }
@@ -108,7 +108,7 @@
 prop {
     api_name: "has_HDR_display"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.has_HDR_display"
 }
@@ -117,7 +117,7 @@
 prop {
     api_name: "present_time_offset_from_vsync_ns"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
 }
@@ -129,7 +129,7 @@
 prop {
     api_name: "force_hwc_copy_for_virtual_displays"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
 }
@@ -139,7 +139,7 @@
 prop {
     api_name: "max_virtual_display_dimension"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.max_virtual_display_dimension"
 }
@@ -151,7 +151,7 @@
 prop {
     api_name: "use_vr_flinger"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_vr_flinger"
 }
@@ -161,7 +161,7 @@
 prop {
     api_name: "start_graphics_allocator_service"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.start_graphics_allocator_service"
 }
@@ -171,7 +171,7 @@
     api_name: "primary_display_orientation"
     type: Enum
     enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.primary_display_orientation"
 }
@@ -182,7 +182,7 @@
 prop {
     api_name: "use_color_management"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_color_management"
 }
@@ -209,7 +209,7 @@
 prop {
     api_name: "default_composition_dataspace"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.default_composition_dataspace"
 }
@@ -220,7 +220,7 @@
 prop {
     api_name: "default_composition_pixel_format"
     type: Integer
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.default_composition_pixel_format"
 }
@@ -235,7 +235,7 @@
 prop {
     api_name: "wcg_composition_dataspace"
     type: Long
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.wcg_composition_dataspace"
 }
@@ -246,7 +246,7 @@
 prop {
     api_name: "wcg_composition_pixel_format"
     type: Integer
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
 }
@@ -258,7 +258,7 @@
 prop {
     api_name: "display_primary_red"
     type: DoubleList
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_red"
 }
@@ -266,7 +266,7 @@
 prop {
     api_name: "display_primary_green"
     type: DoubleList
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_green"
 }
@@ -274,7 +274,7 @@
 prop {
     api_name: "display_primary_blue"
     type: DoubleList
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_blue"
 }
@@ -282,7 +282,7 @@
 prop {
     api_name: "display_primary_white"
     type: DoubleList
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.display_primary_white"
 }
@@ -293,7 +293,7 @@
 prop {
     api_name: "set_idle_timer_ms"
     type: Integer
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.set_idle_timer_ms"
 }
@@ -304,7 +304,7 @@
 prop {
     api_name: "set_touch_timer_ms"
     type: Integer
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.set_touch_timer_ms"
 }
@@ -314,7 +314,7 @@
 prop {
     api_name: "use_smart_90_for_video"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.use_smart_90_for_video"
 }
@@ -322,7 +322,7 @@
 prop {
     api_name: "enable_protected_contents"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.protected_contents"
 }
@@ -332,7 +332,7 @@
 prop {
     api_name: "support_kernel_idle_timer"
     type: Boolean
-    scope: System
+    scope: Public
     access: Readonly
     prop_name: "ro.surface_flinger.support_kernel_idle_timer"
 }
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index f842d61..4917bc2 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -42,7 +42,7 @@
         "DisplayTransactionTest.cpp",
         "EventControlThreadTest.cpp",
         "EventThreadTest.cpp",
-        "IdleTimerTest.cpp",
+        "OneShotTimerTest.cpp",
         "LayerHistoryTest.cpp",
         "LayerMetadataTest.cpp",
         "SchedulerTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/IdleTimerTest.cpp b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
similarity index 75%
rename from services/surfaceflinger/tests/unittests/IdleTimerTest.cpp
rename to services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
index eff22b6..0208728 100644
--- a/services/surfaceflinger/tests/unittests/IdleTimerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
@@ -21,17 +21,17 @@
 #include <utils/Log.h>
 
 #include "AsyncCallRecorder.h"
-#include "Scheduler/IdleTimer.h"
+#include "Scheduler/OneShotTimer.h"
 
 using namespace std::chrono_literals;
 
 namespace android {
 namespace scheduler {
 
-class IdleTimerTest : public testing::Test {
+class OneShotTimerTest : public testing::Test {
 protected:
-    IdleTimerTest() = default;
-    ~IdleTimerTest() override = default;
+    OneShotTimerTest() = default;
+    ~OneShotTimerTest() override = default;
 
     // This timeout should be used when a 3ms callback is expected.
     // While the tests typically request a callback after 3ms, the scheduler
@@ -46,7 +46,7 @@
     AsyncCallRecorder<void (*)()> mResetTimerCallback;
     AsyncCallRecorder<void (*)()> mExpiredTimerCallback;
 
-    std::unique_ptr<IdleTimer> mIdleTimer;
+    std::unique_ptr<OneShotTimer> mIdleTimer;
 
     void clearPendingCallbacks() {
         while (mExpiredTimerCallback.waitForCall(0us).has_value()) {
@@ -55,13 +55,14 @@
 };
 
 namespace {
-TEST_F(IdleTimerTest, createAndDestroyTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, [] {}, [] {});
+TEST_F(OneShotTimerTest, createAndDestroyTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
+            3ms, [] {}, [] {});
 }
 
-TEST_F(IdleTimerTest, startStopTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(30ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, startStopTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(30ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     auto startTime = std::chrono::steady_clock::now();
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -70,7 +71,7 @@
     bool callbackCalled = mExpiredTimerCallback.waitForCall(25ms).has_value();
     // Under ideal conditions there should be no event. But occasionally
     // it is possible that the wait just prior takes more than 30ms, and
-    // a callback is observed. We check the elapsed time since before the IdleTimer
+    // a callback is observed. We check the elapsed time since before the OneShotTimer
     // thread was started as a sanity check to not have a flakey test.
     EXPECT_FALSE(callbackCalled && std::chrono::steady_clock::now() - startTime < 30ms);
 
@@ -79,9 +80,9 @@
     mIdleTimer->stop();
 }
 
-TEST_F(IdleTimerTest, resetTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(20ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, resetTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
     // Observe any event that happens in about 25ms. We don't care if one was
@@ -104,9 +105,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, resetBackToBackTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(20ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, resetBackToBackTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
 
@@ -135,9 +136,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, startNotCalledTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, startNotCalledTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     // The start hasn't happened, so the callback does not happen.
     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
     EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value());
@@ -147,9 +148,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, idleTimerIdlesTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, idleTimerIdlesTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
 
@@ -167,18 +168,18 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(IdleTimerTest, timeoutCallbackExecutionTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, timeoutCallbackExecutionTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
     EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value());
     mIdleTimer->stop();
 }
 
-TEST_F(IdleTimerTest, noCallbacksAfterStopAndResetTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, noCallbacksAfterStopAndResetTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
     EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value());
@@ -190,9 +191,9 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value());
 }
 
-TEST_F(IdleTimerTest, noCallbacksAfterStopTest) {
-    mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
-                                                        mExpiredTimerCallback.getInvocable());
+TEST_F(OneShotTimerTest, noCallbacksAfterStopTest) {
+    mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+                                                           mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
 
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index a7fd912..b71964b 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -350,7 +350,7 @@
     while (!buffer_state_->compare_exchange_weak(
         current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
         std::memory_order_acquire)) {
-      ALOGI(
+      ALOGV(
           "%s: Failed to post to the new consumer. "
           "Current buffer state was changed to %" PRIx32
           " when trying to acquire the buffer and modify the buffer state to "
diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
index fb7932d..7323277 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -994,6 +994,26 @@
   vsync_callback_->SetEventCallback(send_vsync ? event_callback_ : nullptr);
 }
 
+Return<void> VrHwc::debug(const hidl_handle& fd,
+                          const hidl_vec<hidl_string>& args) {
+  std::string result;
+
+  {
+    std::lock_guard<std::mutex> guard(mutex_);
+    for (const auto& pair : displays_) {
+      result += StringPrintf("Display id: %d\n", static_cast<int>(pair.first));
+      pair.second->dumpDebugInfo(&result);
+    }
+    result += "\n";
+  }
+
+  FILE* out = fdopen(dup(fd->data[0]), "w");
+  fprintf(out, "%s", result.c_str());
+  fclose(out);
+
+  return Void();
+}
+
 void HwcLayer::dumpDebugInfo(std::string* result) const {
   if (!result) {
     return;
diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h
index e8c0212..15358c5 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.h
+++ b/services/vr/hardware_composer/impl/vr_hwc.h
@@ -295,6 +295,9 @@
   void RegisterObserver(Observer* observer) override;
   void UnregisterObserver(Observer* observer) override;
 
+  Return<void> debug(const hidl_handle& fd,
+                     const hidl_vec<hidl_string>& args) override;
+
  private:
   class VsyncCallback : public BnVsyncCallback {
    public:
diff --git a/services/vr/virtual_touchpad/virtual_touchpad.rc b/services/vr/virtual_touchpad/virtual_touchpad.rc
index 99315ef..0de0f9e 100644
--- a/services/vr/virtual_touchpad/virtual_touchpad.rc
+++ b/services/vr/virtual_touchpad/virtual_touchpad.rc
@@ -1,5 +1,5 @@
 service virtual_touchpad /system/bin/virtual_touchpad
   class core
   user system
-  group system input
+  group system input uhid
   writepid /dev/cpuset/system/tasks
diff --git a/vulkan/api/templates/asciidoc.tmpl b/vulkan/api/templates/asciidoc.tmpl
deleted file mode 100644
index 3009e19..0000000
--- a/vulkan/api/templates/asciidoc.tmpl
+++ /dev/null
@@ -1,151 +0,0 @@
-{{Include "vulkan_common.tmpl"}}
-{{if not (Global "AsciiDocPath")}}{{Global "AsciiDocPath" "../../doc/specs/vulkan/"}}{{end}}
-{{$ | Macro "AsciiDoc.Main"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  AsciiDoc generation main entry point.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Main"}}
-  {{$docPath := Global "AsciiDocPath"}}
-
-  {{/* Generate AsciiDoc files for API enums and bitfields (flags). */}}
-  {{range $e := $.Enums}}
-    {{if not $e.IsBitfield}}
-      {{$filename := print $docPath "enums/" (Macro "EnumName" $e) ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Enum" $e) "File" $filename}}
-    {{else}}
-      {{$filename := print $docPath "flags/" (Macro "EnumName" $e) ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Flag" $e) "File" $filename}}
-    {{end}}
-  {{end}}
-
-  {{/* Generate AsciiDoc files for API commands (protos). */}}
-  {{range $f := (AllCommands $)}}
-    {{if not (GetAnnotation $f "pfn")}}
-      {{$filename := print $docPath "protos/" $f.Name ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Proto" $f) "File" $filename}}
-    {{end}}
-  {{end}}
-
-  {{/* Generate AsciiDoc files for API structs. */}}
-  {{range $c := $.Classes}}
-    {{if not (GetAnnotation $c "internal")}}
-      {{$filename := print $docPath "structs/" $c.Name ".txt"}}
-      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Struct" $c) "File" $filename}}
-    {{end}}
-  {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Enum"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef enum {
-    {{range $i, $e := $.Entries}}
-      {{Macro "EnumEntry" $e}} = {{AsSigned $e.Value}}, {{Macro "Docs" $e.Docs}}
-    {{end}}
-  ¶
-    {{$name := Macro "EnumName" $ | TrimRight "ABCDEFGHIJKLMNOQRSTUVWXYZ" | SplitPascalCase | Upper | JoinWith "_"}}
-    {{$first := Macro "EnumFirstEntry" $}}
-    {{$last  := Macro "EnumLastEntry" $}}
-    {{$name}}_BEGIN_RANGE = {{$first}},
-    {{$name}}_END_RANGE = {{$last}},
-    {{$name}}_NUM = ({{$last}} - {{$first}} + 1),
-    {{$name}}_MAX_ENUM = 0x7FFFFFFF
-  } {{Macro "EnumName" $}};
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API bitfield.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Flag"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef VkFlags {{Macro "EnumName" $}};
-  {{if $.Entries}}
-  typedef enum {
-  {{range $e := $.Entries}}
-    {{Macro "BitfieldEntryName" $e}} = {{printf "%#.8x" $e.Value}}, {{Macro "Docs" $e.Docs}}
-  {{end}}
-  } {{Macro "EnumName" $ | TrimRight "s"}}Bits;
-  {{end}}
-{{end}}
-
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API class.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Struct"}}
-  {{AssertType $ "Class"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef {{if GetAnnotation $ "union"}}union{{else}}struct{{end}} {
-    {{range $f := $.Fields}}
-      {{Node "Type" $f}} {{$f.Name}}{{Macro "ArrayPostfix" (TypeOf $f)}}; {{Macro "Docs" $f.Docs}}
-    {{end}}
-  } {{Macro "StructName" $}};
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the AsciiDoc contents for the specified API function.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Proto"}}
-  {{AssertType $ "Function"}}
-
-  {{Macro "Docs" $.Docs}}
-  {{Node "Type" $.Return}} VKAPI {{Macro "FunctionName" $}}({{Macro "Parameters" $}});
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Wraps the specified Code in AsciiDoc source tags then writes to the specified File.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Write"}}
-  {{AssertType $.Code "string"}}
-  {{AssertType $.File "string"}}
-
-  {{$code := $.Code | Format (Global "clang-format")}}
-  {{JoinWith "\n" (Macro "AsciiDoc.Header") $code (Macro "AsciiDoc.Footer") ""| Write $.File}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits an AsciiDoc source header.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Header"}}
-[source,{basebackend@docbook:c++:cpp}]
-------------------------------------------------------------------------------
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits an AsciiDoc source footer.
--------------------------------------------------------------------------------
-*/}}
-{{define "AsciiDoc.Footer"}}
-------------------------------------------------------------------------------
-{{end}}
diff --git a/vulkan/api/templates/vk_xml.tmpl b/vulkan/api/templates/vk_xml.tmpl
deleted file mode 100644
index 893bde7..0000000
--- a/vulkan/api/templates/vk_xml.tmpl
+++ /dev/null
@@ -1,435 +0,0 @@
-{{Include "vulkan_common.tmpl"}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "vk.xml" | Reflow 4 | Write "vk.xml"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Entry point
--------------------------------------------------------------------------------
-*/}}
-{{define "vk.xml"}}
-<?xml version="1.0" encoding="UTF-8"?>
-<registry>
-    »<comment>«
-Copyright (c) 2015 The Khronos Group Inc.

-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and/or associated documentation files (the
-"Materials"), to deal in the Materials without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Materials, and to
-permit persons to whom the Materials are furnished to do so, subject to
-the following conditions:

-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Materials.

-THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.

-------------------------------------------------------------------------

-This file, vk.xml, is the Vulkan API Registry.»
-    </comment>

-    <!-- SECTION: Vulkan type definitions -->
-    <types>»
-        <type name="vk_platform" category="include">#include "vk_platform.h"</type>

-        <type category="define">#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \
-    «((major &lt;&lt; 22) | (minor &lt;&lt; 12) | patch)</type>»

-        <type category="define">// Vulkan API version supported by this file««
-#define <name>VK_API_VERSION</name> <type>VK_MAKE_VERSION</type>({{Global "VERSION_MAJOR"}}, {{Global "VERSION_MINOR"}}, {{Global "VERSION_PATCH"}})</type>

-        »»<type category="define">««
-#if (_MSC_VER &gt;= 1800 || __cplusplus &gt;= 201103L)
-#define <name>VK_NONDISP_HANDLE_OPERATOR_BOOL</name>() explicit operator bool() const { return handle != 0; }
-#else
-#define VK_NONDISP_HANDLE_OPERATOR_BOOL()
-«#endif
-      »»»</type>

-      <type category="define">«««
-#define <name>VK_DEFINE_HANDLE</name>(obj) typedef struct obj##_T* obj;</type>
-      »»»<type category="define">«««
-#if defined(__cplusplus)
-    »»#if (_MSC_VER &gt;= 1800 || __cplusplus &gt;= 201103L)
-        »// The bool operator only works if there are no implicit conversions from an obj to
-        // a bool-compatible type, which can then be used to unintentionally violate type safety.
-        // C++11 and above supports the "explicit" keyword on conversion operators to stop this
-        // from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating
-        // the object handle as a bool in expressions like:
-        //     if (obj) vkDestroy(obj);
-        #define VK_NONDISP_HANDLE_OPERATOR_BOOL() explicit operator bool() const { return handle != 0; }
-        #define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-            explicit obj(uint64_t x) : handle(x) { } \
-            obj(decltype(nullptr)) : handle(0) { }
-    «#else»
-        #define VK_NONDISP_HANDLE_OPERATOR_BOOL()
-        #define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-            obj(uint64_t x) : handle(x) { }
-    «#endif
-    #define <name>VK_DEFINE_NONDISP_HANDLE</name>(obj) \»
-        struct obj { \
-            obj() { } \
-            VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-            obj&amp; operator =(uint64_t x) { handle = x; return *this; } \
-            bool operator==(const obj&amp; other) const { return handle == other.handle; } \
-            bool operator!=(const obj&amp; other) const { return handle != other.handle; } \
-            bool operator!() const { return !handle; } \
-            VK_NONDISP_HANDLE_OPERATOR_BOOL() \
-            uint64_t handle; \
-        };
-««#else
-    »#define VK_DEFINE_NONDISP_HANDLE(obj) typedef struct obj##_T { uint64_t handle; } obj;«
-#endif
-        »»</type>

-        <type category="define">
-#if defined(__cplusplus) &amp;&amp; ((defined(_MSC_VER) &amp;&amp; _MSC_VER &gt;= 1800) || __cplusplus &gt;= 201103L)
-    »#define <name>VK_NULL_HANDLE</name> nullptr
-«#else
-    »#define VK_NULL_HANDLE 0
-«#endif
-        »»</type>

-        <type requires="vk_platform" name="VkDeviceSize"/>
-        <type requires="vk_platform" name="VkSampleMask"/>
-        <type requires="vk_platform" name="VkFlags"/>
-        <!-- Basic C types, pulled in via vk_platform.h -->
-        <type requires="vk_platform" name="char"/>
-        <type requires="vk_platform" name="float"/>
-        <type requires="vk_platform" name="VkBool32"/>
-        <type requires="vk_platform" name="uint8_t"/>
-        <type requires="vk_platform" name="uint32_t"/>
-        <type requires="vk_platform" name="uint64_t"/>
-        <type requires="vk_platform" name="int32_t"/>
-        <type requires="vk_platform" name="size_t"/>
-        <!-- Bitfield types -->
-        {{range $e := $.Enums}}
-          {{if $e.IsBitfield}}
-            {{$bits := print (Macro "EnumName" $e | TrimRight "s") "Bits"}}
-            <type{{if $e.Entries}} requires="{{$bits}}"{{end}} category="bitmask">typedef <type>VkFlags</type> <name>{{$e.Name}}</name>;</type>§
-            {{if $e.Entries}}{{Macro "XML.Docs" $e.Docs}}
-            {{else}}{{Macro "XML.Docs" (Strings $e.Docs "(no bits yet)")}}
-            {{end}}
-          {{end}}
-        {{end}}

-        <!-- Types which can be void pointers or class pointers, selected at compile time -->
-        {{range $i, $p := $.Pseudonyms}}
-          {{     if (GetAnnotation $p "dispatchHandle")}}
-            {{if Global "VK_DEFINE_HANDLE_TYPE_DEFINED"}}
-              <type category="handle">VK_DEFINE_HANDLE(<name>{{$p.Name}}</name>)</type>
-            {{else}}
-              {{Global "VK_DEFINE_HANDLE_TYPE_DEFINED" "YES"}}
-              <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>{{$p.Name}}</name>)</type>
-            {{end}}
-          {{else if (GetAnnotation $p "nonDispatchHandle")}}
-            {{if Global "VK_DEFINE_NONDISP_HANDLE_TYPE_DEFINED"}}
-              <type category="handle">VK_DEFINE_NONDISP_HANDLE(<name>{{$p.Name}}</name>)</type>
-            {{else}}
-              {{Global "VK_DEFINE_NONDISP_HANDLE_TYPE_DEFINED" "YES"}}
-              <type category="handle"><type>VK_DEFINE_NONDISP_HANDLE</type>(<name>{{$p.Name}}</name>)</type>
-            {{end}}
-          {{end}}
-        {{end}}

-        <!-- Types generated from corresponding <enums> tags below -->
-        {{range $e := SortBy $.Enums "EnumName"}}
-          {{if and $e.Entries (not (GetAnnotation $e "internal"))}}
-            {{if $e.IsBitfield}}
-              <type name="{{Macro "EnumName" $e | TrimRight "s"}}Bits" category="enum"/>
-            {{else}}
-              <type name="{{$e.Name}}" category="enum"/>
-            {{end}}
-          {{end}}
-        {{end}}

-        <!-- The PFN_vk*Function types are used by VkAllocCallbacks below -->
-        <type>typedef void* (VKAPI *<name>PFN_vkAllocFunction</name>)(«
-          void*                           pUserData,
-          size_t                          size,
-          size_t                          alignment,
-          <type>VkSystemAllocType</type>               allocType);</type>»
-        <type>typedef void (VKAPI *<name>PFN_vkFreeFunction</name>)(«
-          void*                           pUserData,
-          void*                           pMem);</type>»

-        <!-- The PFN_vkVoidFunction type are used by VkGet*ProcAddr below -->
-        <type>typedef void (VKAPI *<name>PFN_vkVoidFunction</name>)(void);</type>

-        <!-- Struct types -->
-        {{range $c := $.Classes}}
-          {{if not (GetAnnotation $c "internal")}}
-            {{Macro "Struct" $c}}
-          {{end}}
-        {{end}}
-    «</types>

-    <!-- SECTION: Vulkan enumerant (token) definitions. -->

-    <enums namespace="VK" comment="Misc. hardcoded constants - not an enumerated type">»
-            <!-- This is part of the header boilerplate -->
-      {{range $d := $.Definitions}}
-        {{if HasPrefix $d.Name "VK_"}}
-        <enum value="{{$d.Expression}}"        name="{{$d.Name}}"/>{{Macro "XML.Docs" $d.Docs}}
-        {{end}}
-      {{end}}
-        <enum value="1000.0f"  name="VK_LOD_CLAMP_NONE"/>
-        <enum value="(-0U)" name="VK_REMAINING_MIP_LEVELS"/>
-        <enum value="(~0U)" name="VK_REMAINING_ARRAY_LAYERS"/>
-        <enum value="(_0ULL)" name="VK_WHOLE_SIZE"/>
-        <enum value="(~0U)" name="VK_ATTACHMENT_UNUSED"/>
-        <enum value="(~0U)" name="VK_QUEUE_FAMILY_IGNORED"/>
-        <enum value="(~0U)" name="VK_SUBPASS_EXTERNAL"/>
-    «</enums>

-    <!-- Unlike OpenGL, most tokens in Vulkan are actual typed enumerants in»
-         their own numeric namespaces. The "name" attribute is the C enum
-         type name, and is pulled in from a <type> definition above
-         (slightly clunky, but retains the type / enum distinction). "type"
-         attributes of "enum" or "bitmask" indicate that these values should
-         be generated inside an appropriate definition. -->«

-    {{range $e := $.Enums}}
-      {{if not (or $e.IsBitfield (GetAnnotation $e "internal"))}}
-        {{Macro "XML.Enum" $e}}
-      {{end}}
-    {{end}}

-    <!-- Flags -->
-    {{range $e := $.Enums}}
-      {{if $e.IsBitfield}}
-        {{Macro "XML.Bitfield" $e}}
-      {{end}}
-    {{end}}

-    <!-- SECTION: Vulkan command definitions -->
-    <commands namespace="vk">»
-    {{range $f := AllCommands $}}
-      {{if not (GetAnnotation $f "pfn")}}
-        {{Macro "XML.Function" $f}}
-      {{end}}
-    {{end}}
-    «</commands>

-    <!-- SECTION: Vulkan API interface definitions -->
-    <feature api="vulkan" name="VK_VERSION_1_0" number="1.0">»
-        <require comment="Header boilerplate">»
-            <type name="vk_platform"/>
-        «</require>
-        <require comment="API version">»
-            <type name="VK_API_VERSION"/>
-        «</require>
-        <require comment="API constants">»
-            <enum name="VK_LOD_CLAMP_NONE"/>
-            <enum name="VK_REMAINING_MIP_LEVELS"/>
-            <enum name="VK_REMAINING_ARRAY_LAYERS"/>
-            <enum name="VK_WHOLE_SIZE"/>
-            <enum name="VK_ATTACHMENT_UNUSED"/>
-            <enum name="VK_TRUE"/>
-            <enum name="VK_FALSE"/>
-        «</require>
-        <require comment="All functions (TODO: split by type)">»
-        {{range $f := AllCommands $}}
-          {{if not (GetAnnotation $f "pfn")}}
-          <command name="{{$f.Name}}"/>
-          {{end}}
-        {{end}}
-        </require>
-        «<require comment="Types not directly used by the API">»
-            <!-- Include <type name="typename"/> here for e.g. structs that»
-                 are not parameter types of commands, but still need to be
-                 defined in the API.
-             «-->
-            <type name="VkBufferMemoryBarrier"/>
-            <type name="VkDispatchIndirectCmd"/>
-            <type name="VkDrawIndexedIndirectCmd"/>
-            <type name="VkDrawIndirectCmd"/>
-            <type name="VkImageMemoryBarrier"/>
-            <type name="VkMemoryBarrier"/>
-        «</require>
-    «</feature>

-    <!-- SECTION: Vulkan extension interface definitions (none yet) -->
-«</registry>
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified bitfield.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Bitfield"}}
-  {{AssertType $ "Enum"}}
-
-  {{if $.Entries}}
-  <enums namespace="VK" name="{{Macro "EnumName" $ | TrimRight "s"}}Bits" type="bitmask">»
-  {{range $e := $.Entries}}
-    {{$pos := Bitpos $e.Value}}
-    <enum §
-      {{if gt $pos -1}} bitpos="{{$pos}}"    §
-      {{else}}value="{{if $e.Value}}{{printf "0x%.8X" $e.Value}}{{else}}0{{end}}"    §
-      {{end}}name="{{Macro "BitfieldEntryName" $e}}" §
-      {{if $d := $e.Docs}} comment="{{$d | JoinWith "  "}}"{{end}}/>
-  {{end}}
-  «</enums>
-  {{end}}
-
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Enum"}}
-  {{AssertType $ "Enum"}}
-
-  <enums namespace="VK" name="{{Macro "EnumName" $}}" type="enum" §
-         expand="{{Macro "EnumName" $ | SplitPascalCase | Upper | JoinWith "_"}}"{{if $.Docs}} comment="{{$.Docs | JoinWith "  "}}"{{end}}>»
-  {{range $i, $e := $.Entries}}
-    <enum value="{{AsSigned $e.Value}}"     name="{{Macro "BitfieldEntryName" $e}}"{{if $e.Docs}} comment="{{$e.Docs | JoinWith "  "}}"{{end}}/>
-  {{end}}
-  {{if $lu := GetAnnotation $ "lastUnused"}}
-    <unused start="{{index $lu.Arguments 0}}"/>
-  {{end}}
-  «</enums>
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "Struct"}}
-  {{AssertType $ "Class"}}
-
-  <type category="{{Macro "StructType" $}}" name="{{Macro "StructName" $}}"{{if $.Docs}} comment="{{$.Docs | JoinWith "  "}}"{{end}}>»
-    {{range $f := $.Fields}}
-    <member>{{Node "XML.Type" $f}}        <name>{{$f.Name}}</name>{{Macro "XML.ArrayPostfix" $f}}</member>{{Macro "XML.Docs" $f.Docs}}
-    {{end}}
-  «</type>
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits either 'struct' or 'union' for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "StructType"}}
-  {{AssertType $ "Class"}}
-
-  {{if GetAnnotation $ "union"}}union{{else}}struct{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function pointer typedef declaration for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Function"}}
-  {{AssertType $ "Function"}}
-
-    {{$ts := GetAnnotation $ "threadSafety"}}
-    <command{{if $ts}} threadsafe="{{index $ts.Arguments 0}}"{{end}}>»
-        <proto>{{Node "XML.Type" $.Return}} <name>{{$.Name}}</name></proto>
-        {{range $p := $.CallParameters}}
-          <param>{{Node "XML.Type" $p}} <name>{{$p.Name}}{{Macro "ArrayPostfix" $p}}</name></param>
-        {{end}}
-    «</command>
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the XML translation for the specified documentation block (string array).
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Docs"}}
-  {{if $}} <!-- {{JoinWith "  " $ | Replace "<" "" | Replace ">" ""}} -->{{end}}
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C translation for the specified type.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Type.Class"      }}<type>{{Macro "StructName" $.Type}}</type>{{end}}
-{{define "XML.Type.Pseudonym"  }}<type>{{$.Type.Name}}</type>{{end}}
-{{define "XML.Type.Enum"       }}<type>{{$.Type.Name}}</type>{{end}}
-{{define "XML.Type.StaticArray"}}{{Node "XML.Type" $.Type.ValueType}}{{end}}
-{{define "XML.Type.Pointer"    }}{{if $.Type.Const}}{{Node "XML.ConstType" $.Type.To}}{{else}}{{Node "XML.Type" $.Type.To}}{{end}}*{{end}}
-{{define "XML.Type.Slice"      }}<type>{{Node "XML.Type" $.Type.To}}</type>*{{end}}
-{{define "XML.Type#s8"         }}<type>int8_t</type>{{end}}
-{{define "XML.Type#u8"         }}<type>uint8_t</type>{{end}}
-{{define "XML.Type#s16"        }}<type>int16_t</type>{{end}}
-{{define "XML.Type#u16"        }}<type>uint16_t</type>{{end}}
-{{define "XML.Type#s32"        }}<type>int32_t</type>{{end}}
-{{define "XML.Type#u32"        }}<type>uint32_t</type>{{end}}
-{{define "XML.Type#f32"        }}<type>float</type>{{end}}
-{{define "XML.Type#s64"        }}<type>int64_t</type>{{end}}
-{{define "XML.Type#u64"        }}<type>uint64_t</type>{{end}}
-{{define "XML.Type#f64"        }}<type>double</type>{{end}}
-{{define "XML.Type#char"       }}<type>char</type>{{end}}
-{{define "XML.Type#void"       }}void{{end}}
-
-{{define "XML.ConstType_Default"}}const {{Node "XML.Type" $.Type}}{{end}}
-{{define "XML.ConstType.Pointer"}}{{Node "XML.Type" $.Type}} const{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a C type and name for the given parameter
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Parameter"}}
-  {{AssertType $ "Parameter"}}
-
-  <type>{{Macro "ParameterType" $}}</type> <name>{{$.Name}}{{Macro "ArrayPostfix" $}}</name>
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits a comma-separated list of C type-name paired parameters for the given
-  command.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.Parameters"}}
-  {{AssertType $ "Function"}}
-
-  {{ForEach $.CallParameters "XML.Parameter" | JoinWith ", "}}
-  {{if not $.CallParameters}}<type>void</type>{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the fixed-size-array postfix for pseudonym types annotated with @array
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.ArrayPostfix"}}{{Node "XML.ArrayPostfix" $}}{{end}}
-{{define "XML.ArrayPostfix.StaticArray"}}[{{Node "XML.NamedValue" $.Type.SizeExpr}}]{{end}}
-{{define "XML.ArrayPostfix_Default"}}{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the value of the given constant, or the <enum> tagged name if existant.
--------------------------------------------------------------------------------
-*/}}
-{{define "XML.NamedValue.Definition"}}<enum>{{$.Node.Name}}</enum>{{end}}
-{{define "XML.NamedValue.EnumEntry"}}<enum>{{$.Node.Name}}</enum>{{end}}
-{{define "XML.NamedValue_Default"}}{{$.Node}}{{end}}
diff --git a/vulkan/api/templates/vulkan_h.tmpl b/vulkan/api/templates/vulkan_h.tmpl
deleted file mode 100644
index 83a5e40..0000000
--- a/vulkan/api/templates/vulkan_h.tmpl
+++ /dev/null
@@ -1,295 +0,0 @@
-{{Include "vulkan_common.tmpl"}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "vulkan.h" | Format (Global "clang-format") | Write "../include/vulkan.h"}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Entry point
--------------------------------------------------------------------------------
-*/}}
-{{define "vulkan.h"}}
-#ifndef __vulkan_h_
-#define __vulkan_h_ 1

-#ifdef __cplusplus
-extern "C" {
-#endif

-/*
-** Copyright (c) 2015-2016 The Khronos Group Inc.
-**
-** Permission is hereby granted, free of charge, to any person obtaining a
-** copy of this software and/or associated documentation files (the
-** "Materials"), to deal in the Materials without restriction, including
-** without limitation the rights to use, copy, modify, merge, publish,
-** distribute, sublicense, and/or sell copies of the Materials, and to
-** permit persons to whom the Materials are furnished to do so, subject to
-** the following conditions:
-**
-** The above copyright notice and this permission notice shall be included
-** in all copies or substantial portions of the Materials.
-**
-** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-*/

-/*
-** This header is generated from the Khronos Vulkan API Registry.
-**
-*/

-#define VK_VERSION_1_0 1
-#include "vk_platform.h"

-#define VK_MAKE_VERSION(major, minor, patch) (((major) << 22) | ((minor) << 12) | (patch))

-// Vulkan API version supported by this file
-#define VK_API_VERSION \
-    VK_MAKE_VERSION({{Global "VERSION_MAJOR"}}, {{Global "VERSION_MINOR"}}, {{Global "VERSION_PATCH"}})

-#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
-#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
-#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)

-#if defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1800 || __cplusplus >= 201103L)
-    #define VK_NULL_HANDLE nullptr
-#else
-    #define VK_NULL_HANDLE 0
-#endif

-#define VK_DEFINE_HANDLE(obj) typedef struct obj##_T* obj;

-#if defined(__cplusplus)
-#if ((defined(_MSC_VER) && _MSC_VER >= 1800 || __cplusplus >= 201103L)
-// The bool operator only works if there are no implicit conversions from an obj to
-// a bool-compatible type, which can then be used to unintentionally violate type safety.
-// C++11 and above supports the "explicit" keyword on conversion operators to stop this
-// from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating
-// the object handle as a bool in expressions like:
-//     if (obj) vkDestroy(obj);
-#define VK_NONDISP_HANDLE_OPERATOR_BOOL() \
-    explicit operator bool() const { return handle != 0; }
-#define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-    explicit obj(uint64_t x) : handle(x) { } \
-    obj(decltype(nullptr)) : handle(0) { }
-#else
-#define VK_NONDISP_HANDLE_OPERATOR_BOOL()
-#define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
-    obj(uint64_t x) : handle(x) { }
-#endif
-#define VK_DEFINE_NONDISP_HANDLE(obj)                                              \
-    struct obj {                                                                   \
-        obj() : handle(0) { }                                                      \
-        VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj)                             \
-        obj& operator=(uint64_t x) {                                               \
-            handle = x;                                                            \
-            return *this;                                                          \
-        }                                                                          \
-        bool operator==(const obj& other) const { return handle == other.handle; } \
-        bool operator!=(const obj& other) const { return handle != other.handle; } \
-        bool operator!() const { return !handle; }                                 \
-        VK_NONDISP_HANDLE_OPERATOR_BOOL()                                          \
-        uint64_t handle;                                                           \
-    };
-#else
-#define VK_DEFINE_NONDISP_HANDLE(obj) \
-    typedef struct obj##_T { uint64_t handle; } obj;
-#endif

-#define VK_LOD_CLAMP_NONE         1000.0f
-#define VK_REMAINING_MIP_LEVELS   (~0U)
-#define VK_REMAINING_ARRAY_LAYERS (~0U)
-#define VK_WHOLE_SIZE             (~0ULL)
-#define VK_ATTACHMENT_UNUSED      (~0U)
-define VK_QUEUE_FAMILY_IGNORED    (~0U)
-define VK_SUBPASS_EXTERNAL        (~0U)
-{{range $d := $.Definitions}}
-  {{if HasPrefix $d.Name "VK_"}}#define {{$d.Name}}  {{$d.Expression}}{{end}}
-{{end}}

-{{range $i, $p := $.Pseudonyms}}
-  {{if GetAnnotation $p "dispatchHandle"}}VK_DEFINE_HANDLE({{$p.Name}})
-  {{else if GetAnnotation $p "nonDispatchHandle"}}VK_DEFINE_NONDISP_HANDLE({{$p.Name}})
-  {{end}}
-{{end}}

-// ------------------------------------------------------------------------------------------------
-// Enumerations

-  {{range $e := $.Enums}}
-    {{if not $e.IsBitfield}}
-      {{Macro "Enum" $e}}
-    {{end}}
-  {{end}}

-// ------------------------------------------------------------------------------------------------
-// Flags

-  {{range $e := $.Enums}}
-    {{if $e.IsBitfield}}
-      {{Macro "Bitfield" $e}}
-    {{end}}
-  {{end}}

-// ------------------------------------------------------------------------------------------------
-// Vulkan structures

-  {{/* Function pointers */}}
-  {{range $f := AllCommands $}}
-    {{if GetAnnotation $f "pfn"}}
-      {{Macro "FunctionTypedef" $f}}
-    {{end}}
-  {{end}}

-  {{range $c := $.Classes}}
-    {{if not (GetAnnotation $c "internal")}}
-      {{Macro "Struct" $c}}
-    {{end}}
-  {{end}}

-// ------------------------------------------------------------------------------------------------
-// API functions

-  {{range $f := AllCommands $}}
-    {{if not (GetAnnotation $f "pfn")}}
-      {{Macro "FunctionTypedef" $f}}
-    {{end}}
-  {{end}}

-#ifdef VK_NO_PROTOTYPES

-  {{range $f := AllCommands $}}
-    {{if not (GetAnnotation $f "pfn")}}
-      {{Macro "FunctionDecl" $f}}
-    {{end}}
-  {{end}}

-#endif

-#ifdef __cplusplus
-}
-#endif

-#endif
-{{end}}
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified bitfield.
--------------------------------------------------------------------------------
-*/}}
-{{define "Bitfield"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef VkFlags {{Macro "EnumName" $}};
-  {{if $.Entries}}
-  typedef enum {
-  {{range $b := $.Entries}}
-    {{Macro "BitfieldEntryName" $b}} = {{printf "0x%.8X" $b.Value}}, {{Macro "Docs" $b.Docs}}
-  {{end}}
-  } {{Macro "EnumName" $ | TrimRight "s"}}Bits;
-  {{end}}
-  ¶
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified enum.
--------------------------------------------------------------------------------
-*/}}
-{{define "Enum"}}
-  {{AssertType $ "Enum"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef enum {
-    {{range $i, $e := $.Entries}}
-      {{Macro "EnumEntry" $e}} = {{printf "0x%.8X" $e.Value}}, {{Macro "Docs" $e.Docs}}
-    {{end}}
-  ¶
-    {{$name  := Macro "EnumName" $ | TrimRight "ABCDEFGHIJKLMNOQRSTUVWXYZ" | SplitPascalCase | Upper | JoinWith "_"}}
-    {{if GetAnnotation $ "enumMaxOnly"}}
-      VK_MAX_ENUM({{$name | SplitOn "VK_"}})
-    {{else}}
-      {{$first := Macro "EnumFirstEntry" $ | SplitOn $name | TrimLeft "_"}}
-      {{$last  := Macro "EnumLastEntry" $  | SplitOn $name | TrimLeft "_"}}
-      VK_ENUM_RANGE({{$name | SplitOn "VK_"}}, {{$first}}, {{$last}})
-    {{end}}
-  } {{Macro "EnumName" $}};
-  ¶
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "Struct"}}
-  {{AssertType $ "Class"}}
-
-  {{Macro "Docs" $.Docs}}
-  typedef {{Macro "StructType" $}} {
-    {{ForEach $.Fields "Field" | JoinWith "\n"}}
-  } {{Macro "StructName" $}};
-  ¶
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C declaration for the specified class field.
--------------------------------------------------------------------------------
-*/}}
-{{define "Field"}}
-  {{AssertType $ "Field"}}
-
-  {{Node "Type" $}} {{$.Name}}§
-  {{Macro "ArrayPostfix" (TypeOf $)}}; {{Macro "Docs" $.Docs}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits either 'struct' or 'union' for the specified class.
--------------------------------------------------------------------------------
-*/}}
-{{define "StructType"}}
-  {{AssertType $ "Class"}}
-
-  {{if GetAnnotation $ "union"}}union{{else}}struct{{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function pointer typedef declaration for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "FunctionTypedef"}}
-  {{AssertType $ "Function"}}
-
-  typedef {{Node "Type" $.Return}} (VKAPI* {{Macro "FunctionPtrName" $}})({{Macro "Parameters" $}});
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
-  Emits the C function declaration for the specified command.
--------------------------------------------------------------------------------
-*/}}
-{{define "FunctionDecl"}}
-  {{AssertType $ "Function"}}
-
-  {{if not (GetAnnotation $ "fptr")}}
-    {{Macro "Docs" $.Docs}}
-    {{Node "Type" $.Return}} VKAPI {{Macro "FunctionName" $}}({{Macro "Parameters" $}});
-  {{end}}
-{{end}}
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index df86af0..ad46c3b 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -16,12 +16,11 @@
 
 // WARNING: This file is generated. See ../README.md for instructions.
 
+#include <log/log.h>
 #include <string.h>
 
 #include <algorithm>
 
-#include <log/log.h>
-
 // to catch mismatches between vulkan.h and this file
 #undef VK_NO_PROTOTYPES
 #include "api.h"
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
index 4bedbeb..f582224 100644
--- a/vulkan/libvulkan/api_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -20,7 +20,9 @@
 #define LIBVULKAN_API_GEN_H
 
 #include <vulkan/vulkan.h>
+
 #include <bitset>
+
 #include "driver_gen.h"
 
 namespace vulkan {
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index bdd3573..940b747 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -37,8 +37,10 @@
 #ifndef LIBVULKAN_API_GEN_H
 #define LIBVULKAN_API_GEN_H

-#include <bitset>
 #include <vulkan/vulkan.h>

+#include <bitset>

 #include "driver_gen.h"

 namespace vulkan {«
@@ -90,12 +92,11 @@

 // WARNING: This file is generated. See ../README.md for instructions.

+#include <log/log.h>
 #include <string.h>

 #include <algorithm>

-#include <log/log.h>

 // to catch mismatches between vulkan.h and this file
 #undef VK_NO_PROTOTYPES
 #include "api.h"
@@ -217,9 +218,10 @@
 #ifndef LIBVULKAN_DRIVER_GEN_H
 #define LIBVULKAN_DRIVER_GEN_H

-#include <bitset>
-#include <vulkan/vulkan.h>
 #include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>

+#include <bitset>

 namespace vulkan {«
 namespace driver {«
@@ -271,12 +273,11 @@

 // WARNING: This file is generated. See ../README.md for instructions.

+#include <log/log.h>
 #include <string.h>

 #include <algorithm>

-#include <log/log.h>

 #include "driver.h"

 namespace vulkan {«
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 23506ba..d33e552 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -16,30 +16,29 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include "driver.h"
+
+#include <dlfcn.h>
 #include <malloc.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/prctl.h>
-
-#include <dlfcn.h>
-#include <algorithm>
-#include <array>
-#include <new>
-
-#include <log/log.h>
 
 #include <android/dlext.h>
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android-base/properties.h>
 #include <configstore/Utils.h>
 #include <cutils/properties.h>
 #include <graphicsenv/GraphicsEnv.h>
+#include <log/log.h>
+#include <sys/prctl.h>
 #include <utils/Timers.h>
 #include <utils/Trace.h>
-#include <utils/Vector.h>
 
-#include "android-base/properties.h"
+#include <algorithm>
+#include <array>
+#include <new>
+#include <vector>
 
-#include "driver.h"
 #include "stubhal.h"
 
 using namespace android::hardware::configstore;
@@ -809,8 +808,7 @@
     const char* pLayerName,
     uint32_t* pPropertyCount,
     VkExtensionProperties* pProperties) {
-
-    android::Vector<VkExtensionProperties> loader_extensions;
+    std::vector<VkExtensionProperties> loader_extensions;
     loader_extensions.push_back({
         VK_KHR_SURFACE_EXTENSION_NAME,
         VK_KHR_SURFACE_SPEC_VERSION});
@@ -833,7 +831,7 @@
         uint32_t count = std::min(
             *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
 
-        std::copy_n(loader_extensions.begin(), count, pProperties);
+        std::copy_n(loader_extensions.data(), count, pProperties);
 
         if (count < loader_extensions.size()) {
             *pPropertyCount = count;
@@ -879,8 +877,7 @@
 
 bool QueryPresentationProperties(
     VkPhysicalDevice physicalDevice,
-    VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties)
-{
+    VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties) {
     const InstanceData& data = GetData(physicalDevice);
 
     // GPDP2 must be present and enabled on the instance.
@@ -920,7 +917,7 @@
     VkExtensionProperties* pProperties) {
     const InstanceData& data = GetData(physicalDevice);
     // extensions that are unconditionally exposed by the loader
-    android::Vector<VkExtensionProperties> loader_extensions;
+    std::vector<VkExtensionProperties> loader_extensions;
     loader_extensions.push_back({
         VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
         VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
@@ -956,7 +953,7 @@
         uint32_t count = std::min(
             *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
 
-        std::copy_n(loader_extensions.begin(), count, pProperties);
+        std::copy_n(loader_extensions.data(), count, pProperties);
 
         if (count < loader_extensions.size()) {
             *pPropertyCount = count;
@@ -1245,11 +1242,10 @@
         if (!device_count)
             return VK_INCOMPLETE;
 
-        android::Vector<VkPhysicalDevice> devices;
-        devices.resize(device_count);
+        std::vector<VkPhysicalDevice> devices(device_count);
         *pPhysicalDeviceGroupCount = device_count;
-        result = EnumeratePhysicalDevices(instance, &device_count,
-                                          devices.editArray());
+        result =
+            EnumeratePhysicalDevices(instance, &device_count, devices.data());
         if (result < 0)
             return result;
 
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 574c327..7020be1 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -16,12 +16,11 @@
 
 // WARNING: This file is generated. See ../README.md for instructions.
 
+#include <log/log.h>
 #include <string.h>
 
 #include <algorithm>
 
-#include <log/log.h>
-
 #include "driver.h"
 
 namespace vulkan {
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 3faf6c0..c299549 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -21,6 +21,7 @@
 
 #include <vulkan/vk_android_native_buffer.h>
 #include <vulkan/vulkan.h>
+
 #include <bitset>
 
 namespace vulkan {
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index a8949d3..761d128 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -24,7 +24,6 @@
 #include <ui/BufferQueueDefs.h>
 #include <utils/StrongPointer.h>
 #include <utils/Trace.h>
-#include <utils/Vector.h>
 
 #include <algorithm>
 #include <unordered_set>
@@ -34,10 +33,6 @@
 
 using android::hardware::graphics::common::V1_0::BufferUsage;
 
-// TODO(jessehall): Currently we don't have a good error code for when a native
-// window operation fails. Just returning INITIALIZATION_FAILED for now. Later
-// versions (post SDK 0.9) of the API/extension have a better error code.
-// When updating to that version, audit all error returns.
 namespace vulkan {
 namespace driver {
 
@@ -48,29 +43,12 @@
     VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
     VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR |
     VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR |
-    // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
-    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
+    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
@@ -78,27 +56,22 @@
     // transforms are built up from a horizontal flip, vertical flip, and
     // 90-degree rotation, all optional but always in that order.
 
-    // TODO(jessehall): For now, only support pure rotations, not
-    // flip or flip-and-rotate, until I have more time to test them and build
-    // sample code. As far as I know we never actually use anything besides
-    // pure rotations anyway.
-
     switch (native) {
-        case 0:  // 0x0
+        case 0:
             return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_H:  // 0x1
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_V:  // 0x2
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
-        case NATIVE_WINDOW_TRANSFORM_ROT_180:  // FLIP_H | FLIP_V
+        case NATIVE_WINDOW_TRANSFORM_FLIP_H:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_FLIP_V:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_ROT_180:
             return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
-        case NATIVE_WINDOW_TRANSFORM_ROT_90:  // 0x4
+        case NATIVE_WINDOW_TRANSFORM_ROT_90:
             return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
-        // case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
-        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
-        case NATIVE_WINDOW_TRANSFORM_ROT_270:  // FLIP_H | FLIP_V | ROT_90
+        case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
+            return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_ROT_270:
             return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
         case NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY:
         default:
@@ -106,6 +79,31 @@
     }
 }
 
+int TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform) {
+    switch (transform) {
+        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_HORIZONTAL_MIRROR_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+        case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
+        default:
+            return 0;
+    }
+}
+
 int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) {
     switch (transform) {
         case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
@@ -114,17 +112,16 @@
             return NATIVE_WINDOW_TRANSFORM_ROT_180;
         case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
             return NATIVE_WINDOW_TRANSFORM_ROT_90;
-        // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H;
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H |
-        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V;
-        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
-        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V |
-        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_H |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V;
+        case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                   NATIVE_WINDOW_TRANSFORM_ROT_90;
         case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
         case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
         default:
@@ -134,7 +131,6 @@
 
 class TimingInfo {
    public:
-    TimingInfo() = default;
     TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId)
         : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
           native_frame_id_(nativeFrameId) {}
@@ -201,8 +197,6 @@
             { NATIVE_WINDOW_TIMESTAMP_PENDING };
 };
 
-// ----------------------------------------------------------------------------
-
 struct Surface {
     android::sp<ANativeWindow> window;
     VkSwapchainKHR swapchain_handle;
@@ -270,7 +264,7 @@
         bool dequeued;
     } images[android::BufferQueueDefs::NUM_BUFFER_SLOTS];
 
-    android::Vector<TimingInfo> timing;
+    std::vector<TimingInfo> timing;
 };
 
 VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
@@ -285,6 +279,8 @@
                            ANativeWindow* window,
                            int release_fence,
                            Swapchain::Image& image) {
+    ATRACE_CALL();
+
     ALOG_ASSERT(release_fence == -1 || image.dequeued,
                 "ReleaseSwapchainImage: can't provide a release fence for "
                 "non-dequeued images");
@@ -323,7 +319,9 @@
     }
 
     if (image.image) {
+        ATRACE_BEGIN("DestroyImage");
         GetData(device).driver.DestroyImage(device, image.image, nullptr);
+        ATRACE_END();
         image.image = VK_NULL_HANDLE;
     }
 
@@ -349,7 +347,7 @@
     uint32_t num_ready = 0;
     const size_t num_timings = swapchain.timing.size() - MIN_NUM_FRAMES_AGO + 1;
     for (uint32_t i = 0; i < num_timings; i++) {
-        TimingInfo& ti = swapchain.timing.editItemAt(i);
+        TimingInfo& ti = swapchain.timing[i];
         if (ti.ready()) {
             // This TimingInfo is ready to be reported to the user.  Add it
             // to the num_ready.
@@ -419,7 +417,7 @@
     }
 
     uint32_t num_copied = 0;
-    size_t num_to_remove = 0;
+    int32_t num_to_remove = 0;
     for (uint32_t i = 0; i <= last_ready && num_copied < *count; i++) {
         const TimingInfo& ti = swapchain.timing[i];
         if (ti.ready()) {
@@ -431,7 +429,8 @@
 
     // Discard old frames that aren't ready if newer frames are ready.
     // We don't expect to get the timing info for those old frames.
-    swapchain.timing.removeItemsAt(0, num_to_remove);
+    swapchain.timing.erase(swapchain.timing.begin(),
+                           swapchain.timing.begin() + num_to_remove);
 
     *count = num_copied;
 }
@@ -539,15 +538,12 @@
               strerror(-err), err);
         surface->~Surface();
         allocator->pfnFree(allocator->pUserData, surface);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
-    // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
     err =
         native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err),
               err);
         surface->~Surface();
@@ -656,7 +652,6 @@
         return VK_ERROR_SURFACE_LOST_KHR;
     }
 
-    // TODO(jessehall): Figure out what the min/max values should be.
     int max_buffer_count;
     err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &max_buffer_count);
     if (err != 0) {
@@ -670,8 +665,7 @@
     capabilities->currentExtent =
         VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
 
-    // TODO(jessehall): Figure out what the max extent should be. Maximum
-    // texture dimension maybe?
+    // TODO(http://b/134182502): Figure out what the max extent should be.
     capabilities->minImageExtent = VkExtent2D{1, 1};
     capabilities->maxImageExtent = VkExtent2D{4096, 4096};
 
@@ -685,11 +679,6 @@
     // associated with the bufferqueue. It can't be changed from here.
     capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
 
-    // TODO(jessehall): I think these are right, but haven't thought hard about
-    // it. Do we need to query the driver for support of any of these?
-    // Currently not included:
-    // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not
-    // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not
     capabilities->supportedUsageFlags =
         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
@@ -729,8 +718,7 @@
     int err = native_window_get_wide_color_support(surface.window.get(),
                                                    &wide_color_support);
     if (err) {
-        // Not allowed to return a more sensible error code, so do this
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
     ALOGV("wide_color_support is: %d", wide_color_support);
     wide_color_support =
@@ -828,11 +816,10 @@
     } else {
         // temp vector for forwarding; we'll marshal it into the pSurfaceFormats
         // after the call.
-        android::Vector<VkSurfaceFormatKHR> surface_formats;
-        surface_formats.resize(*pSurfaceFormatCount);
+        std::vector<VkSurfaceFormatKHR> surface_formats(*pSurfaceFormatCount);
         VkResult result = GetPhysicalDeviceSurfaceFormatsKHR(
             physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount,
-            &surface_formats.editItemAt(0));
+            surface_formats.data());
 
         if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
             // marshal results individually due to stride difference.
@@ -874,7 +861,7 @@
     }
     uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
 
-    android::Vector<VkPresentModeKHR> present_modes;
+    std::vector<VkPresentModeKHR> present_modes;
     if (min_undequeued_buffers + 1 < max_buffer_count)
         present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
     present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
@@ -894,7 +881,7 @@
         if (*count < num_modes)
             result = VK_INCOMPLETE;
         *count = std::min(*count, num_modes);
-        std::copy(present_modes.begin(), present_modes.begin() + int(*count), modes);
+        std::copy_n(present_modes.data(), *count, modes);
     } else {
         *count = num_modes;
     }
@@ -978,6 +965,40 @@
     return VK_SUCCESS;
 }
 
+static void DestroySwapchainInternal(VkDevice device,
+                                     VkSwapchainKHR swapchain_handle,
+                                     const VkAllocationCallbacks* allocator) {
+    ATRACE_CALL();
+
+    const auto& dispatch = GetData(device).driver;
+    Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
+    if (!swapchain) {
+        return;
+    }
+
+    bool active = swapchain->surface.swapchain_handle == swapchain_handle;
+    ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
+
+    if (window && swapchain->frame_timestamps_enabled) {
+        native_window_enable_frame_timestamps(window, false);
+    }
+
+    for (uint32_t i = 0; i < swapchain->num_images; i++) {
+        ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
+    }
+
+    if (active) {
+        swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
+    }
+
+    if (!allocator) {
+        allocator = &GetData(device).allocator;
+    }
+
+    swapchain->~Swapchain();
+    allocator->pfnFree(allocator->pUserData, swapchain);
+}
+
 VKAPI_ATTR
 VkResult CreateSwapchainKHR(VkDevice device,
                             const VkSwapchainCreateInfoKHR* create_info,
@@ -1052,6 +1073,8 @@
     // non-FREE state at any given time. Disconnecting and re-connecting
     // orphans the previous buffers, getting us back to the state where we can
     // dequeue all buffers.
+    //
+    // TODO(http://b/134186185) recycle swapchain images more efficiently
     err = native_window_api_disconnect(surface.window.get(),
                                        NATIVE_WINDOW_API_EGL);
     ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)",
@@ -1072,8 +1095,6 @@
         create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
     err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1100,8 +1121,6 @@
     err = native_window_set_buffers_format(surface.window.get(),
                                            native_pixel_format);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)",
               native_pixel_format, strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1109,8 +1128,6 @@
     err = native_window_set_buffers_data_space(surface.window.get(),
                                                native_dataspace);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)",
               native_dataspace, strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1120,8 +1137,6 @@
         surface.window.get(), static_cast<int>(create_info->imageExtent.width),
         static_cast<int>(create_info->imageExtent.height));
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
               create_info->imageExtent.width, create_info->imageExtent.height,
               strerror(-err), err);
@@ -1140,8 +1155,6 @@
         surface.window.get(),
         InvertTransformToNative(create_info->preTransform));
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
               InvertTransformToNative(create_info->preTransform),
               strerror(-err), err);
@@ -1151,8 +1164,6 @@
     err = native_window_set_scaling_mode(
         surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1182,8 +1193,6 @@
                                 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
                                 &query_value);
     if (err != 0 || query_value < 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
               query_value);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1201,8 +1210,6 @@
     // can't actually use!).
     err = native_window_set_buffer_count(surface.window.get(), std::max(2u, num_images));
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
@@ -1211,7 +1218,7 @@
     int32_t legacy_usage = 0;
     if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
         uint64_t consumer_usage, producer_usage;
-        ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsage2ANDROID");
+        ATRACE_BEGIN("GetSwapchainGrallocUsage2ANDROID");
         result = dispatch.GetSwapchainGrallocUsage2ANDROID(
             device, create_info->imageFormat, create_info->imageUsage,
             swapchain_image_usage, &consumer_usage, &producer_usage);
@@ -1223,7 +1230,7 @@
         legacy_usage =
             android_convertGralloc1To0Usage(producer_usage, consumer_usage);
     } else if (dispatch.GetSwapchainGrallocUsageANDROID) {
-        ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsageANDROID");
+        ATRACE_BEGIN("GetSwapchainGrallocUsageANDROID");
         result = dispatch.GetSwapchainGrallocUsageANDROID(
             device, create_info->imageFormat, create_info->imageUsage,
             &legacy_usage);
@@ -1242,8 +1249,6 @@
     }
     err = native_window_set_usage(surface.window.get(), native_usage);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
@@ -1301,8 +1306,6 @@
         err = surface.window->dequeueBuffer(surface.window.get(), &buffer,
                                             &img.dequeue_fence);
         if (err != 0) {
-            // TODO(jessehall): Improve error reporting. Can we enumerate
-            // possible errors and translate them to valid Vulkan result codes?
             ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
             result = VK_ERROR_SURFACE_LOST_KHR;
             break;
@@ -1322,7 +1325,7 @@
             &image_native_buffer.usage2.producer,
             &image_native_buffer.usage2.consumer);
 
-        ATRACE_BEGIN("dispatch.CreateImage");
+        ATRACE_BEGIN("CreateImage");
         result =
             dispatch.CreateImage(device, &image_create, nullptr, &img.image);
         ATRACE_END();
@@ -1335,9 +1338,6 @@
     // -- Cancel all buffers, returning them to the queue --
     // If an error occurred before, also destroy the VkImage and release the
     // buffer reference. Otherwise, we retain a strong reference to the buffer.
-    //
-    // TODO(jessehall): The error path here is the same as DestroySwapchain,
-    // but not the non-error path. Should refactor/unify.
     for (uint32_t i = 0; i < num_images; i++) {
         Swapchain::Image& img = swapchain->images[i];
         if (img.dequeued) {
@@ -1348,18 +1348,11 @@
                 img.dequeued = false;
             }
         }
-        if (result != VK_SUCCESS) {
-            if (img.image) {
-                ATRACE_BEGIN("dispatch.DestroyImage");
-                dispatch.DestroyImage(device, img.image, nullptr);
-                ATRACE_END();
-            }
-        }
     }
 
     if (result != VK_SUCCESS) {
-        swapchain->~Swapchain();
-        allocator->pfnFree(allocator->pUserData, swapchain);
+        DestroySwapchainInternal(device, HandleFromSwapchain(swapchain),
+                                 allocator);
         return result;
     }
 
@@ -1374,24 +1367,7 @@
                          const VkAllocationCallbacks* allocator) {
     ATRACE_CALL();
 
-    const auto& dispatch = GetData(device).driver;
-    Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
-    if (!swapchain)
-        return;
-    bool active = swapchain->surface.swapchain_handle == swapchain_handle;
-    ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
-
-    if (swapchain->frame_timestamps_enabled) {
-        native_window_enable_frame_timestamps(window, false);
-    }
-    for (uint32_t i = 0; i < swapchain->num_images; i++)
-        ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
-    if (active)
-        swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
-    if (!allocator)
-        allocator = &GetData(device).allocator;
-    swapchain->~Swapchain();
-    allocator->pfnFree(allocator->pUserData, swapchain);
+    DestroySwapchainInternal(device, swapchain_handle, allocator);
 }
 
 VKAPI_ATTR
@@ -1457,8 +1433,6 @@
     int fence_fd;
     err = window->dequeueBuffer(window, &buffer, &fence_fd);
     if (err != 0) {
-        // TODO(jessehall): Improve error reporting. Can we enumerate possible
-        // errors and translate them to valid Vulkan result codes?
         ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
@@ -1513,8 +1487,6 @@
                               uint32_t* pImageIndex) {
     ATRACE_CALL();
 
-    // TODO: this should actually be the other way around and this function
-    // should handle any additional structures that get passed in
     return AcquireNextImageKHR(device, pAcquireInfo->swapchain,
                                pAcquireInfo->timeout, pAcquireInfo->semaphore,
                                pAcquireInfo->fence, pImageIndex);
@@ -1673,9 +1645,9 @@
 
                     // Add a new timing record with the user's presentID and
                     // the nativeFrameId.
-                    swapchain.timing.push_back(TimingInfo(time, nativeFrameId));
+                    swapchain.timing.emplace_back(time, nativeFrameId);
                     while (swapchain.timing.size() > MAX_TIMING_INFOS) {
-                        swapchain.timing.removeAt(0);
+                        swapchain.timing.erase(swapchain.timing.begin());
                     }
                     if (time->desiredPresentTime) {
                         // Set the desiredPresentTime:
@@ -1692,17 +1664,16 @@
                 err = window->queueBuffer(window, img.buffer.get(), fence);
                 // queueBuffer always closes fence, even on error
                 if (err != 0) {
-                    // TODO(jessehall): What now? We should probably cancel the
-                    // buffer, I guess?
                     ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
                     swapchain_result = WorstPresentResult(
                         swapchain_result, VK_ERROR_OUT_OF_DATE_KHR);
+                } else {
+                    if (img.dequeue_fence >= 0) {
+                        close(img.dequeue_fence);
+                        img.dequeue_fence = -1;
+                    }
+                    img.dequeued = false;
                 }
-                if (img.dequeue_fence >= 0) {
-                    close(img.dequeue_fence);
-                    img.dequeue_fence = -1;
-                }
-                img.dequeued = false;
 
                 // If the swapchain is in shared mode, immediately dequeue the
                 // buffer so it can be presented again without an intervening
@@ -1729,7 +1700,6 @@
                 }
             }
             if (swapchain_result != VK_SUCCESS) {
-                ReleaseSwapchainImage(device, window, fence, img);
                 OrphanSwapchain(device, &swapchain);
             }
             int window_transform_hint;
diff --git a/vulkan/nulldrv/null_driver.tmpl b/vulkan/nulldrv/null_driver.tmpl
index ce15517..0f53015 100644
--- a/vulkan/nulldrv/null_driver.tmpl
+++ b/vulkan/nulldrv/null_driver.tmpl
@@ -97,9 +97,10 @@

 // WARNING: This file is generated. See ../README.md for instructions.

-#include "null_driver_gen.h"
 #include <algorithm>

+#include "null_driver_gen.h"

 using namespace null_driver;

 namespace {
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
index 92b7468..b8d7d2b 100644
--- a/vulkan/nulldrv/null_driver_gen.cpp
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -17,6 +17,7 @@
 // WARNING: This file is generated. See ../README.md for instructions.
 
 #include <algorithm>
+
 #include "null_driver_gen.h"
 
 using namespace null_driver;