• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "ComposerCommandEngine.h"
18 
19 #include <hardware/hwcomposer2.h>
20 
21 #include <set>
22 
23 #include "Util.h"
24 
25 namespace aidl::android::hardware::graphics::composer3::impl {
26 
27 #define DISPATCH_LAYER_COMMAND(display, layerCmd, field, funcName)               \
28     do {                                                                         \
29         if (layerCmd.field) {                                                    \
30             executeSetLayer##funcName(display, layerCmd.layer, *layerCmd.field); \
31         }                                                                        \
32     } while (0)
33 
34 #define DISPATCH_LAYER_COMMAND_SIMPLE(display, layerCmd, field, funcName)     \
35     do {                                                                      \
36         dispatchLayerCommand(display, layerCmd.layer, #field, layerCmd.field, \
37                              &IComposerHal::setLayer##funcName);              \
38     } while (0)
39 
40 #define DISPATCH_DISPLAY_COMMAND(displayCmd, field, funcName)                \
41     do {                                                                     \
42         if (displayCmd.field) {                                              \
43             execute##funcName(displayCmd.display, *displayCmd.field);        \
44         }                                                                    \
45     } while (0)
46 
47 #define DISPATCH_DISPLAY_BOOL_COMMAND(displayCmd, field, funcName)           \
48     do {                                                                     \
49         if (displayCmd.field) {                                              \
50             execute##funcName(displayCmd.display);                           \
51         }                                                                    \
52     } while (0)
53 
54 #define DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCmd, field, data, funcName) \
55     do {                                                                          \
56         if (displayCmd.field) {                                                   \
57             execute##funcName(displayCmd.display, displayCmd.data);               \
58         }                                                                         \
59     } while (0)
60 
init()61 int32_t ComposerCommandEngine::init() {
62     mWriter = std::make_unique<ComposerServiceWriter>();
63     return (mWriter != nullptr) ? ::android::NO_ERROR : ::android::NO_MEMORY;
64 }
65 
execute(const std::vector<DisplayCommand> & commands,std::vector<CommandResultPayload> * result)66 int32_t ComposerCommandEngine::execute(const std::vector<DisplayCommand>& commands,
67                                        std::vector<CommandResultPayload>* result) {
68     std::set<int64_t> displaysPendingBrightenssChange;
69     mCommandIndex = 0;
70     for (const auto& command : commands) {
71         dispatchDisplayCommand(command);
72         ++mCommandIndex;
73         // The input commands could have 2+ commands for the same display.
74         // If the first has pending brightness change, the second presentDisplay will apply it.
75         if (command.validateDisplay || command.presentDisplay ||
76             command.presentOrValidateDisplay) {
77             displaysPendingBrightenssChange.erase(command.display);
78         } else if (command.brightness) {
79             displaysPendingBrightenssChange.insert(command.display);
80         }
81     }
82 
83     *result = mWriter->getPendingCommandResults();
84     mWriter->reset();
85 
86     // standalone display brightness command shouldn't wait for next present or validate
87     for (auto display : displaysPendingBrightenssChange) {
88         auto err = mHal->flushDisplayBrightnessChange(display);
89         if (err) {
90             return err;
91         }
92     }
93     return ::android::NO_ERROR;
94 }
95 
dispatchDisplayCommand(const DisplayCommand & command)96 void ComposerCommandEngine::dispatchDisplayCommand(const DisplayCommand& command) {
97     //  place SetDisplayBrightness before SetLayerWhitePointNits since current
98     //  display brightness is used to validate the layer white point nits.
99     DISPATCH_DISPLAY_COMMAND(command, brightness, SetDisplayBrightness);
100     for (const auto& layerCmd : command.layers) {
101         dispatchLayerCommand(command.display, layerCmd);
102     }
103 
104     DISPATCH_DISPLAY_COMMAND(command, colorTransformMatrix, SetColorTransform);
105     DISPATCH_DISPLAY_COMMAND(command, clientTarget, SetClientTarget);
106     DISPATCH_DISPLAY_COMMAND(command, virtualDisplayOutputBuffer, SetOutputBuffer);
107     DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(command, validateDisplay, expectedPresentTime,
108                                            ValidateDisplay);
109     DISPATCH_DISPLAY_BOOL_COMMAND(command, acceptDisplayChanges, AcceptDisplayChanges);
110     DISPATCH_DISPLAY_BOOL_COMMAND(command, presentDisplay, PresentDisplay);
111     DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(command, presentOrValidateDisplay, expectedPresentTime,
112                                            PresentOrValidateDisplay);
113 }
114 
dispatchLayerCommand(int64_t display,const LayerCommand & command)115 void ComposerCommandEngine::dispatchLayerCommand(int64_t display, const LayerCommand& command) {
116     DISPATCH_LAYER_COMMAND(display, command, cursorPosition, CursorPosition);
117     DISPATCH_LAYER_COMMAND(display, command, buffer, Buffer);
118     DISPATCH_LAYER_COMMAND(display, command, damage, SurfaceDamage);
119     DISPATCH_LAYER_COMMAND(display, command, blendMode, BlendMode);
120     DISPATCH_LAYER_COMMAND(display, command, color, Color);
121     DISPATCH_LAYER_COMMAND(display, command, composition, Composition);
122     DISPATCH_LAYER_COMMAND(display, command, dataspace, Dataspace);
123     DISPATCH_LAYER_COMMAND(display, command, displayFrame, DisplayFrame);
124     DISPATCH_LAYER_COMMAND(display, command, planeAlpha, PlaneAlpha);
125     DISPATCH_LAYER_COMMAND(display, command, sidebandStream, SidebandStream);
126     DISPATCH_LAYER_COMMAND(display, command, sourceCrop, SourceCrop);
127     DISPATCH_LAYER_COMMAND(display, command, transform, Transform);
128     DISPATCH_LAYER_COMMAND(display, command, visibleRegion, VisibleRegion);
129     DISPATCH_LAYER_COMMAND(display, command, z, ZOrder);
130     DISPATCH_LAYER_COMMAND(display, command, colorTransform, ColorTransform);
131     DISPATCH_LAYER_COMMAND(display, command, brightness, Brightness);
132     DISPATCH_LAYER_COMMAND(display, command, perFrameMetadata, PerFrameMetadata);
133     DISPATCH_LAYER_COMMAND(display, command, perFrameMetadataBlob, PerFrameMetadataBlobs);
134     DISPATCH_LAYER_COMMAND_SIMPLE(display, command, blockingRegion, BlockingRegion);
135 }
136 
executeValidateDisplayInternal(int64_t display)137 int32_t ComposerCommandEngine::executeValidateDisplayInternal(int64_t display) {
138     std::vector<int64_t> changedLayers;
139     std::vector<Composition> compositionTypes;
140     uint32_t displayRequestMask = 0x0;
141     std::vector<int64_t> requestedLayers;
142     std::vector<int32_t> requestMasks;
143     ClientTargetProperty clientTargetProperty{common::PixelFormat::RGBA_8888,
144                                               common::Dataspace::UNKNOWN};
145     DimmingStage dimmingStage;
146     auto err =
147             mHal->validateDisplay(display, &changedLayers, &compositionTypes, &displayRequestMask,
148                                   &requestedLayers, &requestMasks, &clientTargetProperty,
149                                   &dimmingStage);
150     mResources->setDisplayMustValidateState(display, false);
151     if (err == HWC2_ERROR_NONE || err == HWC2_ERROR_HAS_CHANGES) {
152         mWriter->setChangedCompositionTypes(display, changedLayers, compositionTypes);
153         mWriter->setDisplayRequests(display, displayRequestMask, requestedLayers, requestMasks);
154         static constexpr float kBrightness = 1.f;
155         mWriter->setClientTargetProperty(display, clientTargetProperty, kBrightness, dimmingStage);
156     } else {
157         LOG(ERROR) << __func__ << ": err " << err;
158         mWriter->setError(mCommandIndex, err);
159     }
160     return err;
161 }
162 
executeSetColorTransform(int64_t display,const std::vector<float> & matrix)163 void ComposerCommandEngine::executeSetColorTransform(int64_t display,
164                                                      const std::vector<float>& matrix) {
165     auto err = mHal->setColorTransform(display, matrix);
166     if (err) {
167         LOG(ERROR) << __func__ << ": err " << err;
168         mWriter->setError(mCommandIndex, err);
169     }
170 }
171 
executeSetClientTarget(int64_t display,const ClientTarget & command)172 void ComposerCommandEngine::executeSetClientTarget(int64_t display, const ClientTarget& command) {
173     bool useCache = !command.buffer.handle;
174     buffer_handle_t handle = useCache
175                              ? nullptr
176                              : ::android::makeFromAidl(*command.buffer.handle);
177     buffer_handle_t clientTarget;
178     auto bufferReleaser = mResources->createReleaser(true);
179     auto err = mResources->getDisplayClientTarget(display, command.buffer.slot, useCache, handle,
180                                                   clientTarget, bufferReleaser.get());
181     if (!err) {
182         err = mHal->setClientTarget(display, clientTarget, command.buffer.fence,
183                                     command.dataspace, command.damage);
184         if (err) {
185             LOG(ERROR) << __func__ << " setClientTarget: err " << err;
186             mWriter->setError(mCommandIndex, err);
187         }
188     } else {
189         LOG(ERROR) << __func__ << " getDisplayClientTarget : err " << err;
190         mWriter->setError(mCommandIndex, err);
191     }
192 }
193 
executeSetOutputBuffer(uint64_t display,const Buffer & buffer)194 void ComposerCommandEngine::executeSetOutputBuffer(uint64_t display, const Buffer& buffer) {
195     bool useCache = !buffer.handle;
196     buffer_handle_t handle = useCache
197                              ? nullptr
198                              : ::android::makeFromAidl(*buffer.handle);
199     buffer_handle_t outputBuffer;
200     auto bufferReleaser = mResources->createReleaser(true);
201     auto err = mResources->getDisplayOutputBuffer(display, buffer.slot, useCache, handle,
202                                                   outputBuffer, bufferReleaser.get());
203     if (!err) {
204         err = mHal->setOutputBuffer(display, outputBuffer, buffer.fence);
205         if (err) {
206             LOG(ERROR) << __func__ << " setOutputBuffer: err " << err;
207             mWriter->setError(mCommandIndex, err);
208         }
209     } else {
210         LOG(ERROR) << __func__ << " getDisplayOutputBuffer: err " << err;
211         mWriter->setError(mCommandIndex, err);
212     }
213 }
214 
executeSetExpectedPresentTimeInternal(int64_t display,const std::optional<ClockMonotonicTimestamp> expectedPresentTime)215 void ComposerCommandEngine::executeSetExpectedPresentTimeInternal(
216         int64_t display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
217     mHal->setExpectedPresentTime(display, expectedPresentTime);
218 }
219 
executeValidateDisplay(int64_t display,const std::optional<ClockMonotonicTimestamp> expectedPresentTime)220 void ComposerCommandEngine::executeValidateDisplay(
221         int64_t display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
222     executeSetExpectedPresentTimeInternal(display, expectedPresentTime);
223     executeValidateDisplayInternal(display);
224 }
225 
executeSetDisplayBrightness(uint64_t display,const DisplayBrightness & command)226 void ComposerCommandEngine::executeSetDisplayBrightness(uint64_t display,
227                                         const DisplayBrightness& command) {
228     auto err = mHal->setDisplayBrightness(display, command.brightness);
229     if (err) {
230         LOG(ERROR) << __func__ << ": err " << err;
231         mWriter->setError(mCommandIndex, err);
232     }
233 }
234 
executePresentOrValidateDisplay(int64_t display,const std::optional<ClockMonotonicTimestamp> expectedPresentTime)235 void ComposerCommandEngine::executePresentOrValidateDisplay(
236         int64_t display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
237     executeSetExpectedPresentTimeInternal(display, expectedPresentTime);
238     // First try to Present as is.
239     auto presentErr = mResources->mustValidateDisplay(display) ? IComposerClient::EX_NOT_VALIDATED
240                                                                : executePresentDisplay(display);
241     if (!presentErr) {
242         mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Presented);
243         return;
244     }
245 
246     // Fallback to validate
247     auto validateErr = executeValidateDisplayInternal(display);
248     if (validateErr != HWC2_ERROR_NONE && validateErr != HWC2_ERROR_HAS_CHANGES) return;
249 
250     bool hasClientComp = false;
251     bool cannotPresentDirectly = (validateErr == HWC2_ERROR_HAS_CHANGES) ||
252             (mHal->getHasClientComposition(display, hasClientComp) == HWC2_ERROR_NONE &&
253              hasClientComp);
254     if (cannotPresentDirectly) {
255         mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Validated);
256         return;
257     }
258 
259     // Try to call present again
260     executeAcceptDisplayChanges(display);
261     presentErr = executePresentDisplay(display);
262     if (!presentErr) {
263         mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Presented);
264     }
265 }
266 
executeAcceptDisplayChanges(int64_t display)267 void ComposerCommandEngine::executeAcceptDisplayChanges(int64_t display) {
268     auto err = mHal->acceptDisplayChanges(display);
269     if (err) {
270         LOG(ERROR) << __func__ << ": err " << err;
271         mWriter->setError(mCommandIndex, err);
272     }
273 }
274 
executePresentDisplay(int64_t display)275 int ComposerCommandEngine::executePresentDisplay(int64_t display) {
276     ndk::ScopedFileDescriptor presentFence;
277     std::vector<int64_t> layers;
278     std::vector<ndk::ScopedFileDescriptor> fences;
279     auto err = mHal->presentDisplay(display, presentFence, &layers, &fences);
280     if (!err) {
281         mWriter->setPresentFence(display, std::move(presentFence));
282         mWriter->setReleaseFences(display, layers, std::move(fences));
283     }
284 
285     return err;
286 }
287 
executeSetLayerCursorPosition(int64_t display,int64_t layer,const common::Point & cursorPosition)288 void ComposerCommandEngine::executeSetLayerCursorPosition(int64_t display, int64_t layer,
289                                        const common::Point& cursorPosition) {
290     auto err = mHal->setLayerCursorPosition(display, layer, cursorPosition.x, cursorPosition.y);
291     if (err) {
292         LOG(ERROR) << __func__ << ": err " << err;
293         mWriter->setError(mCommandIndex, err);
294     }
295 }
296 
executeSetLayerBuffer(int64_t display,int64_t layer,const Buffer & buffer)297 void ComposerCommandEngine::executeSetLayerBuffer(int64_t display, int64_t layer,
298                                                   const Buffer& buffer) {
299     bool useCache = !buffer.handle;
300     buffer_handle_t handle = useCache
301                              ? nullptr
302                              : ::android::makeFromAidl(*buffer.handle);
303     buffer_handle_t hwcBuffer;
304     auto bufferReleaser = mResources->createReleaser(true);
305     auto err = mResources->getLayerBuffer(display, layer, buffer.slot, useCache,
306                                           handle, hwcBuffer, bufferReleaser.get());
307     if (!err) {
308         err = mHal->setLayerBuffer(display, layer, hwcBuffer, buffer.fence);
309         if (err) {
310             LOG(ERROR) << __func__ << ": setLayerBuffer err " << err;
311             mWriter->setError(mCommandIndex, err);
312         }
313     } else {
314         LOG(ERROR) << __func__ << ": getLayerBuffer err " << err;
315         mWriter->setError(mCommandIndex, err);
316     }
317 }
318 
executeSetLayerSurfaceDamage(int64_t display,int64_t layer,const std::vector<std::optional<common::Rect>> & damage)319 void ComposerCommandEngine::executeSetLayerSurfaceDamage(int64_t display, int64_t layer,
320                               const std::vector<std::optional<common::Rect>>& damage) {
321     auto err = mHal->setLayerSurfaceDamage(display, layer, damage);
322     if (err) {
323         LOG(ERROR) << __func__ << ": err " << err;
324         mWriter->setError(mCommandIndex, err);
325     }
326 }
327 
executeSetLayerBlendMode(int64_t display,int64_t layer,const ParcelableBlendMode & blendMode)328 void ComposerCommandEngine::executeSetLayerBlendMode(int64_t display, int64_t layer,
329                                                      const ParcelableBlendMode& blendMode) {
330     auto err = mHal->setLayerBlendMode(display, layer, blendMode.blendMode);
331     if (err) {
332         LOG(ERROR) << __func__ << ": err " << err;
333         mWriter->setError(mCommandIndex, err);
334     }
335 }
336 
executeSetLayerColor(int64_t display,int64_t layer,const Color & color)337 void ComposerCommandEngine::executeSetLayerColor(int64_t display, int64_t layer,
338                                                  const Color& color) {
339     auto err = mHal->setLayerColor(display, layer, color);
340     if (err) {
341         LOG(ERROR) << __func__ << ": err " << err;
342         mWriter->setError(mCommandIndex, err);
343     }
344 }
345 
executeSetLayerComposition(int64_t display,int64_t layer,const ParcelableComposition & composition)346 void ComposerCommandEngine::executeSetLayerComposition(int64_t display, int64_t layer,
347                                                        const ParcelableComposition& composition) {
348     auto err = mHal->setLayerCompositionType(display, layer, composition.composition);
349     if (err) {
350         LOG(ERROR) << __func__ << ": err " << err;
351         mWriter->setError(mCommandIndex, err);
352     }
353 }
354 
executeSetLayerDataspace(int64_t display,int64_t layer,const ParcelableDataspace & dataspace)355 void ComposerCommandEngine::executeSetLayerDataspace(int64_t display, int64_t layer,
356                                                      const ParcelableDataspace& dataspace) {
357     auto err = mHal->setLayerDataspace(display, layer, dataspace.dataspace);
358     if (err) {
359         LOG(ERROR) << __func__ << ": err " << err;
360         mWriter->setError(mCommandIndex, err);
361     }
362 }
363 
executeSetLayerDisplayFrame(int64_t display,int64_t layer,const common::Rect & rect)364 void ComposerCommandEngine::executeSetLayerDisplayFrame(int64_t display, int64_t layer,
365                                                         const common::Rect& rect) {
366     auto err = mHal->setLayerDisplayFrame(display, layer, rect);
367     if (err) {
368         LOG(ERROR) << __func__ << ": err " << err;
369         mWriter->setError(mCommandIndex, err);
370     }
371 }
372 
executeSetLayerPlaneAlpha(int64_t display,int64_t layer,const PlaneAlpha & planeAlpha)373 void ComposerCommandEngine::executeSetLayerPlaneAlpha(int64_t display, int64_t layer,
374                                                       const PlaneAlpha& planeAlpha) {
375     auto err = mHal->setLayerPlaneAlpha(display, layer, planeAlpha.alpha);
376     if (err) {
377         LOG(ERROR) << __func__ << ": err " << err;
378         mWriter->setError(mCommandIndex, err);
379     }
380 }
381 
executeSetLayerSidebandStream(int64_t display,int64_t layer,const AidlNativeHandle & sidebandStream)382 void ComposerCommandEngine::executeSetLayerSidebandStream(int64_t display, int64_t layer,
383                                                  const AidlNativeHandle& sidebandStream) {
384     buffer_handle_t handle = ::android::makeFromAidl(sidebandStream);
385     buffer_handle_t stream;
386 
387     auto bufferReleaser = mResources->createReleaser(false);
388     auto err = mResources->getLayerSidebandStream(display, layer, handle,
389                                                   stream, bufferReleaser.get());
390     if (err) {
391         err = mHal->setLayerSidebandStream(display, layer, stream);
392     }
393     if (err) {
394         LOG(ERROR) << __func__ << ": err " << err;
395         mWriter->setError(mCommandIndex, err);
396     }
397 }
398 
executeSetLayerSourceCrop(int64_t display,int64_t layer,const common::FRect & sourceCrop)399 void ComposerCommandEngine::executeSetLayerSourceCrop(int64_t display, int64_t layer,
400                                                       const common::FRect& sourceCrop) {
401     auto err = mHal->setLayerSourceCrop(display, layer, sourceCrop);
402     if (err) {
403         LOG(ERROR) << __func__ << ": err " << err;
404         mWriter->setError(mCommandIndex, err);
405     }
406 }
407 
executeSetLayerTransform(int64_t display,int64_t layer,const ParcelableTransform & transform)408 void ComposerCommandEngine::executeSetLayerTransform(int64_t display, int64_t layer,
409                                                      const ParcelableTransform& transform) {
410     auto err = mHal->setLayerTransform(display, layer, transform.transform);
411     if (err) {
412         LOG(ERROR) << __func__ << ": err " << err;
413         mWriter->setError(mCommandIndex, err);
414     }
415 }
416 
executeSetLayerVisibleRegion(int64_t display,int64_t layer,const std::vector<std::optional<common::Rect>> & visibleRegion)417 void ComposerCommandEngine::executeSetLayerVisibleRegion(int64_t display, int64_t layer,
418                           const std::vector<std::optional<common::Rect>>& visibleRegion) {
419     auto err = mHal->setLayerVisibleRegion(display, layer, visibleRegion);
420     if (err) {
421         LOG(ERROR) << __func__ << ": err " << err;
422         mWriter->setError(mCommandIndex, err);
423     }
424 }
425 
executeSetLayerZOrder(int64_t display,int64_t layer,const ZOrder & zOrder)426 void ComposerCommandEngine::executeSetLayerZOrder(int64_t display, int64_t layer,
427                                                   const ZOrder& zOrder) {
428     auto err = mHal->setLayerZOrder(display, layer, zOrder.z);
429     if (err) {
430         LOG(ERROR) << __func__ << ": err " << err;
431         mWriter->setError(mCommandIndex, err);
432     }
433 }
434 
executeSetLayerPerFrameMetadata(int64_t display,int64_t layer,const std::vector<std::optional<PerFrameMetadata>> & perFrameMetadata)435 void ComposerCommandEngine::executeSetLayerPerFrameMetadata(int64_t display, int64_t layer,
436                 const std::vector<std::optional<PerFrameMetadata>>& perFrameMetadata) {
437     auto err = mHal->setLayerPerFrameMetadata(display, layer, perFrameMetadata);
438     if (err) {
439         LOG(ERROR) << __func__ << ": err " << err;
440         mWriter->setError(mCommandIndex, err);
441     }
442 }
443 
executeSetLayerColorTransform(int64_t display,int64_t layer,const std::vector<float> & matrix)444 void ComposerCommandEngine::executeSetLayerColorTransform(int64_t display, int64_t layer,
445                                                        const std::vector<float>& matrix) {
446     auto err = mHal->setLayerColorTransform(display, layer, matrix);
447     if (err) {
448         LOG(ERROR) << __func__ << ": err " << err;
449         mWriter->setError(mCommandIndex, err);
450     }
451 }
452 
executeSetLayerBrightness(int64_t display,int64_t layer,const LayerBrightness & brightness)453 void ComposerCommandEngine::executeSetLayerBrightness(int64_t display, int64_t layer,
454                                                       const LayerBrightness& brightness) {
455     auto err = mHal->setLayerBrightness(display, layer, brightness.brightness);
456     if (err) {
457         LOG(ERROR) << __func__ << ": err " << err;
458         mWriter->setError(mCommandIndex, err);
459     }
460 }
461 
executeSetLayerPerFrameMetadataBlobs(int64_t display,int64_t layer,const std::vector<std::optional<PerFrameMetadataBlob>> & metadata)462 void ComposerCommandEngine::executeSetLayerPerFrameMetadataBlobs(int64_t display, int64_t layer,
463                       const std::vector<std::optional<PerFrameMetadataBlob>>& metadata) {
464     auto err = mHal->setLayerPerFrameMetadataBlobs(display, layer, metadata);
465     if (err) {
466         LOG(ERROR) << __func__ << ": err " << err;
467         mWriter->setError(mCommandIndex, err);
468     }
469 }
470 
471 } // namespace aidl::android::hardware::graphics::composer3::impl
472