459 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			459 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright (C) 2021 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.
 | |
|  */
 | |
| 
 | |
| #include <set>
 | |
| 
 | |
| #include "ComposerCommandEngine.h"
 | |
| #include "Util.h"
 | |
| 
 | |
| namespace aidl::android::hardware::graphics::composer3::impl {
 | |
| 
 | |
| #define DISPATCH_LAYER_COMMAND(display, layerCmd, field, funcName)               \
 | |
|     do {                                                                         \
 | |
|         if (layerCmd.field) {                                                    \
 | |
|             executeSetLayer##funcName(display, layerCmd.layer, *layerCmd.field); \
 | |
|         }                                                                        \
 | |
|     } while (0)
 | |
| 
 | |
| #define DISPATCH_LAYER_COMMAND_SIMPLE(display, layerCmd, field, funcName)     \
 | |
|     do {                                                                      \
 | |
|         dispatchLayerCommand(display, layerCmd.layer, #field, layerCmd.field, \
 | |
|                              &IComposerHal::setLayer##funcName);              \
 | |
|     } while (0)
 | |
| 
 | |
| #define DISPATCH_DISPLAY_COMMAND(displayCmd, field, funcName)                \
 | |
|     do {                                                                     \
 | |
|         if (displayCmd.field) {                                              \
 | |
|             execute##funcName(displayCmd.display, *displayCmd.field);        \
 | |
|         }                                                                    \
 | |
|     } while (0)
 | |
| 
 | |
| #define DISPATCH_DISPLAY_BOOL_COMMAND(displayCmd, field, funcName)           \
 | |
|     do {                                                                     \
 | |
|         if (displayCmd.field) {                                              \
 | |
|             execute##funcName(displayCmd.display);                           \
 | |
|         }                                                                    \
 | |
|     } while (0)
 | |
| 
 | |
| #define DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCmd, field, data, funcName) \
 | |
|     do {                                                                          \
 | |
|         if (displayCmd.field) {                                                   \
 | |
|             execute##funcName(displayCmd.display, displayCmd.data);               \
 | |
|         }                                                                         \
 | |
|     } while (0)
 | |
| 
 | |
| bool ComposerCommandEngine::init() {
 | |
|     mWriter = std::make_unique<ComposerServiceWriter>();
 | |
|     return (mWriter != nullptr);
 | |
| }
 | |
| 
 | |
| int32_t ComposerCommandEngine::execute(const std::vector<DisplayCommand>& commands,
 | |
|                                        std::vector<CommandResultPayload>* result) {
 | |
|     std::set<int64_t> displaysPendingBrightenssChange;
 | |
|     mCommandIndex = 0;
 | |
|     for (const auto& command : commands) {
 | |
|         dispatchDisplayCommand(command);
 | |
|         ++mCommandIndex;
 | |
|         // The input commands could have 2+ commands for the same display.
 | |
|         // If the first has pending brightness change, the second presentDisplay will apply it.
 | |
|         if (command.validateDisplay || command.presentDisplay ||
 | |
|             command.presentOrValidateDisplay) {
 | |
|             displaysPendingBrightenssChange.erase(command.display);
 | |
|         } else if (command.brightness) {
 | |
|             displaysPendingBrightenssChange.insert(command.display);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     *result = mWriter->getPendingCommandResults();
 | |
|     mWriter->reset();
 | |
| 
 | |
|     // standalone display brightness command shouldn't wait for next present or validate
 | |
|     for (auto display : displaysPendingBrightenssChange) {
 | |
|         auto err = mHal->flushDisplayBrightnessChange(display);
 | |
|         if (err) {
 | |
|             return err;
 | |
|         }
 | |
|     }
 | |
|     return ::android::NO_ERROR;
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::dispatchDisplayCommand(const DisplayCommand& command) {
 | |
|     //  place SetDisplayBrightness before SetLayerWhitePointNits since current
 | |
|     //  display brightness is used to validate the layer white point nits.
 | |
|     DISPATCH_DISPLAY_COMMAND(command, brightness, SetDisplayBrightness);
 | |
|     for (const auto& layerCmd : command.layers) {
 | |
|         dispatchLayerCommand(command.display, layerCmd);
 | |
|     }
 | |
| 
 | |
|     DISPATCH_DISPLAY_COMMAND(command, colorTransformMatrix, SetColorTransform);
 | |
|     DISPATCH_DISPLAY_COMMAND(command, clientTarget, SetClientTarget);
 | |
|     DISPATCH_DISPLAY_COMMAND(command, virtualDisplayOutputBuffer, SetOutputBuffer);
 | |
|     DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(command, validateDisplay, expectedPresentTime,
 | |
|                                            ValidateDisplay);
 | |
|     DISPATCH_DISPLAY_BOOL_COMMAND(command, acceptDisplayChanges, AcceptDisplayChanges);
 | |
|     DISPATCH_DISPLAY_BOOL_COMMAND(command, presentDisplay, PresentDisplay);
 | |
|     DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(command, presentOrValidateDisplay, expectedPresentTime,
 | |
|                                            PresentOrValidateDisplay);
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::dispatchLayerCommand(int64_t display, const LayerCommand& command) {
 | |
|     DISPATCH_LAYER_COMMAND(display, command, cursorPosition, CursorPosition);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, buffer, Buffer);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, damage, SurfaceDamage);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, blendMode, BlendMode);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, color, Color);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, composition, Composition);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, dataspace, Dataspace);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, displayFrame, DisplayFrame);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, planeAlpha, PlaneAlpha);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, sidebandStream, SidebandStream);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, sourceCrop, SourceCrop);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, transform, Transform);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, visibleRegion, VisibleRegion);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, z, ZOrder);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, colorTransform, ColorTransform);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, brightness, Brightness);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, perFrameMetadata, PerFrameMetadata);
 | |
