1 /*
2 * Copyright (C) 2017 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 <composer-vts/2.1/ComposerVts.h>
18
19 #include <VtsHalHidlTargetTestBase.h>
20
21 namespace android {
22 namespace hardware {
23 namespace graphics {
24 namespace composer {
25 namespace V2_1 {
26 namespace vts {
27
Composer()28 Composer::Composer() : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>()) {}
29
Composer(const std::string & name)30 Composer::Composer(const std::string& name)
31 : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name)) {}
32
Composer(const sp<IComposer> & composer)33 Composer::Composer(const sp<IComposer>& composer) : mComposer(composer) {
34 // ASSERT_* can only be used in functions returning void.
35 [this] {
36 ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
37
38 std::vector<IComposer::Capability> capabilities = getCapabilities();
39 mCapabilities.insert(capabilities.begin(), capabilities.end());
40 }();
41 }
42
getRaw() const43 sp<IComposer> Composer::getRaw() const {
44 return mComposer;
45 }
46
hasCapability(IComposer::Capability capability) const47 bool Composer::hasCapability(IComposer::Capability capability) const {
48 return mCapabilities.count(capability) > 0;
49 }
50
getCapabilities()51 std::vector<IComposer::Capability> Composer::getCapabilities() {
52 std::vector<IComposer::Capability> capabilities;
53 mComposer->getCapabilities(
54 [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
55
56 return capabilities;
57 }
58
dumpDebugInfo()59 std::string Composer::dumpDebugInfo() {
60 std::string debugInfo;
61 mComposer->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
62
63 return debugInfo;
64 }
65
createClient()66 std::unique_ptr<ComposerClient> Composer::createClient() {
67 std::unique_ptr<ComposerClient> client;
68 mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
69 ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
70 client = std::make_unique<ComposerClient>(tmpClient);
71 });
72
73 return client;
74 }
75
ComposerClient(const sp<IComposerClient> & client)76 ComposerClient::ComposerClient(const sp<IComposerClient>& client) : mClient(client) {}
77
~ComposerClient()78 ComposerClient::~ComposerClient() {
79 for (const auto& it : mDisplayResources) {
80 Display display = it.first;
81 const DisplayResource& resource = it.second;
82
83 for (auto layer : resource.layers) {
84 EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer))
85 << "failed to destroy layer " << layer;
86 }
87
88 if (resource.isVirtual) {
89 EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display))
90 << "failed to destroy virtual display " << display;
91 }
92 }
93 mDisplayResources.clear();
94 }
95
getRaw() const96 sp<IComposerClient> ComposerClient::getRaw() const {
97 return mClient;
98 }
99
registerCallback(const sp<IComposerCallback> & callback)100 void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) {
101 mClient->registerCallback(callback);
102 }
103
getMaxVirtualDisplayCount()104 uint32_t ComposerClient::getMaxVirtualDisplayCount() {
105 return mClient->getMaxVirtualDisplayCount();
106 }
107
createVirtualDisplay(uint32_t width,uint32_t height,PixelFormat formatHint,uint32_t outputBufferSlotCount,PixelFormat * outFormat)108 Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
109 PixelFormat formatHint, uint32_t outputBufferSlotCount,
110 PixelFormat* outFormat) {
111 Display display = 0;
112 mClient->createVirtualDisplay(
113 width, height, formatHint, outputBufferSlotCount,
114 [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
115 ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
116 display = tmpDisplay;
117 *outFormat = tmpFormat;
118
119 ASSERT_TRUE(mDisplayResources.insert({display, DisplayResource(true)}).second)
120 << "duplicated virtual display id " << display;
121 });
122
123 return display;
124 }
125
destroyVirtualDisplay(Display display)126 void ComposerClient::destroyVirtualDisplay(Display display) {
127 Error error = mClient->destroyVirtualDisplay(display);
128 ASSERT_EQ(Error::NONE, error) << "failed to destroy virtual display " << display;
129
130 mDisplayResources.erase(display);
131 }
132
createLayer(Display display,uint32_t bufferSlotCount)133 Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) {
134 Layer layer = 0;
135 mClient->createLayer(display, bufferSlotCount, [&](const auto& tmpError, const auto& tmpLayer) {
136 ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer";
137 layer = tmpLayer;
138
139 auto resourceIt = mDisplayResources.find(display);
140 if (resourceIt == mDisplayResources.end()) {
141 resourceIt = mDisplayResources.insert({display, DisplayResource(false)}).first;
142 }
143
144 ASSERT_TRUE(resourceIt->second.layers.insert(layer).second)
145 << "duplicated layer id " << layer;
146 });
147
148 return layer;
149 }
150
destroyLayer(Display display,Layer layer)151 void ComposerClient::destroyLayer(Display display, Layer layer) {
152 Error error = mClient->destroyLayer(display, layer);
153 ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer;
154
155 auto resourceIt = mDisplayResources.find(display);
156 ASSERT_NE(mDisplayResources.end(), resourceIt);
157 resourceIt->second.layers.erase(layer);
158 }
159
getActiveConfig(Display display)160 Config ComposerClient::getActiveConfig(Display display) {
161 Config config = 0;
162 mClient->getActiveConfig(display, [&](const auto& tmpError, const auto& tmpConfig) {
163 ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config";
164 config = tmpConfig;
165 });
166
167 return config;
168 }
169
getClientTargetSupport(Display display,uint32_t width,uint32_t height,PixelFormat format,Dataspace dataspace)170 bool ComposerClient::getClientTargetSupport(Display display, uint32_t width, uint32_t height,
171 PixelFormat format, Dataspace dataspace) {
172 Error error = mClient->getClientTargetSupport(display, width, height, format, dataspace);
173 return error == Error::NONE;
174 }
175
getColorModes(Display display)176 std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
177 std::vector<ColorMode> modes;
178 mClient->getColorModes(display, [&](const auto& tmpError, const auto& tmpMode) {
179 ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode";
180 modes = tmpMode;
181 });
182
183 return modes;
184 }
185
getDisplayAttribute(Display display,Config config,IComposerClient::Attribute attribute)186 int32_t ComposerClient::getDisplayAttribute(Display display, Config config,
187 IComposerClient::Attribute attribute) {
188 int32_t value = 0;
189 mClient->getDisplayAttribute(
190 display, config, attribute, [&](const auto& tmpError, const auto& tmpValue) {
191 ASSERT_EQ(Error::NONE, tmpError) << "failed to get display attribute";
192 value = tmpValue;
193 });
194
195 return value;
196 }
197
getDisplayConfigs(Display display)198 std::vector<Config> ComposerClient::getDisplayConfigs(Display display) {
199 std::vector<Config> configs;
200 mClient->getDisplayConfigs(display, [&](const auto& tmpError, const auto& tmpConfigs) {
201 ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs";
202 configs = tmpConfigs;
203 });
204
205 return configs;
206 }
207
getDisplayName(Display display)208 std::string ComposerClient::getDisplayName(Display display) {
209 std::string name;
210 mClient->getDisplayName(display, [&](const auto& tmpError, const auto& tmpName) {
211 ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name";
212 name = tmpName.c_str();
213 });
214
215 return name;
216 }
217
getDisplayType(Display display)218 IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) {
219 IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
220 mClient->getDisplayType(display, [&](const auto& tmpError, const auto& tmpType) {
221 ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type";
222 type = tmpType;
223 });
224
225 return type;
226 }
227
getDozeSupport(Display display)228 bool ComposerClient::getDozeSupport(Display display) {
229 bool support = false;
230 mClient->getDozeSupport(display, [&](const auto& tmpError, const auto& tmpSupport) {
231 ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support";
232 support = tmpSupport;
233 });
234
235 return support;
236 }
237
getHdrCapabilities(Display display,float * outMaxLuminance,float * outMaxAverageLuminance,float * outMinLuminance)238 std::vector<Hdr> ComposerClient::getHdrCapabilities(Display display, float* outMaxLuminance,
239 float* outMaxAverageLuminance,
240 float* outMinLuminance) {
241 std::vector<Hdr> types;
242 mClient->getHdrCapabilities(
243 display, [&](const auto& tmpError, const auto& tmpTypes, const auto& tmpMaxLuminance,
244 const auto& tmpMaxAverageLuminance, const auto& tmpMinLuminance) {
245 ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities";
246 types = tmpTypes;
247 *outMaxLuminance = tmpMaxLuminance;
248 *outMaxAverageLuminance = tmpMaxAverageLuminance;
249 *outMinLuminance = tmpMinLuminance;
250 });
251
252 return types;
253 }
254
setClientTargetSlotCount(Display display,uint32_t clientTargetSlotCount)255 void ComposerClient::setClientTargetSlotCount(Display display, uint32_t clientTargetSlotCount) {
256 Error error = mClient->setClientTargetSlotCount(display, clientTargetSlotCount);
257 ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count";
258 }
259
setActiveConfig(Display display,Config config)260 void ComposerClient::setActiveConfig(Display display, Config config) {
261 Error error = mClient->setActiveConfig(display, config);
262 ASSERT_EQ(Error::NONE, error) << "failed to set active config";
263 }
264
setColorMode(Display display,ColorMode mode)265 void ComposerClient::setColorMode(Display display, ColorMode mode) {
266 Error error = mClient->setColorMode(display, mode);
267 ASSERT_EQ(Error::NONE, error) << "failed to set color mode";
268 }
269
setPowerMode(Display display,IComposerClient::PowerMode mode)270 void ComposerClient::setPowerMode(Display display, IComposerClient::PowerMode mode) {
271 Error error = mClient->setPowerMode(display, mode);
272 ASSERT_EQ(Error::NONE, error) << "failed to set power mode";
273 }
274
setVsyncEnabled(Display display,bool enabled)275 void ComposerClient::setVsyncEnabled(Display display, bool enabled) {
276 IComposerClient::Vsync vsync =
277 (enabled) ? IComposerClient::Vsync::ENABLE : IComposerClient::Vsync::DISABLE;
278 Error error = mClient->setVsyncEnabled(display, vsync);
279 ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode";
280
281 // give the hwbinder thread some time to handle any pending vsync callback
282 if (!enabled) {
283 usleep(5 * 1000);
284 }
285 }
286
execute(TestCommandReader * reader,CommandWriterBase * writer)287 void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* writer) {
288 bool queueChanged = false;
289 uint32_t commandLength = 0;
290 hidl_vec<hidl_handle> commandHandles;
291 ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
292
293 if (queueChanged) {
294 auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
295 ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
296 }
297
298 mClient->executeCommands(commandLength, commandHandles,
299 [&](const auto& tmpError, const auto& tmpOutQueueChanged,
300 const auto& tmpOutLength, const auto& tmpOutHandles) {
301 ASSERT_EQ(Error::NONE, tmpError);
302
303 if (tmpOutQueueChanged) {
304 mClient->getOutputCommandQueue(
305 [&](const auto& tmpError, const auto& tmpDescriptor) {
306 ASSERT_EQ(Error::NONE, tmpError);
307 reader->setMQDescriptor(tmpDescriptor);
308 });
309 }
310
311 ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
312 reader->parse();
313 });
314 reader->reset();
315 writer->reset();
316 }
317
Gralloc()318 Gralloc::Gralloc() {
319 [this] {
320 ASSERT_NO_FATAL_FAILURE(mGralloc3 = std::make_shared<Gralloc3>("default", "default",
321 /*errOnFailure=*/false));
322 if (mGralloc3->getAllocator() == nullptr || mGralloc3->getMapper() == nullptr) {
323 mGralloc3 = nullptr;
324 ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared<Gralloc2>());
325 }
326 }();
327 }
328
allocate(uint32_t width,uint32_t height,uint32_t layerCount,PixelFormat format,uint64_t usage,bool import,uint32_t * outStride)329 const native_handle_t* Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount,
330 PixelFormat format, uint64_t usage, bool import,
331 uint32_t* outStride) {
332 if (mGralloc3) {
333 IMapper3::BufferDescriptorInfo info{};
334 info.width = width;
335 info.height = height;
336 info.layerCount = layerCount;
337 info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
338 info.usage = usage;
339 return mGralloc3->allocate(info, import, outStride);
340 } else {
341 IMapper2::BufferDescriptorInfo info{};
342 info.width = width;
343 info.height = height;
344 info.layerCount = layerCount;
345 info.format = format;
346 info.usage = usage;
347 return mGralloc2->allocate(info, import, outStride);
348 }
349 }
350
lock(const native_handle_t * bufferHandle,uint64_t cpuUsage,const AccessRegion & accessRegionRect,int acquireFence)351 void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
352 const AccessRegion& accessRegionRect, int acquireFence) {
353 if (mGralloc3) {
354 IMapper3::Rect accessRegion;
355 accessRegion.left = accessRegionRect.left;
356 accessRegion.top = accessRegionRect.top;
357 accessRegion.width = accessRegionRect.width;
358 accessRegion.height = accessRegionRect.height;
359 int32_t bytesPerPixel;
360 int32_t bytesPerStride;
361 return mGralloc3->lock(bufferHandle, cpuUsage, accessRegion, acquireFence, &bytesPerPixel,
362 &bytesPerStride);
363 } else {
364 IMapper2::Rect accessRegion;
365 accessRegion.left = accessRegionRect.left;
366 accessRegion.top = accessRegionRect.top;
367 accessRegion.width = accessRegionRect.width;
368 accessRegion.height = accessRegionRect.height;
369 return mGralloc2->lock(bufferHandle, cpuUsage, accessRegion, acquireFence);
370 }
371 }
372
unlock(const native_handle_t * bufferHandle)373 int Gralloc::unlock(const native_handle_t* bufferHandle) {
374 if (mGralloc3) {
375 return mGralloc3->unlock(bufferHandle);
376 } else {
377 return mGralloc2->unlock(bufferHandle);
378 }
379 }
380
freeBuffer(const native_handle_t * bufferHandle)381 void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
382 if (mGralloc3) {
383 mGralloc3->freeBuffer(bufferHandle);
384 } else {
385 mGralloc2->freeBuffer(bufferHandle);
386 }
387 }
388
389 } // namespace vts
390 } // namespace V2_1
391 } // namespace composer
392 } // namespace graphics
393 } // namespace hardware
394 } // namespace android
395