blob: 3e9ef2425d15b5a4115f5c8e8249585f66ff5c03 [file] [log] [blame]
Chia-I Wuaab99f52016-10-05 12:59:58 +08001/*
2 * Copyright 2016 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#undef LOG_TAG
18#define LOG_TAG "HwcComposer"
19
Daniel Nicoara2f5f8a52016-12-20 16:11:58 -050020#include <android/dvr/composer/1.0/IVrComposerClient.h>
Chia-I Wuaab99f52016-10-05 12:59:58 +080021#include <inttypes.h>
22#include <log/log.h>
Chia-I Wu06d63de2017-01-04 14:58:51 +080023#include <gui/BufferQueue.h>
Chia-I Wuaab99f52016-10-05 12:59:58 +080024
25#include "ComposerHal.h"
26
27namespace android {
28
Daniel Nicoara2f5f8a52016-12-20 16:11:58 -050029using dvr::composer::V1_0::IVrComposerClient;
Chia-I Wuaab99f52016-10-05 12:59:58 +080030using hardware::Return;
31using hardware::hidl_vec;
Martijn Coenen7c5a92f2016-11-21 10:01:07 +010032using hardware::hidl_handle;
Chia-I Wuaab99f52016-10-05 12:59:58 +080033
34namespace Hwc2 {
35
36namespace {
37
38class BufferHandle {
39public:
40 BufferHandle(const native_handle_t* buffer)
41 {
42 // nullptr is not a valid handle to HIDL
43 mHandle = (buffer) ? buffer : native_handle_init(mStorage, 0, 0);
44 }
45
Martijn Coenen7c5a92f2016-11-21 10:01:07 +010046 operator const hidl_handle&() const
Chia-I Wuaab99f52016-10-05 12:59:58 +080047 {
48 return mHandle;
49 }
50
51private:
52 NATIVE_HANDLE_DECLARE_STORAGE(mStorage, 0, 0);
Martijn Coenen7c5a92f2016-11-21 10:01:07 +010053 hidl_handle mHandle;
Chia-I Wuaab99f52016-10-05 12:59:58 +080054};
55
56class FenceHandle
57{
58public:
59 FenceHandle(int fd, bool owned)
60 : mOwned(owned)
61 {
Martijn Coenen7c5a92f2016-11-21 10:01:07 +010062 native_handle_t* handle;
Chia-I Wuaab99f52016-10-05 12:59:58 +080063 if (fd >= 0) {
Martijn Coenen7c5a92f2016-11-21 10:01:07 +010064 handle = native_handle_init(mStorage, 1, 0);
65 handle->data[0] = fd;
Chia-I Wuaab99f52016-10-05 12:59:58 +080066 } else {
67 // nullptr is not a valid handle to HIDL
Martijn Coenen7c5a92f2016-11-21 10:01:07 +010068 handle = native_handle_init(mStorage, 0, 0);
Chia-I Wuaab99f52016-10-05 12:59:58 +080069 }
Martijn Coenen7c5a92f2016-11-21 10:01:07 +010070 mHandle = handle;
Chia-I Wuaab99f52016-10-05 12:59:58 +080071 }
72
73 ~FenceHandle()
74 {
75 if (mOwned) {
76 native_handle_close(mHandle);
77 }
78 }
79
Martijn Coenen7c5a92f2016-11-21 10:01:07 +010080 operator const hidl_handle&() const
Chia-I Wuaab99f52016-10-05 12:59:58 +080081 {
82 return mHandle;
83 }
84
85private:
86 bool mOwned;
87 NATIVE_HANDLE_DECLARE_STORAGE(mStorage, 1, 0);
Martijn Coenen7c5a92f2016-11-21 10:01:07 +010088 hidl_handle mHandle;
Chia-I Wuaab99f52016-10-05 12:59:58 +080089};
90
91// assume NO_RESOURCES when Status::isOk returns false
92constexpr Error kDefaultError = Error::NO_RESOURCES;
93
94template<typename T, typename U>
95T unwrapRet(Return<T>& ret, const U& default_val)
96{
Steven Moreland9d021002017-01-03 17:10:54 -080097 return (ret.isOk()) ? static_cast<T>(ret) :
Chia-I Wuaab99f52016-10-05 12:59:58 +080098 static_cast<T>(default_val);
99}
100
101Error unwrapRet(Return<Error>& ret)
102{
103 return unwrapRet(ret, kDefaultError);
104}
105
Chia-I Wuaab99f52016-10-05 12:59:58 +0800106} // anonymous namespace
107
Daniel Nicoara2f5f8a52016-12-20 16:11:58 -0500108Composer::CommandWriter::CommandWriter(uint32_t initialMaxSize)
109 : CommandWriterBase(initialMaxSize) {}
110
111Composer::CommandWriter::~CommandWriter()
Chia-I Wuaab99f52016-10-05 12:59:58 +0800112{
Daniel Nicoara2f5f8a52016-12-20 16:11:58 -0500113}
114
115void Composer::CommandWriter::setLayerInfo(uint32_t type, uint32_t appId)
116{
117 constexpr uint16_t kSetLayerInfoLength = 2;
118 beginCommand(
119 static_cast<IComposerClient::Command>(
120 IVrComposerClient::VrCommand::SET_LAYER_INFO),
121 kSetLayerInfoLength);
122 write(type);
123 write(appId);
124 endCommand();
125}
126
Hendrik Wagenaar87670ff2017-02-01 12:10:46 -0800127Composer::Composer(bool useVrComposer)
128 : mWriter(kWriterInitialSize),
129 mIsUsingVrComposer(useVrComposer)
Daniel Nicoara2f5f8a52016-12-20 16:11:58 -0500130{
Hendrik Wagenaar87670ff2017-02-01 12:10:46 -0800131 if (mIsUsingVrComposer) {
Daniel Nicoara2f5f8a52016-12-20 16:11:58 -0500132 mComposer = IComposer::getService("vr_hwcomposer");
133 } else {
134 mComposer = IComposer::getService("hwcomposer");
135 }
136
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800137 if (mComposer == nullptr) {
Chia-I Wuaab99f52016-10-05 12:59:58 +0800138 LOG_ALWAYS_FATAL("failed to get hwcomposer service");
139 }
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800140
141 mComposer->createClient(
142 [&](const auto& tmpError, const auto& tmpClient)
143 {
144 if (tmpError == Error::NONE) {
145 mClient = tmpClient;
146 }
147 });
148 if (mClient == nullptr) {
149 LOG_ALWAYS_FATAL("failed to create composer client");
150 }
Chia-I Wuaab99f52016-10-05 12:59:58 +0800151}
152
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800153std::vector<IComposer::Capability> Composer::getCapabilities()
Chia-I Wuaab99f52016-10-05 12:59:58 +0800154{
155 std::vector<IComposer::Capability> capabilities;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800156 mComposer->getCapabilities(
Chia-I Wuaab99f52016-10-05 12:59:58 +0800157 [&](const auto& tmpCapabilities) {
Chia-I Wu67e376d2016-12-19 11:36:22 +0800158 capabilities = tmpCapabilities;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800159 });
160
161 return capabilities;
162}
163
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800164std::string Composer::dumpDebugInfo()
Chia-I Wuaab99f52016-10-05 12:59:58 +0800165{
166 std::string info;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800167 mComposer->dumpDebugInfo([&](const auto& tmpInfo) {
Chia-I Wuaab99f52016-10-05 12:59:58 +0800168 info = tmpInfo.c_str();
169 });
170
171 return info;
172}
173
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800174void Composer::registerCallback(const sp<IComposerCallback>& callback)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800175{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800176 auto ret = mClient->registerCallback(callback);
Steven Moreland9d021002017-01-03 17:10:54 -0800177 if (!ret.isOk()) {
Chia-I Wuaab99f52016-10-05 12:59:58 +0800178 ALOGE("failed to register IComposerCallback");
179 }
180}
181
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800182uint32_t Composer::getMaxVirtualDisplayCount()
Chia-I Wuaab99f52016-10-05 12:59:58 +0800183{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800184 auto ret = mClient->getMaxVirtualDisplayCount();
Chia-I Wuaab99f52016-10-05 12:59:58 +0800185 return unwrapRet(ret, 0);
186}
187
188Error Composer::createVirtualDisplay(uint32_t width, uint32_t height,
Chia-I Wu67e376d2016-12-19 11:36:22 +0800189 PixelFormat* format, Display* outDisplay)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800190{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800191 const uint32_t bufferSlotCount = 1;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800192 Error error = kDefaultError;
Chia-I Wu67e376d2016-12-19 11:36:22 +0800193 mClient->createVirtualDisplay(width, height, *format, bufferSlotCount,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800194 [&](const auto& tmpError, const auto& tmpDisplay,
195 const auto& tmpFormat) {
196 error = tmpError;
197 if (error != Error::NONE) {
198 return;
199 }
200
Chia-I Wu67e376d2016-12-19 11:36:22 +0800201 *outDisplay = tmpDisplay;
202 *format = tmpFormat;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800203 });
204
205 return error;
206}
207
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800208Error Composer::destroyVirtualDisplay(Display display)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800209{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800210 auto ret = mClient->destroyVirtualDisplay(display);
Chia-I Wuaab99f52016-10-05 12:59:58 +0800211 return unwrapRet(ret);
212}
213
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800214Error Composer::acceptDisplayChanges(Display display)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800215{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800216 mWriter.selectDisplay(display);
217 mWriter.acceptDisplayChanges();
218 return Error::NONE;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800219}
220
Chia-I Wu67e376d2016-12-19 11:36:22 +0800221Error Composer::createLayer(Display display, Layer* outLayer)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800222{
223 Error error = kDefaultError;
Chia-I Wu06d63de2017-01-04 14:58:51 +0800224 mClient->createLayer(display, BufferQueue::NUM_BUFFER_SLOTS,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800225 [&](const auto& tmpError, const auto& tmpLayer) {
226 error = tmpError;
227 if (error != Error::NONE) {
228 return;
229 }
230
Chia-I Wu67e376d2016-12-19 11:36:22 +0800231 *outLayer = tmpLayer;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800232 });
233
234 return error;
235}
236
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800237Error Composer::destroyLayer(Display display, Layer layer)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800238{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800239 auto ret = mClient->destroyLayer(display, layer);
Chia-I Wuaab99f52016-10-05 12:59:58 +0800240 return unwrapRet(ret);
241}
242
Chia-I Wu67e376d2016-12-19 11:36:22 +0800243Error Composer::getActiveConfig(Display display, Config* outConfig)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800244{
245 Error error = kDefaultError;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800246 mClient->getActiveConfig(display,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800247 [&](const auto& tmpError, const auto& tmpConfig) {
248 error = tmpError;
249 if (error != Error::NONE) {
250 return;
251 }
252
Chia-I Wu67e376d2016-12-19 11:36:22 +0800253 *outConfig = tmpConfig;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800254 });
255
256 return error;
257}
258
259Error Composer::getChangedCompositionTypes(Display display,
Chia-I Wu67e376d2016-12-19 11:36:22 +0800260 std::vector<Layer>* outLayers,
261 std::vector<IComposerClient::Composition>* outTypes)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800262{
Chia-I Wu67e376d2016-12-19 11:36:22 +0800263 mReader.takeChangedCompositionTypes(display, outLayers, outTypes);
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800264 return Error::NONE;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800265}
266
267Error Composer::getColorModes(Display display,
Chia-I Wu67e376d2016-12-19 11:36:22 +0800268 std::vector<ColorMode>* outModes)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800269{
270 Error error = kDefaultError;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800271 mClient->getColorModes(display,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800272 [&](const auto& tmpError, const auto& tmpModes) {
273 error = tmpError;
274 if (error != Error::NONE) {
275 return;
276 }
277
Chia-I Wu67e376d2016-12-19 11:36:22 +0800278 *outModes = tmpModes;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800279 });
280
281 return error;
282}
283
284Error Composer::getDisplayAttribute(Display display, Config config,
Chia-I Wu67e376d2016-12-19 11:36:22 +0800285 IComposerClient::Attribute attribute, int32_t* outValue)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800286{
287 Error error = kDefaultError;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800288 mClient->getDisplayAttribute(display, config, attribute,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800289 [&](const auto& tmpError, const auto& tmpValue) {
290 error = tmpError;
291 if (error != Error::NONE) {
292 return;
293 }
294
Chia-I Wu67e376d2016-12-19 11:36:22 +0800295 *outValue = tmpValue;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800296 });
297
298 return error;
299}
300
301Error Composer::getDisplayConfigs(Display display,
Chia-I Wu67e376d2016-12-19 11:36:22 +0800302 std::vector<Config>* outConfigs)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800303{
304 Error error = kDefaultError;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800305 mClient->getDisplayConfigs(display,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800306 [&](const auto& tmpError, const auto& tmpConfigs) {
307 error = tmpError;
308 if (error != Error::NONE) {
309 return;
310 }
311
Chia-I Wu67e376d2016-12-19 11:36:22 +0800312 *outConfigs = tmpConfigs;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800313 });
314
315 return error;
316}
317
Chia-I Wu67e376d2016-12-19 11:36:22 +0800318Error Composer::getDisplayName(Display display, std::string* outName)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800319{
320 Error error = kDefaultError;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800321 mClient->getDisplayName(display,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800322 [&](const auto& tmpError, const auto& tmpName) {
323 error = tmpError;
324 if (error != Error::NONE) {
325 return;
326 }
327
Chia-I Wu67e376d2016-12-19 11:36:22 +0800328 *outName = tmpName.c_str();
Chia-I Wuaab99f52016-10-05 12:59:58 +0800329 });
330
331 return error;
332}
333
334Error Composer::getDisplayRequests(Display display,
Chia-I Wu67e376d2016-12-19 11:36:22 +0800335 uint32_t* outDisplayRequestMask, std::vector<Layer>* outLayers,
336 std::vector<uint32_t>* outLayerRequestMasks)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800337{
Chia-I Wu67e376d2016-12-19 11:36:22 +0800338 mReader.takeDisplayRequests(display, outDisplayRequestMask,
339 outLayers, outLayerRequestMasks);
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800340 return Error::NONE;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800341}
342
Chia-I Wu67e376d2016-12-19 11:36:22 +0800343Error Composer::getDisplayType(Display display,
344 IComposerClient::DisplayType* outType)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800345{
346 Error error = kDefaultError;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800347 mClient->getDisplayType(display,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800348 [&](const auto& tmpError, const auto& tmpType) {
349 error = tmpError;
350 if (error != Error::NONE) {
351 return;
352 }
353
Chia-I Wu67e376d2016-12-19 11:36:22 +0800354 *outType = tmpType;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800355 });
356
357 return error;
358}
359
Chia-I Wu67e376d2016-12-19 11:36:22 +0800360Error Composer::getDozeSupport(Display display, bool* outSupport)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800361{
362 Error error = kDefaultError;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800363 mClient->getDozeSupport(display,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800364 [&](const auto& tmpError, const auto& tmpSupport) {
365 error = tmpError;
366 if (error != Error::NONE) {
367 return;
368 }
369
Chia-I Wu67e376d2016-12-19 11:36:22 +0800370 *outSupport = tmpSupport;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800371 });
372
373 return error;
374}
375
Chia-I Wu67e376d2016-12-19 11:36:22 +0800376Error Composer::getHdrCapabilities(Display display,
377 std::vector<Hdr>* outTypes, float* outMaxLuminance,
378 float* outMaxAverageLuminance, float* outMinLuminance)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800379{
380 Error error = kDefaultError;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800381 mClient->getHdrCapabilities(display,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800382 [&](const auto& tmpError, const auto& tmpTypes,
383 const auto& tmpMaxLuminance,
384 const auto& tmpMaxAverageLuminance,
385 const auto& tmpMinLuminance) {
386 error = tmpError;
387 if (error != Error::NONE) {
388 return;
389 }
390
Chia-I Wu67e376d2016-12-19 11:36:22 +0800391 *outTypes = tmpTypes;
392 *outMaxLuminance = tmpMaxLuminance;
393 *outMaxAverageLuminance = tmpMaxAverageLuminance;
394 *outMinLuminance = tmpMinLuminance;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800395 });
396
397 return error;
398}
399
Chia-I Wu67e376d2016-12-19 11:36:22 +0800400Error Composer::getReleaseFences(Display display,
401 std::vector<Layer>* outLayers, std::vector<int>* outReleaseFences)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800402{
Chia-I Wu67e376d2016-12-19 11:36:22 +0800403 mReader.takeReleaseFences(display, outLayers, outReleaseFences);
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800404 return Error::NONE;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800405}
406
Chia-I Wu67e376d2016-12-19 11:36:22 +0800407Error Composer::presentDisplay(Display display, int* outPresentFence)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800408{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800409 mWriter.selectDisplay(display);
410 mWriter.presentDisplay();
Chia-I Wuaab99f52016-10-05 12:59:58 +0800411
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800412 Error error = execute();
413 if (error != Error::NONE) {
414 return error;
415 }
Chia-I Wuaab99f52016-10-05 12:59:58 +0800416
Chia-I Wu67e376d2016-12-19 11:36:22 +0800417 mReader.takePresentFence(display, outPresentFence);
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800418
419 return Error::NONE;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800420}
421
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800422Error Composer::setActiveConfig(Display display, Config config)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800423{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800424 auto ret = mClient->setActiveConfig(display, config);
Chia-I Wuaab99f52016-10-05 12:59:58 +0800425 return unwrapRet(ret);
426}
427
Chia-I Wu06d63de2017-01-04 14:58:51 +0800428Error Composer::setClientTarget(Display display, uint32_t slot,
429 const native_handle_t* target,
Chia-I Wuaab99f52016-10-05 12:59:58 +0800430 int acquireFence, Dataspace dataspace,
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800431 const std::vector<IComposerClient::Rect>& damage)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800432{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800433 mWriter.selectDisplay(display);
Chia-I Wu06d63de2017-01-04 14:58:51 +0800434 mWriter.setClientTarget(slot, target, acquireFence, dataspace, damage);
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800435 return Error::NONE;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800436}
437
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800438Error Composer::setColorMode(Display display, ColorMode mode)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800439{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800440 auto ret = mClient->setColorMode(display, mode);
Chia-I Wuaab99f52016-10-05 12:59:58 +0800441 return unwrapRet(ret);
442}
443
444Error Composer::setColorTransform(Display display, const float* matrix,
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800445 ColorTransform hint)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800446{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800447 mWriter.selectDisplay(display);
448 mWriter.setColorTransform(matrix, hint);
449 return Error::NONE;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800450}
451
452Error Composer::setOutputBuffer(Display display, const native_handle_t* buffer,
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800453 int releaseFence)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800454{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800455 mWriter.selectDisplay(display);
456 mWriter.setOutputBuffer(0, buffer, dup(releaseFence));
457 return Error::NONE;
458}
Chia-I Wuaab99f52016-10-05 12:59:58 +0800459
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800460Error Composer::setPowerMode(Display display, IComposerClient::PowerMode mode)
461{
462 auto ret = mClient->setPowerMode(display, mode);
Chia-I Wuaab99f52016-10-05 12:59:58 +0800463 return unwrapRet(ret);
464}
465
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800466Error Composer::setVsyncEnabled(Display display, IComposerClient::Vsync enabled)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800467{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800468 auto ret = mClient->setVsyncEnabled(display, enabled);
Chia-I Wuaab99f52016-10-05 12:59:58 +0800469 return unwrapRet(ret);
470}
471
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800472Error Composer::setClientTargetSlotCount(Display display)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800473{
Chia-I Wu06d63de2017-01-04 14:58:51 +0800474 const uint32_t bufferSlotCount = BufferQueue::NUM_BUFFER_SLOTS;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800475 auto ret = mClient->setClientTargetSlotCount(display, bufferSlotCount);
Chia-I Wuaab99f52016-10-05 12:59:58 +0800476 return unwrapRet(ret);
477}
478
Chia-I Wu67e376d2016-12-19 11:36:22 +0800479Error Composer::validateDisplay(Display display, uint32_t* outNumTypes,
480 uint32_t* outNumRequests)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800481{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800482 mWriter.selectDisplay(display);
483 mWriter.validateDisplay();
484
485 Error error = execute();
486 if (error != Error::NONE) {
487 return error;
488 }
489
Chia-I Wu67e376d2016-12-19 11:36:22 +0800490 mReader.hasChanges(display, outNumTypes, outNumRequests);
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800491
492 return Error::NONE;
493}
494
495Error Composer::setCursorPosition(Display display, Layer layer,
496 int32_t x, int32_t y)
497{
498 mWriter.selectDisplay(display);
499 mWriter.selectLayer(layer);
500 mWriter.setLayerCursorPosition(x, y);
501 return Error::NONE;
502}
503
504Error Composer::setLayerBuffer(Display display, Layer layer,
Chia-I Wu06d63de2017-01-04 14:58:51 +0800505 uint32_t slot, const native_handle_t* buffer, int acquireFence)
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800506{
507 mWriter.selectDisplay(display);
508 mWriter.selectLayer(layer);
Chia-I Wu06d63de2017-01-04 14:58:51 +0800509 mWriter.setLayerBuffer(slot, buffer, acquireFence);
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800510 return Error::NONE;
511}
512
513Error Composer::setLayerSurfaceDamage(Display display, Layer layer,
514 const std::vector<IComposerClient::Rect>& damage)
515{
516 mWriter.selectDisplay(display);
517 mWriter.selectLayer(layer);
518 mWriter.setLayerSurfaceDamage(damage);
519 return Error::NONE;
520}
521
522Error Composer::setLayerBlendMode(Display display, Layer layer,
523 IComposerClient::BlendMode mode)
524{
525 mWriter.selectDisplay(display);
526 mWriter.selectLayer(layer);
527 mWriter.setLayerBlendMode(mode);
528 return Error::NONE;
529}
530
531Error Composer::setLayerColor(Display display, Layer layer,
532 const IComposerClient::Color& color)
533{
534 mWriter.selectDisplay(display);
535 mWriter.selectLayer(layer);
536 mWriter.setLayerColor(color);
537 return Error::NONE;
538}
539
540Error Composer::setLayerCompositionType(Display display, Layer layer,
541 IComposerClient::Composition type)
542{
543 mWriter.selectDisplay(display);
544 mWriter.selectLayer(layer);
545 mWriter.setLayerCompositionType(type);
546 return Error::NONE;
547}
548
549Error Composer::setLayerDataspace(Display display, Layer layer,
550 Dataspace dataspace)
551{
552 mWriter.selectDisplay(display);
553 mWriter.selectLayer(layer);
554 mWriter.setLayerDataspace(dataspace);
555 return Error::NONE;
556}
557
558Error Composer::setLayerDisplayFrame(Display display, Layer layer,
559 const IComposerClient::Rect& frame)
560{
561 mWriter.selectDisplay(display);
562 mWriter.selectLayer(layer);
563 mWriter.setLayerDisplayFrame(frame);
564 return Error::NONE;
565}
566
567Error Composer::setLayerPlaneAlpha(Display display, Layer layer,
568 float alpha)
569{
570 mWriter.selectDisplay(display);
571 mWriter.selectLayer(layer);
572 mWriter.setLayerPlaneAlpha(alpha);
573 return Error::NONE;
574}
575
576Error Composer::setLayerSidebandStream(Display display, Layer layer,
577 const native_handle_t* stream)
578{
579 mWriter.selectDisplay(display);
580 mWriter.selectLayer(layer);
581 mWriter.setLayerSidebandStream(stream);
582 return Error::NONE;
583}
584
585Error Composer::setLayerSourceCrop(Display display, Layer layer,
586 const IComposerClient::FRect& crop)
587{
588 mWriter.selectDisplay(display);
589 mWriter.selectLayer(layer);
590 mWriter.setLayerSourceCrop(crop);
591 return Error::NONE;
592}
593
594Error Composer::setLayerTransform(Display display, Layer layer,
595 Transform transform)
596{
597 mWriter.selectDisplay(display);
598 mWriter.selectLayer(layer);
599 mWriter.setLayerTransform(transform);
600 return Error::NONE;
601}
602
603Error Composer::setLayerVisibleRegion(Display display, Layer layer,
604 const std::vector<IComposerClient::Rect>& visible)
605{
606 mWriter.selectDisplay(display);
607 mWriter.selectLayer(layer);
608 mWriter.setLayerVisibleRegion(visible);
609 return Error::NONE;
610}
611
612Error Composer::setLayerZOrder(Display display, Layer layer, uint32_t z)
613{
614 mWriter.selectDisplay(display);
615 mWriter.selectLayer(layer);
616 mWriter.setLayerZOrder(z);
617 return Error::NONE;
618}
619
Daniel Nicoara2f5f8a52016-12-20 16:11:58 -0500620Error Composer::setLayerInfo(Display display, Layer layer, uint32_t type,
621 uint32_t appId)
622{
Hendrik Wagenaar87670ff2017-02-01 12:10:46 -0800623 if (mIsUsingVrComposer) {
Daniel Nicoara2f5f8a52016-12-20 16:11:58 -0500624 mWriter.selectDisplay(display);
625 mWriter.selectLayer(layer);
626 mWriter.setLayerInfo(type, appId);
627 }
628 return Error::NONE;
629}
630
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800631Error Composer::execute()
632{
633 // prepare input command queue
634 bool queueChanged = false;
635 uint32_t commandLength = 0;
636 hidl_vec<hidl_handle> commandHandles;
Chia-I Wu67e376d2016-12-19 11:36:22 +0800637 if (!mWriter.writeQueue(&queueChanged, &commandLength, &commandHandles)) {
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800638 mWriter.reset();
639 return Error::NO_RESOURCES;
640 }
641
642 // set up new input command queue if necessary
643 if (queueChanged) {
644 auto ret = mClient->setInputCommandQueue(*mWriter.getMQDescriptor());
645 auto error = unwrapRet(ret);
646 if (error != Error::NONE) {
647 mWriter.reset();
648 return error;
649 }
650 }
651
Chia-I Wuaab99f52016-10-05 12:59:58 +0800652 Error error = kDefaultError;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800653 mClient->executeCommands(commandLength, commandHandles,
654 [&](const auto& tmpError, const auto& tmpOutChanged,
655 const auto& tmpOutLength, const auto& tmpOutHandles)
656 {
Chia-I Wuaab99f52016-10-05 12:59:58 +0800657 error = tmpError;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800658
659 // set up new output command queue if necessary
660 if (error == Error::NONE && tmpOutChanged) {
661 error = kDefaultError;
662 mClient->getOutputCommandQueue(
663 [&](const auto& tmpError,
664 const auto& tmpDescriptor)
665 {
666 error = tmpError;
667 if (error != Error::NONE) {
668 return;
669 }
670
671 mReader.setMQDescriptor(tmpDescriptor);
672 });
673 }
674
Chia-I Wuaab99f52016-10-05 12:59:58 +0800675 if (error != Error::NONE) {
676 return;
677 }
678
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800679 if (mReader.readQueue(tmpOutLength, tmpOutHandles)) {
680 error = mReader.parse();
681 mReader.reset();
682 } else {
683 error = Error::NO_RESOURCES;
684 }
Chia-I Wuaab99f52016-10-05 12:59:58 +0800685 });
686
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800687 if (error == Error::NONE) {
688 std::vector<CommandReader::CommandError> commandErrors =
689 mReader.takeErrors();
690
691 for (const auto& cmdErr : commandErrors) {
692 auto command = mWriter.getCommand(cmdErr.location);
693
694 if (command == IComposerClient::Command::VALIDATE_DISPLAY ||
695 command == IComposerClient::Command::PRESENT_DISPLAY) {
696 error = cmdErr.error;
697 } else {
698 ALOGW("command 0x%x generated error %d",
699 command, cmdErr.error);
700 }
701 }
702 }
703
704 mWriter.reset();
705
Chia-I Wuaab99f52016-10-05 12:59:58 +0800706 return error;
707}
708
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800709CommandReader::~CommandReader()
Chia-I Wuaab99f52016-10-05 12:59:58 +0800710{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800711 resetData();
Chia-I Wuaab99f52016-10-05 12:59:58 +0800712}
713
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800714Error CommandReader::parse()
Chia-I Wuaab99f52016-10-05 12:59:58 +0800715{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800716 resetData();
Chia-I Wuaab99f52016-10-05 12:59:58 +0800717
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800718 IComposerClient::Command command;
719 uint16_t length = 0;
720
721 while (!isEmpty()) {
Chia-I Wu67e376d2016-12-19 11:36:22 +0800722 if (!beginCommand(&command, &length)) {
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800723 break;
724 }
725
726 bool parsed = false;
727 switch (command) {
728 case IComposerClient::Command::SELECT_DISPLAY:
729 parsed = parseSelectDisplay(length);
730 break;
731 case IComposerClient::Command::SET_ERROR:
732 parsed = parseSetError(length);
733 break;
734 case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
735 parsed = parseSetChangedCompositionTypes(length);
736 break;
737 case IComposerClient::Command::SET_DISPLAY_REQUESTS:
738 parsed = parseSetDisplayRequests(length);
739 break;
740 case IComposerClient::Command::SET_PRESENT_FENCE:
741 parsed = parseSetPresentFence(length);
742 break;
743 case IComposerClient::Command::SET_RELEASE_FENCES:
744 parsed = parseSetReleaseFences(length);
745 break;
746 default:
747 parsed = false;
748 break;
749 }
750
751 endCommand();
752
753 if (!parsed) {
754 ALOGE("failed to parse command 0x%x length %" PRIu16,
755 command, length);
756 break;
757 }
758 }
759
760 return isEmpty() ? Error::NONE : Error::NO_RESOURCES;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800761}
762
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800763bool CommandReader::parseSelectDisplay(uint16_t length)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800764{
Daniel Nicoara3c9cbd42017-01-17 12:04:06 -0500765 if (length != CommandWriterBase::kSelectDisplayLength) {
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800766 return false;
767 }
Chia-I Wuaab99f52016-10-05 12:59:58 +0800768
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800769 mCurrentReturnData = &mReturnData[read64()];
770
771 return true;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800772}
773
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800774bool CommandReader::parseSetError(uint16_t length)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800775{
Daniel Nicoara3c9cbd42017-01-17 12:04:06 -0500776 if (length != CommandWriterBase::kSetErrorLength) {
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800777 return false;
778 }
779
780 auto location = read();
781 auto error = static_cast<Error>(readSigned());
782
783 mErrors.emplace_back(CommandError{location, error});
784
785 return true;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800786}
787
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800788bool CommandReader::parseSetChangedCompositionTypes(uint16_t length)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800789{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800790 // (layer id, composition type) pairs
791 if (length % 3 != 0 || !mCurrentReturnData) {
792 return false;
793 }
794
795 uint32_t count = length / 3;
796 mCurrentReturnData->changedLayers.reserve(count);
797 mCurrentReturnData->compositionTypes.reserve(count);
798 while (count > 0) {
799 auto layer = read64();
800 auto type = static_cast<IComposerClient::Composition>(readSigned());
801
802 mCurrentReturnData->changedLayers.push_back(layer);
803 mCurrentReturnData->compositionTypes.push_back(type);
804
805 count--;
806 }
807
808 return true;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800809}
810
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800811bool CommandReader::parseSetDisplayRequests(uint16_t length)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800812{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800813 // display requests followed by (layer id, layer requests) pairs
814 if (length % 3 != 1 || !mCurrentReturnData) {
815 return false;
816 }
817
818 mCurrentReturnData->displayRequests = read();
819
820 uint32_t count = (length - 1) / 3;
821 mCurrentReturnData->requestedLayers.reserve(count);
822 mCurrentReturnData->requestMasks.reserve(count);
823 while (count > 0) {
824 auto layer = read64();
825 auto layerRequestMask = read();
826
827 mCurrentReturnData->requestedLayers.push_back(layer);
828 mCurrentReturnData->requestMasks.push_back(layerRequestMask);
829
830 count--;
831 }
832
833 return true;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800834}
835
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800836bool CommandReader::parseSetPresentFence(uint16_t length)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800837{
Daniel Nicoara3c9cbd42017-01-17 12:04:06 -0500838 if (length != CommandWriterBase::kSetPresentFenceLength ||
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800839 !mCurrentReturnData) {
840 return false;
841 }
842
843 if (mCurrentReturnData->presentFence >= 0) {
844 close(mCurrentReturnData->presentFence);
845 }
846 mCurrentReturnData->presentFence = readFence();
847
848 return true;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800849}
850
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800851bool CommandReader::parseSetReleaseFences(uint16_t length)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800852{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800853 // (layer id, release fence index) pairs
854 if (length % 3 != 0 || !mCurrentReturnData) {
855 return false;
856 }
857
858 uint32_t count = length / 3;
859 mCurrentReturnData->releasedLayers.reserve(count);
860 mCurrentReturnData->releaseFences.reserve(count);
861 while (count > 0) {
862 auto layer = read64();
863 auto fence = readFence();
864
865 mCurrentReturnData->releasedLayers.push_back(layer);
866 mCurrentReturnData->releaseFences.push_back(fence);
867
868 count--;
869 }
870
871 return true;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800872}
873
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800874void CommandReader::resetData()
Chia-I Wuaab99f52016-10-05 12:59:58 +0800875{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800876 mErrors.clear();
877
878 for (auto& data : mReturnData) {
879 if (data.second.presentFence >= 0) {
880 close(data.second.presentFence);
881 }
882 for (auto fence : data.second.releaseFences) {
883 if (fence >= 0) {
884 close(fence);
885 }
886 }
887 }
888
889 mReturnData.clear();
890 mCurrentReturnData = nullptr;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800891}
892
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800893std::vector<CommandReader::CommandError> CommandReader::takeErrors()
Chia-I Wuaab99f52016-10-05 12:59:58 +0800894{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800895 return std::move(mErrors);
Chia-I Wuaab99f52016-10-05 12:59:58 +0800896}
897
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800898bool CommandReader::hasChanges(Display display,
Chia-I Wu67e376d2016-12-19 11:36:22 +0800899 uint32_t* outNumChangedCompositionTypes,
900 uint32_t* outNumLayerRequestMasks) const
Chia-I Wuaab99f52016-10-05 12:59:58 +0800901{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800902 auto found = mReturnData.find(display);
903 if (found == mReturnData.end()) {
Chia-I Wu67e376d2016-12-19 11:36:22 +0800904 *outNumChangedCompositionTypes = 0;
905 *outNumLayerRequestMasks = 0;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800906 return false;
907 }
908
909 const ReturnData& data = found->second;
910
Chia-I Wu67e376d2016-12-19 11:36:22 +0800911 *outNumChangedCompositionTypes = data.compositionTypes.size();
912 *outNumLayerRequestMasks = data.requestMasks.size();
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800913
914 return !(data.compositionTypes.empty() && data.requestMasks.empty());
Chia-I Wuaab99f52016-10-05 12:59:58 +0800915}
916
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800917void CommandReader::takeChangedCompositionTypes(Display display,
Chia-I Wu67e376d2016-12-19 11:36:22 +0800918 std::vector<Layer>* outLayers,
919 std::vector<IComposerClient::Composition>* outTypes)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800920{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800921 auto found = mReturnData.find(display);
922 if (found == mReturnData.end()) {
Chia-I Wu67e376d2016-12-19 11:36:22 +0800923 outLayers->clear();
924 outTypes->clear();
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800925 return;
926 }
927
928 ReturnData& data = found->second;
929
Chia-I Wu67e376d2016-12-19 11:36:22 +0800930 *outLayers = std::move(data.changedLayers);
931 *outTypes = std::move(data.compositionTypes);
Chia-I Wuaab99f52016-10-05 12:59:58 +0800932}
933
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800934void CommandReader::takeDisplayRequests(Display display,
Chia-I Wu67e376d2016-12-19 11:36:22 +0800935 uint32_t* outDisplayRequestMask, std::vector<Layer>* outLayers,
936 std::vector<uint32_t>* outLayerRequestMasks)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800937{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800938 auto found = mReturnData.find(display);
939 if (found == mReturnData.end()) {
Chia-I Wu67e376d2016-12-19 11:36:22 +0800940 *outDisplayRequestMask = 0;
941 outLayers->clear();
942 outLayerRequestMasks->clear();
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800943 return;
944 }
Chia-I Wuaab99f52016-10-05 12:59:58 +0800945
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800946 ReturnData& data = found->second;
947
Chia-I Wu67e376d2016-12-19 11:36:22 +0800948 *outDisplayRequestMask = data.displayRequests;
949 *outLayers = std::move(data.requestedLayers);
950 *outLayerRequestMasks = std::move(data.requestMasks);
Chia-I Wuaab99f52016-10-05 12:59:58 +0800951}
952
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800953void CommandReader::takeReleaseFences(Display display,
Chia-I Wu67e376d2016-12-19 11:36:22 +0800954 std::vector<Layer>* outLayers, std::vector<int>* outReleaseFences)
Chia-I Wuaab99f52016-10-05 12:59:58 +0800955{
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800956 auto found = mReturnData.find(display);
957 if (found == mReturnData.end()) {
Chia-I Wu67e376d2016-12-19 11:36:22 +0800958 outLayers->clear();
959 outReleaseFences->clear();
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800960 return;
961 }
962
963 ReturnData& data = found->second;
964
Chia-I Wu67e376d2016-12-19 11:36:22 +0800965 *outLayers = std::move(data.releasedLayers);
966 *outReleaseFences = std::move(data.releaseFences);
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800967}
968
Chia-I Wu67e376d2016-12-19 11:36:22 +0800969void CommandReader::takePresentFence(Display display, int* outPresentFence)
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800970{
971 auto found = mReturnData.find(display);
972 if (found == mReturnData.end()) {
Chia-I Wu67e376d2016-12-19 11:36:22 +0800973 *outPresentFence = -1;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800974 return;
975 }
976
977 ReturnData& data = found->second;
978
Chia-I Wu67e376d2016-12-19 11:36:22 +0800979 *outPresentFence = data.presentFence;
Chia-I Wucd8d7f02016-11-16 11:02:31 +0800980 data.presentFence = -1;
Chia-I Wuaab99f52016-10-05 12:59:58 +0800981}
982
983} // namespace Hwc2
984
985} // namespace android