|     DISPATCH_LAYER_COMMAND(display, command, perFrameMetadataBlob, PerFrameMetadataBlobs);
 | |
|     DISPATCH_LAYER_COMMAND_SIMPLE(display, command, blockingRegion, BlockingRegion);
 | |
| }
 | |
| 
 | |
| int32_t ComposerCommandEngine::executeValidateDisplayInternal(int64_t display) {
 | |
|     std::vector<int64_t> changedLayers;
 | |
|     std::vector<Composition> compositionTypes;
 | |
|     uint32_t displayRequestMask = 0x0;
 | |
|     std::vector<int64_t> requestedLayers;
 | |
|     std::vector<int32_t> requestMasks;
 | |
|     ClientTargetProperty clientTargetProperty{common::PixelFormat::RGBA_8888,
 | |
|                                               common::Dataspace::UNKNOWN};
 | |
|     DimmingStage dimmingStage;
 | |
|     auto err =
 | |
|             mHal->validateDisplay(display, &changedLayers, &compositionTypes, &displayRequestMask,
 | |
|                                   &requestedLayers, &requestMasks, &clientTargetProperty,
 | |
|                                   &dimmingStage);
 | |
|     mResources->setDisplayMustValidateState(display, false);
 | |
|     if (!err) {
 | |
|         mWriter->setChangedCompositionTypes(display, changedLayers, compositionTypes);
 | |
|         mWriter->setDisplayRequests(display, displayRequestMask, requestedLayers, requestMasks);
 | |
|         static constexpr float kBrightness = 1.f;
 | |
|         mWriter->setClientTargetProperty(display, clientTargetProperty, kBrightness, dimmingStage);
 | |
|     } else {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
|     return err;
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetColorTransform(int64_t display,
 | |
|                                                      const std::vector<float>& matrix) {
 | |
|     auto err = mHal->setColorTransform(display, matrix);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetClientTarget(int64_t display, const ClientTarget& command) {
 | |
|     bool useCache = !command.buffer.handle;
 | |
|     buffer_handle_t handle = useCache
 | |
|                              ? nullptr
 | |
|                              : ::android::makeFromAidl(*command.buffer.handle);
 | |
|     buffer_handle_t clientTarget;
 | |
|     auto bufferReleaser = mResources->createReleaser(true);
 | |
|     auto err = mResources->getDisplayClientTarget(display, command.buffer.slot, useCache, handle,
 | |
|                                                   clientTarget, bufferReleaser.get());
 | |
|     if (!err) {
 | |
|         err = mHal->setClientTarget(display, clientTarget, command.buffer.fence,
 | |
|                                     command.dataspace, command.damage);
 | |
|         if (err) {
 | |
|             LOG(ERROR) << __func__ << " setClientTarget: err " << err;
 | |
|             mWriter->setError(mCommandIndex, err);
 | |
|         }
 | |
|     } else {
 | |
|         LOG(ERROR) << __func__ << " getDisplayClientTarget : err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetOutputBuffer(uint64_t display, const Buffer& buffer) {
 | |
|     bool useCache = !buffer.handle;
 | |
|     buffer_handle_t handle = useCache
 | |
|                              ? nullptr
 | |
|                              : ::android::makeFromAidl(*buffer.handle);
 | |
|     buffer_handle_t outputBuffer;
 | |
|     auto bufferReleaser = mResources->createReleaser(true);
 | |
|     auto err = mResources->getDisplayOutputBuffer(display, buffer.slot, useCache, handle,
 | |
|                                                   outputBuffer, bufferReleaser.get());
 | |
|     if (!err) {
 | |
|         err = mHal->setOutputBuffer(display, outputBuffer, buffer.fence);
 | |
|         if (err) {
 | |
|             LOG(ERROR) << __func__ << " setOutputBuffer: err " << err;
 | |
|             mWriter->setError(mCommandIndex, err);
 | |
|         }
 | |
|     } else {
 | |
|         LOG(ERROR) << __func__ << " getDisplayOutputBuffer: err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetExpectedPresentTimeInternal(
 | |
|         int64_t display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
 | |
|     mHal->setExpectedPresentTime(display, expectedPresentTime);
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeValidateDisplay(
 | |
|         int64_t display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
 | |
|     executeSetExpectedPresentTimeInternal(display, expectedPresentTime);
 | |
|     executeValidateDisplayInternal(display);
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetDisplayBrightness(uint64_t display,
 | |
|                                         const DisplayBrightness& command) {
 | |
|     auto err = mHal->setDisplayBrightness(display, command.brightness);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executePresentOrValidateDisplay(
 | |
|         int64_t display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
 | |
|     executeSetExpectedPresentTimeInternal(display, expectedPresentTime);
 | |
| 
 | |
|     int err;
 | |
|     // First try to Present as is.
 | |
|     if (mHal->hasCapability(Capability::SKIP_VALIDATE)) {
 | |
|         err = mResources->mustValidateDisplay(display) ? IComposerClient::EX_NOT_VALIDATED
 | |
|                                                        : executePresentDisplay(display);
 | |
|         if (!err) {
 | |
|             mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Presented);
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Fallback to validate
 | |
|     err = executeValidateDisplayInternal(display);
 | |
|     if (!err) {
 | |
|         mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Validated);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeAcceptDisplayChanges(int64_t display) {
 | |
|     auto err = mHal->acceptDisplayChanges(display);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| int ComposerCommandEngine::executePresentDisplay(int64_t display) {
 | |
|     ndk::ScopedFileDescriptor presentFence;
 | |
|     std::vector<int64_t> layers;
 | |
|     std::vector<ndk::ScopedFileDescriptor> fences;
 | |
|     auto err = mHal->presentDisplay(display, presentFence, &layers, &fences);
 | |
|     if (!err) {
 | |
|         mWriter->setPresentFence(display, std::move(presentFence));
 | |
|         mWriter->setReleaseFences(display, layers, std::move(fences));
 | |
|     }
 | |
| 
 | |
|     return err;
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerCursorPosition(int64_t display, int64_t layer,
 | |
|                                        const common::Point& cursorPosition) {
 | |
|     auto err = mHal->setLayerCursorPosition(display, layer, cursorPosition.x, cursorPosition.y);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerBuffer(int64_t display, int64_t layer,
 | |
|                                                   const Buffer& buffer) {
 | |
|     bool useCache = !buffer.handle;
 | |
|     buffer_handle_t handle = useCache
 | |
|                              ? nullptr
 | |
|                              : ::android::makeFromAidl(*buffer.handle);
 | |
|     buffer_handle_t hwcBuffer;
 | |
|     auto bufferReleaser = mResources->createReleaser(true);
 | |
|     auto err = mResources->getLayerBuffer(display, layer, buffer.slot, useCache,
 | |
|                                           handle, hwcBuffer, bufferReleaser.get());
 | |
|     if (!err) {
 | |
|         err = mHal->setLayerBuffer(display, layer, hwcBuffer, buffer.fence);
 | |
|         if (err) {
 | |
|             LOG(ERROR) << __func__ << ": setLayerBuffer err " << err;
 | |
|             mWriter->setError(mCommandIndex, err);
 | |
|         }
 | |
|     } else {
 | |
|         LOG(ERROR) << __func__ << ": getLayerBuffer err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerSurfaceDamage(int64_t display, int64_t layer,
 | |
|                               const std::vector<std::optional<common::Rect>>& damage) {
 | |
|     auto err = mHal->setLayerSurfaceDamage(display, layer, damage);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerBlendMode(int64_t display, int64_t layer,
 | |
|                                                      const ParcelableBlendMode& blendMode) {
 | |
|     auto err = mHal->setLayerBlendMode(display, layer, blendMode.blendMode);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerColor(int64_t display, int64_t layer,
 | |
|                                                  const Color& color) {
 | |
|     auto err = mHal->setLayerColor(display, layer, color);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerComposition(int64_t display, int64_t layer,
 | |
|                                                        const ParcelableComposition& composition) {
 | |
|     auto err = mHal->setLayerCompositionType(display, layer, composition.composition);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerDataspace(int64_t display, int64_t layer,
 | |
|                                                      const ParcelableDataspace& dataspace) {
 | |
|     auto err = mHal->setLayerDataspace(display, layer, dataspace.dataspace);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerDisplayFrame(int64_t display, int64_t layer,
 | |
|                                                         const common::Rect& rect) {
 | |
|     auto err = mHal->setLayerDisplayFrame(display, layer, rect);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerPlaneAlpha(int64_t display, int64_t layer,
 | |
|                                                       const PlaneAlpha& planeAlpha) {
 | |
|     auto err = mHal->setLayerPlaneAlpha(display, layer, planeAlpha.alpha);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerSidebandStream(int64_t display, int64_t layer,
 | |
|                                                  const AidlNativeHandle& sidebandStream) {
 | |
|     buffer_handle_t handle = ::android::makeFromAidl(sidebandStream);
 | |
|     buffer_handle_t stream;
 | |
| 
 | |
|     auto bufferReleaser = mResources->createReleaser(false);
 | |
|     auto err = mResources->getLayerSidebandStream(display, layer, handle,
 | |
|                                                   stream, bufferReleaser.get());
 | |
|     if (err) {
 | |
|         err = mHal->setLayerSidebandStream(display, layer, stream);
 | |
|     }
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerSourceCrop(int64_t display, int64_t layer,
 | |
|                                                       const common::FRect& sourceCrop) {
 | |
|     auto err = mHal->setLayerSourceCrop(display, layer, sourceCrop);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerTransform(int64_t display, int64_t layer,
 | |
|                                                      const ParcelableTransform& transform) {
 | |
|     auto err = mHal->setLayerTransform(display, layer, transform.transform);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerVisibleRegion(int64_t display, int64_t layer,
 | |
|                           const std::vector<std::optional<common::Rect>>& visibleRegion) {
 | |
|     auto err = mHal->setLayerVisibleRegion(display, layer, visibleRegion);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerZOrder(int64_t display, int64_t layer,
 | |
|                                                   const ZOrder& zOrder) {
 | |
|     auto err = mHal->setLayerZOrder(display, layer, zOrder.z);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerPerFrameMetadata(int64_t display, int64_t layer,
 | |
|                 const std::vector<std::optional<PerFrameMetadata>>& perFrameMetadata) {
 | |
|     auto err = mHal->setLayerPerFrameMetadata(display, layer, perFrameMetadata);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerColorTransform(int64_t display, int64_t layer,
 | |
|                                                        const std::vector<float>& matrix) {
 | |
|     auto err = mHal->setLayerColorTransform(display, layer, matrix);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerBrightness(int64_t display, int64_t layer,
 | |
|                                                       const LayerBrightness& brightness) {
 | |
|     auto err = mHal->setLayerBrightness(display, layer, brightness.brightness);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ComposerCommandEngine::executeSetLayerPerFrameMetadataBlobs(int64_t display, int64_t layer,
 | |
|                       const std::vector<std::optional<PerFrameMetadataBlob>>& metadata) {
 | |
|     auto err = mHal->setLayerPerFrameMetadataBlobs(display, layer, metadata);
 | |
|     if (err) {
 | |
|         LOG(ERROR) << __func__ << ": err " << err;
 | |
|         mWriter->setError(mCommandIndex, err);
 | |
|     }
 | |
| }
 | |
| 
 | |
| } // namespace aidl::android::hardware::graphics::composer3::impl
 |