graphics: add ComposerCommandEngine

Add ComposerCommandEngine to the HAL support library to replace
ComposerClient::CommandReader and ComposerClient::mWriter.

Test: boots and VTS
Change-Id: I2d1281d37180497cbd5c623ef005cee44bce377e
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp
index 807ff81..4fda5ae 100644
--- a/graphics/composer/2.1/default/ComposerClient.cpp
+++ b/graphics/composer/2.1/default/ComposerClient.cpp
@@ -29,7 +29,7 @@
 namespace implementation {
 
 ComposerClient::ComposerClient(ComposerHal& hal)
-    : mHal(hal), mWriter(kWriterInitialSize)
+    : mHal(hal)
 {
 }
 
@@ -106,7 +106,7 @@
         LOG_ALWAYS_FATAL("failed to create resources");
     }
 
-    mReader = createCommandReader();
+    mCommandEngine = createCommandEngine();
 }
 
 void ComposerClient::onHotplug(Display display,
@@ -333,8 +333,8 @@
 Return<Error> ComposerClient::setInputCommandQueue(
         const MQDescriptorSync<uint32_t>& descriptor)
 {
-    std::lock_guard<std::mutex> lock(mCommandMutex);
-    return mReader->setMQDescriptor(descriptor) ?
+    std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+    return mCommandEngine->setInputMQDescriptor(descriptor) ?
         Error::NONE : Error::NO_RESOURCES;
 }
 
@@ -344,7 +344,7 @@
     // no locking as we require this function to be called inside
     // executeCommands_cb
 
-    auto outDescriptor = mWriter.getMQDescriptor();
+    auto outDescriptor = mCommandEngine->getOutputMQDescriptor();
     if (outDescriptor) {
         hidl_cb(Error::NONE, *outDescriptor);
     } else {
@@ -358,27 +358,17 @@
         const hidl_vec<hidl_handle>& inHandles,
         executeCommands_cb hidl_cb)
 {
-    std::lock_guard<std::mutex> lock(mCommandMutex);
+    std::lock_guard<std::mutex> lock(mCommandEngineMutex);
 
     bool outChanged = false;
     uint32_t outLength = 0;
     hidl_vec<hidl_handle> outHandles;
+    Error error = mCommandEngine->execute(inLength, inHandles,
+            &outChanged, &outLength, &outHandles);
 
-    if (!mReader->readQueue(inLength, inHandles)) {
-        hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
-        return Void();
-    }
+    hidl_cb(error, outChanged, outLength, outHandles);
 
-    Error err = mReader->parse();
-    if (err == Error::NONE &&
-            !mWriter.writeQueue(&outChanged, &outLength, &outHandles)) {
-        err = Error::NO_RESOURCES;
-    }
-
-    hidl_cb(err, outChanged, outLength, outHandles);
-
-    mReader->reset();
-    mWriter.reset();
+    mCommandEngine->reset();
 
     return Void();
 }
@@ -388,571 +378,10 @@
     return ComposerResources::create();
 }
 
