blob: 6f087d9e54825d9f822d72376e582957b4f5968e [file] [log] [blame]
Lloyd Pique32cbe282018-10-19 13:09:22 -07001/*
2 * Copyright 2019 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 <cmath>
18
19#include <compositionengine/impl/Output.h>
20#include <compositionengine/mock/CompositionEngine.h>
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070021#include <compositionengine/mock/DisplayColorProfile.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080022#include <compositionengine/mock/Layer.h>
23#include <compositionengine/mock/LayerFE.h>
24#include <compositionengine/mock/OutputLayer.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070025#include <compositionengine/mock/RenderSurface.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070026#include <gtest/gtest.h>
27#include <ui/Rect.h>
28#include <ui/Region.h>
29
30#include "RegionMatcher.h"
31#include "TransformMatcher.h"
32
33namespace android::compositionengine {
34namespace {
35
Lloyd Pique31cb2942018-10-19 17:23:03 -070036using testing::Return;
Lloyd Pique32cbe282018-10-19 13:09:22 -070037using testing::ReturnRef;
38using testing::StrictMock;
39
40class OutputTest : public testing::Test {
41public:
Lloyd Pique31cb2942018-10-19 17:23:03 -070042 OutputTest() {
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070043 mOutput.setDisplayColorProfileForTest(
44 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Pique31cb2942018-10-19 17:23:03 -070045 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -080046
47 mOutput.editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -070048 }
Lloyd Pique32cbe282018-10-19 13:09:22 -070049 ~OutputTest() override = default;
50
Lloyd Piqueef958122019-02-05 18:00:12 -080051 static const Rect kDefaultDisplaySize;
52
Lloyd Pique32cbe282018-10-19 13:09:22 -070053 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070054 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -070055 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique32cbe282018-10-19 13:09:22 -070056 impl::Output mOutput{mCompositionEngine};
57};
58
Lloyd Piqueef958122019-02-05 18:00:12 -080059const Rect OutputTest::kDefaultDisplaySize{100, 200};
60
Lloyd Pique32cbe282018-10-19 13:09:22 -070061/* ------------------------------------------------------------------------
62 * Basic construction
63 */
64
Lloyd Pique31cb2942018-10-19 17:23:03 -070065TEST_F(OutputTest, canInstantiateOutput) {
66 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070067 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -070068 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
69
70 EXPECT_TRUE(mOutput.isValid());
71
72 // If we take away the required components, it is no longer valid.
73 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
74
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070075 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
76
Lloyd Pique31cb2942018-10-19 17:23:03 -070077 EXPECT_FALSE(mOutput.isValid());
78}
Lloyd Pique32cbe282018-10-19 13:09:22 -070079
80/* ------------------------------------------------------------------------
81 * Output::setCompositionEnabled()
82 */
83
84TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Pique32cbe282018-10-19 13:09:22 -070085 mOutput.editState().isEnabled = true;
86
87 mOutput.setCompositionEnabled(true);
88
89 EXPECT_TRUE(mOutput.getState().isEnabled);
90 EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
91}
92
93TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -070094 mOutput.editState().isEnabled = false;
95
96 mOutput.setCompositionEnabled(true);
97
98 EXPECT_TRUE(mOutput.getState().isEnabled);
Lloyd Piqueef958122019-02-05 18:00:12 -080099 EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700100}
101
102TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700103 mOutput.editState().isEnabled = true;
104
105 mOutput.setCompositionEnabled(false);
106
107 EXPECT_FALSE(mOutput.getState().isEnabled);
Lloyd Piqueef958122019-02-05 18:00:12 -0800108 EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700109}
110
111/* ------------------------------------------------------------------------
112 * Output::setProjection()
113 */
114
115TEST_F(OutputTest, setProjectionTriviallyWorks) {
116 const ui::Transform transform{ui::Transform::ROT_180};
117 const int32_t orientation = 123;
118 const Rect frame{1, 2, 3, 4};
119 const Rect viewport{5, 6, 7, 8};
120 const Rect scissor{9, 10, 11, 12};
121 const bool needsFiltering = true;
122
123 mOutput.setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
124
125 EXPECT_THAT(mOutput.getState().transform, TransformEq(transform));
126 EXPECT_EQ(orientation, mOutput.getState().orientation);
127 EXPECT_EQ(frame, mOutput.getState().frame);
128 EXPECT_EQ(viewport, mOutput.getState().viewport);
129 EXPECT_EQ(scissor, mOutput.getState().scissor);
130 EXPECT_EQ(needsFiltering, mOutput.getState().needsFiltering);
131}
132
133/* ------------------------------------------------------------------------
134 * Output::setBounds()
135 */
136
137TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800138 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700139
140 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
141 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
142
Lloyd Pique32cbe282018-10-19 13:09:22 -0700143 mOutput.setBounds(displaySize);
144
Lloyd Pique31cb2942018-10-19 17:23:03 -0700145 EXPECT_EQ(Rect(displaySize), mOutput.getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700146
Lloyd Pique31cb2942018-10-19 17:23:03 -0700147 EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700148}
149
150/* ------------------------------------------------------------------------
151 * Output::setLayerStackFilter()
152 */
153
154TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700155 const uint32_t layerStack = 123u;
Lloyd Piqueef36b002019-01-23 17:52:04 -0800156 mOutput.setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700157
Lloyd Piqueef36b002019-01-23 17:52:04 -0800158 EXPECT_TRUE(mOutput.getState().layerStackInternal);
159 EXPECT_EQ(layerStack, mOutput.getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700160
Lloyd Piqueef958122019-02-05 18:00:12 -0800161 EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700162}
163
164/* ------------------------------------------------------------------------
165 * Output::setColorTransform
166 */
167
168TEST_F(OutputTest, setColorTransformSetsTransform) {
169 // Identity matrix sets an identity state value
170 const mat4 identity;
171
172 mOutput.setColorTransform(identity);
173
174 EXPECT_EQ(HAL_COLOR_TRANSFORM_IDENTITY, mOutput.getState().colorTransform);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700175 EXPECT_EQ(identity, mOutput.getState().colorTransformMat);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700176
Lloyd Piqueef958122019-02-05 18:00:12 -0800177 // Since identity is the default, the dirty region should be unchanged (empty)
178 EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
179
Lloyd Pique32cbe282018-10-19 13:09:22 -0700180 // Non-identity matrix sets a non-identity state value
Lloyd Pique77f79a22019-04-29 15:55:40 -0700181 const mat4 nonIdentityHalf = mat4() * 0.5;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700182
Lloyd Pique77f79a22019-04-29 15:55:40 -0700183 mOutput.setColorTransform(nonIdentityHalf);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700184
185 EXPECT_EQ(HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX, mOutput.getState().colorTransform);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700186 EXPECT_EQ(nonIdentityHalf, mOutput.getState().colorTransformMat);
187
188 // Since this is a state change, the entire output should now be dirty.
189 EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
190
191 // Non-identity matrix sets a non-identity state value
192 const mat4 nonIdentityQuarter = mat4() * 0.25;
193
194 mOutput.setColorTransform(nonIdentityQuarter);
195
196 EXPECT_EQ(HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX, mOutput.getState().colorTransform);
197 EXPECT_EQ(nonIdentityQuarter, mOutput.getState().colorTransformMat);
Lloyd Piqueef958122019-02-05 18:00:12 -0800198
199 // Since this is a state change, the entire output should now be dirty.
200 EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700201}
202
203/* ------------------------------------------------------------------------
204 * Output::setColorMode
205 */
206
Lloyd Piqueef958122019-02-05 18:00:12 -0800207TEST_F(OutputTest, setColorModeSetsStateAndDirtiesOutputIfChanged) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800208 EXPECT_CALL(*mDisplayColorProfile,
209 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
210 ui::Dataspace::UNKNOWN))
211 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800212 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700213
Lloyd Piqueef958122019-02-05 18:00:12 -0800214 mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
Lloyd Piquef5275482019-01-29 18:42:42 -0800215 ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700216
Lloyd Piqueef958122019-02-05 18:00:12 -0800217 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput.getState().colorMode);
218 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput.getState().dataspace);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700219 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput.getState().renderIntent);
Lloyd Piquef5275482019-01-29 18:42:42 -0800220 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput.getState().targetDataspace);
221
Lloyd Piqueef958122019-02-05 18:00:12 -0800222 EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
223}
224
225TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) {
Lloyd Piquef5275482019-01-29 18:42:42 -0800226 EXPECT_CALL(*mDisplayColorProfile,
227 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
228 ui::Dataspace::UNKNOWN))
229 .WillOnce(Return(ui::Dataspace::UNKNOWN));
230
Lloyd Piqueef958122019-02-05 18:00:12 -0800231 mOutput.editState().colorMode = ui::ColorMode::DISPLAY_P3;
232 mOutput.editState().dataspace = ui::Dataspace::DISPLAY_P3;
233 mOutput.editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
Lloyd Piquef5275482019-01-29 18:42:42 -0800234 mOutput.editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800235
236 mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
Lloyd Piquef5275482019-01-29 18:42:42 -0800237 ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN);
Lloyd Piqueef958122019-02-05 18:00:12 -0800238
239 EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700240}
241
242/* ------------------------------------------------------------------------
Lloyd Pique31cb2942018-10-19 17:23:03 -0700243 * Output::setRenderSurface()
244 */
245
246TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
247 const ui::Size newDisplaySize{640, 480};
248
249 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
250 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
251
252 mOutput.setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
253
254 EXPECT_EQ(Rect(newDisplaySize), mOutput.getState().bounds);
255}
256
257/* ------------------------------------------------------------------------
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000258 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700259 */
260
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000261TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
262 const Rect viewport{100, 200};
263 mOutput.editState().viewport = viewport;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700264 mOutput.editState().dirtyRegion.set(50, 300);
265
266 {
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000267 Region result = mOutput.getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700268
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000269 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700270 }
271}
272
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000273TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
274 const Rect viewport{100, 200};
275 mOutput.editState().viewport = viewport;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700276 mOutput.editState().dirtyRegion.set(50, 300);
277
278 {
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000279 Region result = mOutput.getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700280
281 // The dirtyRegion should be clipped to the display bounds.
282 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
283 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700284}
285
Lloyd Piqueef36b002019-01-23 17:52:04 -0800286/* ------------------------------------------------------------------------
287 * Output::belongsInOutput()
288 */
289
290TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
291 const uint32_t layerStack1 = 123u;
292 const uint32_t layerStack2 = 456u;
293
294 // If the output accepts layerStack1 and internal-only layers....
295 mOutput.setLayerStackFilter(layerStack1, true);
296
297 // Any layer with layerStack1 belongs to it, internal-only or not.
298 EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, false));
299 EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, true));
300 EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, true));
301 EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, false));
302
303 // If the output accepts layerStack21 but not internal-only layers...
304 mOutput.setLayerStackFilter(layerStack1, false);
305
306 // Only non-internal layers with layerStack1 belong to it.
307 EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, false));
308 EXPECT_FALSE(mOutput.belongsInOutput(layerStack1, true));
309 EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, true));
310 EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, false));
311}
312
Lloyd Piquecc01a452018-12-04 17:24:00 -0800313/* ------------------------------------------------------------------------
314 * Output::getOutputLayerForLayer()
315 */
316
317TEST_F(OutputTest, getOutputLayerForLayerWorks) {
318 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
319 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
320
321 Output::OutputLayers outputLayers;
322 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer1));
323 outputLayers.emplace_back(nullptr);
324 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer2));
325 mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
326
327 StrictMock<mock::Layer> layer;
328 StrictMock<mock::Layer> otherLayer;
329
330 // If the input layer matches the first OutputLayer, it will be returned.
331 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
332 EXPECT_EQ(outputLayer1, mOutput.getOutputLayerForLayer(&layer));
333
334 // If the input layer matches the second OutputLayer, it will be returned.
335 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
336 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
337 EXPECT_EQ(outputLayer2, mOutput.getOutputLayerForLayer(&layer));
338
339 // If the input layer does not match an output layer, null will be returned.
340 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
341 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
342 EXPECT_EQ(nullptr, mOutput.getOutputLayerForLayer(&layer));
343}
344
345/* ------------------------------------------------------------------------
346 * Output::getOrCreateOutputLayer()
347 */
348
349TEST_F(OutputTest, getOrCreateOutputLayerWorks) {
350 mock::OutputLayer* existingOutputLayer = new StrictMock<mock::OutputLayer>();
351
352 Output::OutputLayers outputLayers;
353 outputLayers.emplace_back(nullptr);
354 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(existingOutputLayer));
355 mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
356
357 std::shared_ptr<mock::Layer> layer{new StrictMock<mock::Layer>()};
358 sp<LayerFE> layerFE{new StrictMock<mock::LayerFE>()};
359
360 StrictMock<mock::Layer> otherLayer;
361
362 {
363 // If there is no OutputLayer corresponding to the input layer, a
364 // new OutputLayer is constructed and returned.
365 EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Pique07e33212018-12-18 16:33:37 -0800366 auto result = mOutput.getOrCreateOutputLayer(std::nullopt, layer, layerFE);
Lloyd Piquecc01a452018-12-04 17:24:00 -0800367 EXPECT_NE(existingOutputLayer, result.get());
368 EXPECT_TRUE(result.get() != nullptr);
369 EXPECT_EQ(layer.get(), &result->getLayer());
370 EXPECT_EQ(layerFE.get(), &result->getLayerFE());
371
372 // The entries in the ordered array should be unchanged.
373 auto& outputLayers = mOutput.getOutputLayersOrderedByZ();
374 EXPECT_EQ(nullptr, outputLayers[0].get());
375 EXPECT_EQ(existingOutputLayer, outputLayers[1].get());
376 }
377
378 {
379 // If there is an existing OutputLayer for the requested layer, an owned
380 // pointer is returned
381 EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(*layer));
Lloyd Pique07e33212018-12-18 16:33:37 -0800382 auto result = mOutput.getOrCreateOutputLayer(std::nullopt, layer, layerFE);
Lloyd Piquecc01a452018-12-04 17:24:00 -0800383 EXPECT_EQ(existingOutputLayer, result.get());
384
385 // The corresponding entry in the ordered array should be cleared.
386 auto& outputLayers = mOutput.getOutputLayersOrderedByZ();
387 EXPECT_EQ(nullptr, outputLayers[0].get());
388 EXPECT_EQ(nullptr, outputLayers[1].get());
389 }
390}
391
Lloyd Pique32cbe282018-10-19 13:09:22 -0700392} // namespace
393} // namespace android::compositionengine