-std::unique_ptr<ComposerClient::CommandReader>
-ComposerClient::createCommandReader()
+std::unique_ptr<ComposerCommandEngine>
+ComposerClient::createCommandEngine()
 {
-    return std::unique_ptr<ComposerClient::CommandReader>(
-        new CommandReader(*this));
-}
-
-ComposerClient::CommandReader::CommandReader(ComposerClient& client)
-    : mHal(client.mHal), mResources(client.mResources.get()), mWriter(client.mWriter)
-{
-}
-
-ComposerClient::CommandReader::~CommandReader()
-{
-}
-
-Error ComposerClient::CommandReader::parse()
-{
-    IComposerClient::Command command;
-    uint16_t length = 0;
-
-    while (!isEmpty()) {
-        if (!beginCommand(&command, &length)) {
-            break;
-        }
-
-        bool parsed = parseCommand(command, length);
-        endCommand();
-
-        if (!parsed) {
-            ALOGE("failed to parse command 0x%x, length %" PRIu16,
-                    command, length);
-            break;
-        }
-    }
-
-    return (isEmpty()) ? Error::NONE : Error::BAD_PARAMETER;
-}
-
-bool ComposerClient::CommandReader::parseCommand(
-        IComposerClient::Command command, uint16_t length) {
-    switch (command) {
-    case IComposerClient::Command::SELECT_DISPLAY:
-        return parseSelectDisplay(length);
-    case IComposerClient::Command::SELECT_LAYER:
-        return parseSelectLayer(length);
-    case IComposerClient::Command::SET_COLOR_TRANSFORM:
-        return parseSetColorTransform(length);
-    case IComposerClient::Command::SET_CLIENT_TARGET:
-        return parseSetClientTarget(length);
-    case IComposerClient::Command::SET_OUTPUT_BUFFER:
-        return parseSetOutputBuffer(length);
-    case IComposerClient::Command::VALIDATE_DISPLAY:
-        return parseValidateDisplay(length);
-    case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
-        return parsePresentOrValidateDisplay(length);
-    case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
-        return parseAcceptDisplayChanges(length);
-    case IComposerClient::Command::PRESENT_DISPLAY:
-        return parsePresentDisplay(length);
-    case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
-        return parseSetLayerCursorPosition(length);
-    case IComposerClient::Command::SET_LAYER_BUFFER:
-        return parseSetLayerBuffer(length);
-    case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
-        return parseSetLayerSurfaceDamage(length);
-    case IComposerClient::Command::SET_LAYER_BLEND_MODE:
-        return parseSetLayerBlendMode(length);
-    case IComposerClient::Command::SET_LAYER_COLOR:
-        return parseSetLayerColor(length);
-    case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
-        return parseSetLayerCompositionType(length);
-    case IComposerClient::Command::SET_LAYER_DATASPACE:
-        return parseSetLayerDataspace(length);
-    case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
-        return parseSetLayerDisplayFrame(length);
-    case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
-        return parseSetLayerPlaneAlpha(length);
-    case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
-        return parseSetLayerSidebandStream(length);
-    case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
-        return parseSetLayerSourceCrop(length);
-    case IComposerClient::Command::SET_LAYER_TRANSFORM:
-        return parseSetLayerTransform(length);
-    case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
-        return parseSetLayerVisibleRegion(length);
-    case IComposerClient::Command::SET_LAYER_Z_ORDER:
-        return parseSetLayerZOrder(length);
-    default:
-        return false;
-    }
-}
-
-bool ComposerClient::CommandReader::parseSelectDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kSelectDisplayLength) {
-        return false;
-    }
-
-    mDisplay = read64();
-    mWriter.selectDisplay(mDisplay);
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSelectLayer(uint16_t length)
-{
-    if (length != CommandWriterBase::kSelectLayerLength) {
-        return false;
-    }
-
-    mLayer = read64();
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetColorTransform(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetColorTransformLength) {
-        return false;
-    }
-
-    float matrix[16];
-    for (int i = 0; i < 16; i++) {
-        matrix[i] = readFloat();
-    }
-    auto transform = readSigned();
-
-    auto err = mHal.setColorTransform(mDisplay, matrix, transform);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetClientTarget(uint16_t length)
-{
-    // 4 parameters followed by N rectangles
-    if ((length - 4) % 4 != 0) {
-        return false;
-    }
-
-    bool useCache = false;
-    auto slot = read();
-    auto rawHandle = readHandle(&useCache);
-    auto fence = readFence();
-    auto dataspace = readSigned();
-    auto damage = readRegion((length - 4) / 4);
-    bool closeFence = true;
-
-    const native_handle_t* clientTarget;
-    ComposerResources::ReplacedBufferHandle replacedClientTarget;
-    auto err = mResources->getDisplayClientTarget(mDisplay,
-            slot, useCache, rawHandle, &clientTarget, &replacedClientTarget);
-    if (err == Error::NONE) {
-        err = mHal.setClientTarget(mDisplay, clientTarget, fence,
-                dataspace, damage);
-        if (err == Error::NONE) {
-            closeFence = false;
-        }
-    }
-    if (closeFence) {
-        close(fence);
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetOutputBuffer(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetOutputBufferLength) {
-        return false;
-    }
-
-    bool useCache = false;
-    auto slot = read();
-    auto rawhandle = readHandle(&useCache);
-    auto fence = readFence();
-    bool closeFence = true;
-
-    const native_handle_t* outputBuffer;
-    ComposerResources::ReplacedBufferHandle replacedOutputBuffer;
-    auto err = mResources->getDisplayOutputBuffer(mDisplay,
-            slot, useCache, rawhandle, &outputBuffer, &replacedOutputBuffer);
-    if (err == Error::NONE) {
-        err = mHal.setOutputBuffer(mDisplay, outputBuffer, fence);
-        if (err == Error::NONE) {
-            closeFence = false;
-        }
-    }
-    if (closeFence) {
-        close(fence);
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseValidateDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kValidateDisplayLength) {
-        return false;
-    }
-
-    std::vector<Layer> changedLayers;
-    std::vector<IComposerClient::Composition> compositionTypes;
-    uint32_t displayRequestMask = 0x0;
-    std::vector<Layer> requestedLayers;
-    std::vector<uint32_t> requestMasks;
-
-    auto err = mHal.validateDisplay(mDisplay, &changedLayers,
-            &compositionTypes, &displayRequestMask,
-            &requestedLayers, &requestMasks);
-    if (err == Error::NONE) {
-        mWriter.setChangedCompositionTypes(changedLayers,
-                compositionTypes);
-        mWriter.setDisplayRequests(displayRequestMask,
-                requestedLayers, requestMasks);
-    } else {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parsePresentOrValidateDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kPresentOrValidateDisplayLength) {
-        return false;
-    }
-
-    // First try to Present as is.
-    if (mHal.hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
-        int presentFence = -1;
-        std::vector<Layer> layers;
-        std::vector<int> fences;
-        auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
-        if (err == Error::NONE) {
-            mWriter.setPresentOrValidateResult(1);
-            mWriter.setPresentFence(presentFence);
-            mWriter.setReleaseFences(layers, fences);
-            return true;
-        }
-    }
-
-    // Present has failed. We need to fallback to validate
-    std::vector<Layer> changedLayers;
-    std::vector<IComposerClient::Composition> compositionTypes;
-    uint32_t displayRequestMask = 0x0;
-    std::vector<Layer> requestedLayers;
-    std::vector<uint32_t> requestMasks;
-
-    auto err = mHal.validateDisplay(mDisplay, &changedLayers, &compositionTypes,
-                                    &displayRequestMask, &requestedLayers, &requestMasks);
-    if (err == Error::NONE) {
-        mWriter.setPresentOrValidateResult(0);
-        mWriter.setChangedCompositionTypes(changedLayers,
-                                           compositionTypes);
-        mWriter.setDisplayRequests(displayRequestMask,
-                                   requestedLayers, requestMasks);
-    } else {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseAcceptDisplayChanges(uint16_t length)
-{
-    if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
-        return false;
-    }
-
-    auto err = mHal.acceptDisplayChanges(mDisplay);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parsePresentDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kPresentDisplayLength) {
-        return false;
-    }
-
-    int presentFence = -1;
-    std::vector<Layer> layers;
-    std::vector<int> fences;
-    auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
-    if (err == Error::NONE) {
-        mWriter.setPresentFence(presentFence);
-        mWriter.setReleaseFences(layers, fences);
-    } else {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerCursorPosition(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerCursorPositionLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerCursorPosition(mDisplay, mLayer,
-            readSigned(), readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerBuffer(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerBufferLength) {
-        return false;
-    }
-
-    bool useCache = false;
-    auto slot = read();
-    auto rawHandle = readHandle(&useCache);
-    auto fence = readFence();
-    bool closeFence = true;
-
-    const native_handle_t* buffer;
-    ComposerResources::ReplacedBufferHandle replacedBuffer;
-    auto err = mResources->getLayerBuffer(mDisplay, mLayer,
-            slot, useCache, rawHandle, &buffer, &replacedBuffer);
-    if (err == Error::NONE) {
-        err = mHal.setLayerBuffer(mDisplay, mLayer, buffer, fence);
-        if (err == Error::NONE) {
-            closeFence = false;
-        }
-    }
-    if (closeFence) {
-        close(fence);
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSurfaceDamage(uint16_t length)
-{
-    // N rectangles
-    if (length % 4 != 0) {
-        return false;
-    }
-
-    auto damage = readRegion(length / 4);
-    auto err = mHal.setLayerSurfaceDamage(mDisplay, mLayer, damage);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerBlendMode(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerBlendModeLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerBlendMode(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerColor(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerColorLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerColor(mDisplay, mLayer, readColor());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerCompositionType(
-        uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerCompositionTypeLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerCompositionType(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerDataspace(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerDataspaceLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerDataspace(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerDisplayFrame(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerDisplayFrameLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerDisplayFrame(mDisplay, mLayer, readRect());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerPlaneAlpha(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerPlaneAlpha(mDisplay, mLayer, readFloat());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSidebandStream(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerSidebandStreamLength) {
-        return false;
-    }
-
-    auto rawHandle = readHandle();
-
-    const native_handle_t* stream;
-    ComposerResources::ReplacedStreamHandle replacedStream;
-    auto err = mResources->getLayerSidebandStream(mDisplay, mLayer,
-            rawHandle, &stream, &replacedStream);
-    if (err == Error::NONE) {
-        err = mHal.setLayerSidebandStream(mDisplay, mLayer, stream);
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSourceCrop(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerSourceCropLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerSourceCrop(mDisplay, mLayer, readFRect());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerTransform(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerTransformLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerTransform(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerVisibleRegion(uint16_t length)
-{
-    // N rectangles
-    if (length % 4 != 0) {
-        return false;
-    }
-
-    auto region = readRegion(length / 4);
-    auto err = mHal.setLayerVisibleRegion(mDisplay, mLayer, region);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerZOrder(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerZOrderLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerZOrder(mDisplay, mLayer, read());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-hwc_rect_t ComposerClient::CommandReader::readRect()
-{
-    return hwc_rect_t{
-        readSigned(),
-        readSigned(),
-        readSigned(),
-        readSigned(),
-    };
-}
-
-std::vector<hwc_rect_t> ComposerClient::CommandReader::readRegion(size_t count)
-{
-    std::vector<hwc_rect_t> region;
-    region.reserve(count);
-    while (count > 0) {
-        region.emplace_back(readRect());
-        count--;
-    }
-
-    return region;
-}
-
-hwc_frect_t ComposerClient::CommandReader::readFRect()
-{
-    return hwc_frect_t{
-        readFloat(),
-        readFloat(),
-        readFloat(),
-        readFloat(),
-    };
+    return std::make_unique<ComposerCommandEngine>(&mHal, mResources.get());
 }
 
 } // namespace implementation
diff --git a/graphics/composer/2.1/default/ComposerClient.h b/graphics/composer/2.1/default/ComposerClient.h
index ee71492..bbb0522 100644
--- a/graphics/composer/2.1/default/ComposerClient.h
+++ b/graphics/composer/2.1/default/ComposerClient.h
@@ -22,6 +22,7 @@
 #include <vector>
 
 #include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerCommandEngine.h>
 #include <composer-hal/2.1/ComposerHal.h>
 #include <composer-hal/2.1/ComposerResources.h>
 #include <hardware/hwcomposer2.h>
@@ -92,68 +93,17 @@
             executeCommands_cb hidl_cb) override;
 
 protected:
-    class CommandReader : public CommandReaderBase {
-    public:
-        CommandReader(ComposerClient& client);
-        virtual ~CommandReader();
-
-        Error parse();
-
-    protected:
-        virtual bool parseCommand(IComposerClient::Command command,
-                uint16_t length);
-
-        bool parseSelectDisplay(uint16_t length);
-        bool parseSelectLayer(uint16_t length);
-        bool parseSetColorTransform(uint16_t length);
-        bool parseSetClientTarget(uint16_t length);
-        bool parseSetOutputBuffer(uint16_t length);
-        bool parseValidateDisplay(uint16_t length);
-        bool parsePresentOrValidateDisplay(uint16_t length);
-        bool parseAcceptDisplayChanges(uint16_t length);
-        bool parsePresentDisplay(uint16_t length);
-        bool parseSetLayerCursorPosition(uint16_t length);
-        bool parseSetLayerBuffer(uint16_t length);
-        bool parseSetLayerSurfaceDamage(uint16_t length);
-        bool parseSetLayerBlendMode(uint16_t length);
-        bool parseSetLayerColor(uint16_t length);
-        bool parseSetLayerCompositionType(uint16_t length);
-        bool parseSetLayerDataspace(uint16_t length);
-        bool parseSetLayerDisplayFrame(uint16_t length);
-        bool parseSetLayerPlaneAlpha(uint16_t length);
-        bool parseSetLayerSidebandStream(uint16_t length);
-        bool parseSetLayerSourceCrop(uint16_t length);
-        bool parseSetLayerTransform(uint16_t length);
-        bool parseSetLayerVisibleRegion(uint16_t length);
-        bool parseSetLayerZOrder(uint16_t length);
-
-        hwc_rect_t readRect();
-        std::vector<hwc_rect_t> readRegion(size_t count);
-        hwc_frect_t readFRect();
-
-        ComposerHal& mHal;
-        ComposerResources* mResources;
-        CommandWriterBase& mWriter;
-
-        Display mDisplay;
-        Layer mLayer;
-    };
+    virtual std::unique_ptr<ComposerResources> createResources();
+    virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine();
 
     void destroyResources();
 
-    virtual std::unique_ptr<ComposerResources> createResources();
-    virtual std::unique_ptr<CommandReader> createCommandReader();
-
     ComposerHal& mHal;
 
     std::unique_ptr<ComposerResources> mResources;
 
-    // 64KiB minus a small space for metadata such as read/write pointers
-    static constexpr size_t kWriterInitialSize =
-        64 * 1024 / sizeof(uint32_t) - 16;
-    std::mutex mCommandMutex;
-    std::unique_ptr<CommandReader> mReader;
-    CommandWriterBase mWriter;
+    std::mutex mCommandEngineMutex;
+    std::unique_ptr<ComposerCommandEngine> mCommandEngine;
 
     sp<IComposerCallback> mCallback;
 };
diff --git a/graphics/composer/2.1/utils/hal/Android.bp b/graphics/composer/2.1/utils/hal/Android.bp
index a8ff59d..f24e768 100644
--- a/graphics/composer/2.1/utils/hal/Android.bp
+++ b/graphics/composer/2.1/utils/hal/Android.bp
@@ -27,5 +27,11 @@
         "android.hardware.graphics.mapper@2.0",
         "libhardware",
     ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
     export_include_dirs: ["include"],
 }
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
new file mode 100644
index 0000000..36aa64e
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
@@ -0,0 +1,594 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerCommandEngine.h included without LOG_TAG"
+#endif
+
+#include <vector>
+
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#include <composer-hal/2.1/ComposerResources.h>
+// TODO remove hwcomposer_defs.h dependency
+#include <hardware/hwcomposer_defs.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+// TODO own a CommandReaderBase rather than subclassing
+class ComposerCommandEngine : protected CommandReaderBase {
+   public:
+    ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
+        : mHal(hal), mResources(resources) {}
+
+    virtual ~ComposerCommandEngine() = default;
+
+    bool setInputMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor) {
+        return setMQDescriptor(descriptor);
+    }
+
+    Error execute(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles, bool* outQueueChanged,
+                  uint32_t* outCommandLength, hidl_vec<hidl_handle>* outCommandHandles) {
+        if (!readQueue(inLength, inHandles)) {
+            return Error::BAD_PARAMETER;
+        }
+
+        IComposerClient::Command command;
+        uint16_t length = 0;
+        while (!isEmpty()) {
+            if (!beginCommand(&command, &length)) {
+                break;
+            }
+
+            bool parsed = executeCommand(command, length);
+            endCommand();
+
+            if (!parsed) {
+                ALOGE("failed to parse command 0x%x, length %" PRIu16, command, length);
+                break;
+            }
+        }
+
+        if (!isEmpty()) {
+            return Error::BAD_PARAMETER;
+        }
+
+        return mWriter.writeQueue(outQueueChanged, outCommandLength, outCommandHandles)
+                   ? Error::NONE
+                   : Error::NO_RESOURCES;
+    }
+
+    const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter.getMQDescriptor(); }
+
+    void reset() {
+        CommandReaderBase::reset();
+        mWriter.reset();
+    }
+
+   protected:
+    virtual bool executeCommand(IComposerClient::Command command, uint16_t length) {
+        switch (command) {
+            case IComposerClient::Command::SELECT_DISPLAY:
+                return executeSelectDisplay(length);
+            case IComposerClient::Command::SELECT_LAYER:
+                return executeSelectLayer(length);
+            case IComposerClient::Command::SET_COLOR_TRANSFORM:
+                return executeSetColorTransform(length);
+            case IComposerClient::Command::SET_CLIENT_TARGET:
+                return executeSetClientTarget(length);
+            case IComposerClient::Command::SET_OUTPUT_BUFFER:
+                return executeSetOutputBuffer(length);
+            case IComposerClient::Command::VALIDATE_DISPLAY:
+                return executeValidateDisplay(length);
+            case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
+                return executePresentOrValidateDisplay(length);
+            case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
+                return executeAcceptDisplayChanges(length);
+            case IComposerClient::Command::PRESENT_DISPLAY:
+                return executePresentDisplay(length);
+            case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
+                return executeSetLayerCursorPosition(length);
+            case IComposerClient::Command::SET_LAYER_BUFFER:
+                return executeSetLayerBuffer(length);
+            case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
+                return executeSetLayerSurfaceDamage(length);
+            case IComposerClient::Command::SET_LAYER_BLEND_MODE:
+                return executeSetLayerBlendMode(length);
+            case IComposerClient::Command::SET_LAYER_COLOR:
+                return executeSetLayerColor(length);
+            case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
+                return executeSetLayerCompositionType(length);
+            case IComposerClient::Command::SET_LAYER_DATASPACE:
+                return executeSetLayerDataspace(length);
+            case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
+                return executeSetLayerDisplayFrame(length);
+            case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
+                return executeSetLayerPlaneAlpha(length);
+            case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
+                return executeSetLayerSidebandStream(length);
+            case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
+                return executeSetLayerSourceCrop(length);
+            case IComposerClient::Command::SET_LAYER_TRANSFORM:
+                return executeSetLayerTransform(length);
+            case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
+                return executeSetLayerVisibleRegion(length);
+            case IComposerClient::Command::SET_LAYER_Z_ORDER:
+                return executeSetLayerZOrder(length);
+            default:
+                return false;
+        }
+    }
+
+    bool executeSelectDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kSelectDisplayLength) {
+            return false;
+        }
+
+        mCurrentDisplay = read64();
+        mWriter.selectDisplay(mCurrentDisplay);
+
+        return true;
+    }
+
+    bool executeSelectLayer(uint16_t length) {
+        if (length != CommandWriterBase::kSelectLayerLength) {
+            return false;
+        }
+
+        mCurrentLayer = read64();
+
+        return true;
+    }
+
+    bool executeSetColorTransform(uint16_t length) {
+        if (length != CommandWriterBase::kSetColorTransformLength) {
+            return false;
+        }
+
+        float matrix[16];
+        for (int i = 0; i < 16; i++) {
+            matrix[i] = readFloat();
+        }
+        auto transform = readSigned();
+
+        auto err = mHal->setColorTransform(mCurrentDisplay, matrix, transform);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetClientTarget(uint16_t length) {
+        // 4 parameters followed by N rectangles
+        if ((length - 4) % 4 != 0) {
+            return false;
+        }
+
+        bool useCache = false;
+        auto slot = read();
+        auto rawHandle = readHandle(&useCache);
+        auto fence = readFence();
+        auto dataspace = readSigned();
+        auto damage = readRegion((length - 4) / 4);
+        bool closeFence = true;
+
+        const native_handle_t* clientTarget;
+        ComposerResources::ReplacedBufferHandle replacedClientTarget;
+        auto err = mResources->getDisplayClientTarget(mCurrentDisplay, slot, useCache, rawHandle,
+                                                      &clientTarget, &replacedClientTarget);
+        if (err == Error::NONE) {
+            err = mHal->setClientTarget(mCurrentDisplay, clientTarget, fence, dataspace, damage);
+            if (err == Error::NONE) {
+                closeFence = false;
+            }
+        }
+        if (closeFence) {
+            close(fence);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetOutputBuffer(uint16_t length) {
+        if (length != CommandWriterBase::kSetOutputBufferLength) {
+            return false;
+        }
+
+        bool useCache = false;
+        auto slot = read();
+        auto rawhandle = readHandle(&useCache);
+        auto fence = readFence();
+        bool closeFence = true;
+
+        const native_handle_t* outputBuffer;
+        ComposerResources::ReplacedBufferHandle replacedOutputBuffer;
+        auto err = mResources->getDisplayOutputBuffer(mCurrentDisplay, slot, useCache, rawhandle,
+                                                      &outputBuffer, &replacedOutputBuffer);
+        if (err == Error::NONE) {
+            err = mHal->setOutputBuffer(mCurrentDisplay, outputBuffer, fence);
+            if (err == Error::NONE) {
+                closeFence = false;
+            }
+        }
+        if (closeFence) {
+            close(fence);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeValidateDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kValidateDisplayLength) {
+            return false;
+        }
+
+        std::vector<Layer> changedLayers;
+        std::vector<IComposerClient::Composition> compositionTypes;
+        uint32_t displayRequestMask = 0x0;
+        std::vector<Layer> requestedLayers;
+        std::vector<uint32_t> requestMasks;
+
+        auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
+                                         &displayRequestMask, &requestedLayers, &requestMasks);
+        if (err == Error::NONE) {
+            mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+            mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+        } else {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executePresentOrValidateDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kPresentOrValidateDisplayLength) {
+            return false;
+        }
+
+        // First try to Present as is.
+        if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
+            int presentFence = -1;
+            std::vector<Layer> layers;
+            std::vector<int> fences;
+            auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
+            if (err == Error::NONE) {
+                mWriter.setPresentOrValidateResult(1);
+                mWriter.setPresentFence(presentFence);
+                mWriter.setReleaseFences(layers, fences);
+                return true;
+            }
+        }
+
+        // Present has failed. We need to fallback to validate
+        std::vector<Layer> changedLayers;
+        std::vector<IComposerClient::Composition> compositionTypes;
+        uint32_t displayRequestMask = 0x0;
+        std::vector<Layer> requestedLayers;
+        std::vector<uint32_t> requestMasks;
+
+        auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
+                                         &displayRequestMask, &requestedLayers, &requestMasks);
+        if (err == Error::NONE) {
+            mWriter.setPresentOrValidateResult(0);
+            mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+            mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+        } else {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeAcceptDisplayChanges(uint16_t length) {
+        if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
+            return false;
+        }
+
+        auto err = mHal->acceptDisplayChanges(mCurrentDisplay);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executePresentDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kPresentDisplayLength) {
+            return false;
+        }
+
+        int presentFence = -1;
+        std::vector<Layer> layers;
+        std::vector<int> fences;
+        auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
+        if (err == Error::NONE) {
+            mWriter.setPresentFence(presentFence);
+            mWriter.setReleaseFences(layers, fences);
+        } else {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerCursorPosition(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerCursorPositionLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerCursorPosition(mCurrentDisplay, mCurrentLayer, readSigned(),
+                                                readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerBuffer(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerBufferLength) {
+            return false;
+        }
+
+        bool useCache = false;
+        auto slot = read();
+        auto rawHandle = readHandle(&useCache);
+        auto fence = readFence();
+        bool closeFence = true;
+
+        const native_handle_t* buffer;
+        ComposerResources::ReplacedBufferHandle replacedBuffer;
+        auto err = mResources->getLayerBuffer(mCurrentDisplay, mCurrentLayer, slot, useCache,
+                                              rawHandle, &buffer, &replacedBuffer);
+        if (err == Error::NONE) {
+            err = mHal->setLayerBuffer(mCurrentDisplay, mCurrentLayer, buffer, fence);
+            if (err == Error::NONE) {
+                closeFence = false;
+            }
+        }
+        if (closeFence) {
+            close(fence);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerSurfaceDamage(uint16_t length) {
+        // N rectangles
+        if (length % 4 != 0) {
+            return false;
+        }
+
+        auto damage = readRegion(length / 4);
+        auto err = mHal->setLayerSurfaceDamage(mCurrentDisplay, mCurrentLayer, damage);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerBlendMode(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerBlendModeLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerBlendMode(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerColor(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerColorLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerColor(mCurrentDisplay, mCurrentLayer, readColor());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerCompositionType(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerCompositionTypeLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerCompositionType(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerDataspace(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerDataspaceLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerDataspace(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerDisplayFrame(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerDisplayFrameLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerDisplayFrame(mCurrentDisplay, mCurrentLayer, readRect());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerPlaneAlpha(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerPlaneAlpha(mCurrentDisplay, mCurrentLayer, readFloat());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerSidebandStream(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerSidebandStreamLength) {
+            return false;
+        }
+
+        auto rawHandle = readHandle();
+
+        const native_handle_t* stream;
+        ComposerResources::ReplacedStreamHandle replacedStream;
+        auto err = mResources->getLayerSidebandStream(mCurrentDisplay, mCurrentLayer, rawHandle,
+                                                      &stream, &replacedStream);
+        if (err == Error::NONE) {
+            err = mHal->setLayerSidebandStream(mCurrentDisplay, mCurrentLayer, stream);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerSourceCrop(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerSourceCropLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerSourceCrop(mCurrentDisplay, mCurrentLayer, readFRect());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerTransform(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerTransformLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerTransform(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerVisibleRegion(uint16_t length) {
+        // N rectangles
+        if (length % 4 != 0) {
+            return false;
+        }
+
+        auto region = readRegion(length / 4);
+        auto err = mHal->setLayerVisibleRegion(mCurrentDisplay, mCurrentLayer, region);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerZOrder(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerZOrderLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerZOrder(mCurrentDisplay, mCurrentLayer, read());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    hwc_rect_t readRect() {
+        return hwc_rect_t{
+            readSigned(), readSigned(), readSigned(), readSigned(),
+        };
+    }
+
+    std::vector<hwc_rect_t> readRegion(size_t count) {
+        std::vector<hwc_rect_t> region;
+        region.reserve(count);
+        while (count > 0) {
+            region.emplace_back(readRect());
+            count--;
+        }
+
+        return region;
+    }
+
+    hwc_frect_t readFRect() {
+        return hwc_frect_t{
+            readFloat(), readFloat(), readFloat(), readFloat(),
+        };
+    }
+
+    ComposerHal* mHal;
+    ComposerResources* mResources;
+
+    // 64KiB minus a small space for metadata such as read/write pointers
+    static constexpr size_t kWriterInitialSize = 64 * 1024 / sizeof(uint32_t) - 16;
+    CommandWriterBase mWriter{kWriterInitialSize};
+
+    Display mCurrentDisplay = 0;
+    Layer mCurrentLayer = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android