blob: 09c62f0af22dc764ec9a0c3c25600e0ce1023ae4 [file] [log] [blame]
Chia-I Wu7f8d3962016-09-28 21:04:23 +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#define LOG_TAG "HwcPassthrough"
18
19#include <mutex>
20#include <type_traits>
21#include <unordered_map>
22#include <unordered_set>
23#include <utility>
24#include <vector>
25
26#include <hardware/gralloc.h>
27#include <hardware/gralloc1.h>
28#include <hardware/hwcomposer2.h>
29#include <log/log.h>
30
31#include "Hwc.h"
32
33namespace android {
34namespace hardware {
35namespace graphics {
36namespace composer {
37namespace V2_1 {
38namespace implementation {
39
40using android::hardware::graphics::allocator::V2_0::PixelFormat;
41
42namespace {
43
44class HandleImporter {
45public:
46 HandleImporter() : mInitialized(false) {}
47
48 bool initialize()
49 {
50 // allow only one client
51 if (mInitialized) {
52 return false;
53 }
54
55 if (!openGralloc()) {
56 return false;
57 }
58
59 mInitialized = true;
60 return true;
61 }
62
63 void cleanup()
64 {
65 if (!mInitialized) {
66 return;
67 }
68
69 closeGralloc();
70 mInitialized = false;
71 }
72
73 // In IComposer, any buffer_handle_t is owned by the caller and we need to
74 // make a clone for hwcomposer2. We also need to translate empty handle
75 // to nullptr. This function does that, in-place.
76 bool importBuffer(buffer_handle_t& handle)
77 {
78 if (!handle->numFds && !handle->numInts) {
79 handle = nullptr;
80 return true;
81 }
82
83 buffer_handle_t clone = cloneBuffer(handle);
84 if (!clone) {
85 return false;
86 }
87
88 handle = clone;
89 return true;
90 }
91
92 void freeBuffer(buffer_handle_t handle)
93 {
94 if (!handle) {
95 return;
96 }
97
98 releaseBuffer(handle);
99 }
100
101 bool importFence(const native_handle_t* handle, int& fd)
102 {
103 if (handle->numFds == 0) {
104 fd = -1;
105 } else if (handle->numFds == 1) {
106 fd = dup(handle->data[0]);
107 if (fd < 0) {
108 ALOGE("failed to dup fence fd %d", handle->data[0]);
109 return false;
110 }
111 } else {
112 ALOGE("invalid fence handle with %d file descriptors",
113 handle->numFds);
114 return false;
115 }
116
117 return true;
118 }
119
120 void closeFence(int fd)
121 {
122 if (fd >= 0) {
123 close(fd);
124 }
125 }
126
127private:
128 bool mInitialized;
129
130 // Some existing gralloc drivers do not support retaining more than once,
131 // when we are in passthrough mode.
132#ifdef BINDERIZED
133 bool openGralloc()
134 {
135 const hw_module_t* module;
136 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
137 if (err) {
138 ALOGE("failed to get gralloc module");
139 return false;
140 }
141
142 uint8_t major = (module->module_api_version >> 8) & 0xff;
143 if (major > 1) {
144 ALOGE("unknown gralloc module major version %d", major);
145 return false;
146 }
147
148 if (major == 1) {
149 err = gralloc1_open(module, &mDevice);
150 if (err) {
151 ALOGE("failed to open gralloc1 device");
152 return false;
153 }
154
155 mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>(
156 mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN));
157 mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
158 mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE));
159 if (!mRetain || !mRelease) {
160 ALOGE("invalid gralloc1 device");
161 gralloc1_close(mDevice);
162 return false;
163 }
164 } else {
165 mModule = reinterpret_cast<const gralloc_module_t*>(module);
166 }
167
168 return true;
169 }
170
171 void closeGralloc()
172 {
173 if (mDevice) {
174 gralloc1_close(mDevice);
175 }
176 }
177
178 buffer_handle_t cloneBuffer(buffer_handle_t handle)
179 {
180 native_handle_t* clone = native_handle_clone(handle);
181 if (!clone) {
182 ALOGE("failed to clone buffer %p", handle);
183 return nullptr;
184 }
185
186 bool err;
187 if (mDevice) {
188 err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE);
189 } else {
190 err = (mModule->registerBuffer(mModule, clone) != 0);
191 }
192
193 if (err) {
194 ALOGE("failed to retain/register buffer %p", clone);
195 native_handle_close(clone);
196 native_handle_delete(clone);
197 return nullptr;
198 }
199
200 return clone;
201 }
202
203 void releaseBuffer(buffer_handle_t handle)
204 {
205 if (mDevice) {
206 mRelease(mDevice, handle);
207 } else {
208 mModule->unregisterBuffer(mModule, handle);
209 native_handle_close(handle);
210 native_handle_delete(const_cast<native_handle_t*>(handle));
211 }
212 }
213
214 // gralloc1
215 gralloc1_device_t* mDevice;
216 GRALLOC1_PFN_RETAIN mRetain;
217 GRALLOC1_PFN_RELEASE mRelease;
218
219 // gralloc0
220 const gralloc_module_t* mModule;
221#else
222 bool openGralloc() { return true; }
223 void closeGralloc() {}
224 buffer_handle_t cloneBuffer(buffer_handle_t handle) { return handle; }
225 void releaseBuffer(buffer_handle_t) {}
226#endif
227};
228
229HandleImporter sHandleImporter;
230
231class BufferClone {
232public:
233 BufferClone() : mHandle(nullptr) {}
234
235 BufferClone(BufferClone&& other)
236 {
237 mHandle = other.mHandle;
238 other.mHandle = nullptr;
239 }
240
241 BufferClone(const BufferClone& other) = delete;
242 BufferClone& operator=(const BufferClone& other) = delete;
243
244 BufferClone& operator=(buffer_handle_t handle)
245 {
246 clear();
247 mHandle = handle;
248 return *this;
249 }
250
251 ~BufferClone()
252 {
253 clear();
254 }
255
256private:
257 void clear()
258 {
259 if (mHandle) {
260 sHandleImporter.freeBuffer(mHandle);
261 }
262 }
263
264 buffer_handle_t mHandle;
265};
266
267} // anonymous namespace
268
269class HwcHal : public IComposer {
270public:
271 HwcHal(const hw_module_t* module);
272 virtual ~HwcHal();
273
274 // IComposer interface
275 Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
276 Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
277 Return<void> registerCallback(const sp<IComposerCallback>& callback) override;
278 Return<uint32_t> getMaxVirtualDisplayCount() override;
279 Return<void> createVirtualDisplay(uint32_t width, uint32_t height,
280 PixelFormat formatHint, createVirtualDisplay_cb hidl_cb) override;
281 Return<Error> destroyVirtualDisplay(Display display) override;
282 Return<Error> acceptDisplayChanges(Display display) override;
283 Return<void> createLayer(Display display,
284 createLayer_cb hidl_cb) override;
285 Return<Error> destroyLayer(Display display, Layer layer) override;
286 Return<void> getActiveConfig(Display display,
287 getActiveConfig_cb hidl_cb) override;
288 Return<void> getChangedCompositionTypes(Display display,
289 getChangedCompositionTypes_cb hidl_cb) override;
290 Return<Error> getClientTargetSupport(Display display,
291 uint32_t width, uint32_t height,
292 PixelFormat format, Dataspace dataspace) override;
293 Return<void> getColorModes(Display display,
294 getColorModes_cb hidl_cb) override;
295 Return<void> getDisplayAttribute(Display display,
296 Config config, Attribute attribute,
297 getDisplayAttribute_cb hidl_cb) override;
298 Return<void> getDisplayConfigs(Display display,
299 getDisplayConfigs_cb hidl_cb) override;
300 Return<void> getDisplayName(Display display,
301 getDisplayName_cb hidl_cb) override;
302 Return<void> getDisplayRequests(Display display,
303 getDisplayRequests_cb hidl_cb) override;
304 Return<void> getDisplayType(Display display,
305 getDisplayType_cb hidl_cb) override;
306 Return<void> getDozeSupport(Display display,
307 getDozeSupport_cb hidl_cb) override;
308 Return<void> getHdrCapabilities(Display display,
309 getHdrCapabilities_cb hidl_cb) override;
310 Return<void> getReleaseFences(Display display,
311 getReleaseFences_cb hidl_cb) override;
312 Return<void> presentDisplay(Display display,
313 presentDisplay_cb hidl_cb) override;
314 Return<Error> setActiveConfig(Display display, Config config) override;
315 Return<Error> setClientTarget(Display display,
316 const native_handle_t* target,
317 const native_handle_t* acquireFence,
318 Dataspace dataspace, const hidl_vec<Rect>& damage) override;
319 Return<Error> setColorMode(Display display, ColorMode mode) override;
320 Return<Error> setColorTransform(Display display,
321 const hidl_vec<float>& matrix, ColorTransform hint) override;
322 Return<Error> setOutputBuffer(Display display,
323 const native_handle_t* buffer,
324 const native_handle_t* releaseFence) override;
325 Return<Error> setPowerMode(Display display, PowerMode mode) override;
326 Return<Error> setVsyncEnabled(Display display, Vsync enabled) override;
327 Return<void> validateDisplay(Display display,
328 validateDisplay_cb hidl_cb) override;
329 Return<Error> setCursorPosition(Display display,
330 Layer layer, int32_t x, int32_t y) override;
331 Return<Error> setLayerBuffer(Display display,
332 Layer layer, const native_handle_t* buffer,
333 const native_handle_t* acquireFence) override;
334 Return<Error> setLayerSurfaceDamage(Display display,
335 Layer layer, const hidl_vec<Rect>& damage) override;
336 Return<Error> setLayerBlendMode(Display display,
337 Layer layer, BlendMode mode) override;
338 Return<Error> setLayerColor(Display display,
339 Layer layer, const Color& color) override;
340 Return<Error> setLayerCompositionType(Display display,
341 Layer layer, Composition type) override;
342 Return<Error> setLayerDataspace(Display display,
343 Layer layer, Dataspace dataspace) override;
344 Return<Error> setLayerDisplayFrame(Display display,
345 Layer layer, const Rect& frame) override;
346 Return<Error> setLayerPlaneAlpha(Display display,
347 Layer layer, float alpha) override;
348 Return<Error> setLayerSidebandStream(Display display,
349 Layer layer, const native_handle_t* stream) override;
350 Return<Error> setLayerSourceCrop(Display display,
351 Layer layer, const FRect& crop) override;
352 Return<Error> setLayerTransform(Display display,
353 Layer layer, Transform transform) override;
354 Return<Error> setLayerVisibleRegion(Display display,
355 Layer layer, const hidl_vec<Rect>& visible) override;
356 Return<Error> setLayerZOrder(Display display,
357 Layer layer, uint32_t z) override;
358
359private:
360 void initCapabilities();
361
362 template<typename T>
363 void initDispatch(T& func, hwc2_function_descriptor_t desc);
364 void initDispatch();
365
366 bool hasCapability(Capability capability) const;
367
368 static void hotplugHook(hwc2_callback_data_t callbackData,
369 hwc2_display_t display, int32_t connected);
370 static void refreshHook(hwc2_callback_data_t callbackData,
371 hwc2_display_t display);
372 static void vsyncHook(hwc2_callback_data_t callbackData,
373 hwc2_display_t display, int64_t timestamp);
374
375 hwc2_device_t* mDevice;
376
377 std::unordered_set<Capability> mCapabilities;
378
379 struct {
380 HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges;
381 HWC2_PFN_CREATE_LAYER createLayer;
382 HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay;
383 HWC2_PFN_DESTROY_LAYER destroyLayer;
384 HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay;
385 HWC2_PFN_DUMP dump;
386 HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig;
387 HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes;
388 HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport;
389 HWC2_PFN_GET_COLOR_MODES getColorModes;
390 HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute;
391 HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs;
392 HWC2_PFN_GET_DISPLAY_NAME getDisplayName;
393 HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests;
394 HWC2_PFN_GET_DISPLAY_TYPE getDisplayType;
395 HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport;
396 HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities;
397 HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount;
398 HWC2_PFN_GET_RELEASE_FENCES getReleaseFences;
399 HWC2_PFN_PRESENT_DISPLAY presentDisplay;
400 HWC2_PFN_REGISTER_CALLBACK registerCallback;
401 HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig;
402 HWC2_PFN_SET_CLIENT_TARGET setClientTarget;
403 HWC2_PFN_SET_COLOR_MODE setColorMode;
404 HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform;
405 HWC2_PFN_SET_CURSOR_POSITION setCursorPosition;
406 HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode;
407 HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer;
408 HWC2_PFN_SET_LAYER_COLOR setLayerColor;
409 HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType;
410 HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace;
411 HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame;
412 HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha;
413 HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream;
414 HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop;
415 HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage;
416 HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform;
417 HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion;
418 HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder;
419 HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer;
420 HWC2_PFN_SET_POWER_MODE setPowerMode;
421 HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled;
422 HWC2_PFN_VALIDATE_DISPLAY validateDisplay;
423 } mDispatch;
424
425 // cloned buffers for a display
426 struct DisplayBuffers {
427 BufferClone ClientTarget;
428 BufferClone OutputBuffer;
429
430 std::unordered_map<Layer, BufferClone> LayerBuffers;
431 std::unordered_map<Layer, BufferClone> LayerSidebandStreams;
432 };
433
434 std::mutex mCallbackMutex;
435 sp<IComposerCallback> mCallback;
436
437 std::mutex mDisplayMutex;
438 std::unordered_map<Display, DisplayBuffers> mDisplays;
439};
440
441HwcHal::HwcHal(const hw_module_t* module)
442 : mDevice(nullptr), mDispatch()
443{
444 if (!sHandleImporter.initialize()) {
445 LOG_ALWAYS_FATAL("failed to initialize handle importer");
446 }
447
448 int status = hwc2_open(module, &mDevice);
449 if (status) {
450 LOG_ALWAYS_FATAL("failed to open hwcomposer2 device: %s",
451 strerror(-status));
452 }
453
454 initCapabilities();
455 initDispatch();
456}
457
458HwcHal::~HwcHal()
459{
460 hwc2_close(mDevice);
461 mDisplays.clear();
462 sHandleImporter.cleanup();
463}
464
465void HwcHal::initCapabilities()
466{
467 uint32_t count = 0;
468 mDevice->getCapabilities(mDevice, &count, nullptr);
469
470 std::vector<Capability> caps(count);
471 mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
472 std::underlying_type<Capability>::type*>(caps.data()));
473 caps.resize(count);
474
475 mCapabilities.insert(caps.cbegin(), caps.cend());
476}
477
478template<typename T>
479void HwcHal::initDispatch(T& func, hwc2_function_descriptor_t desc)
480{
481 auto pfn = mDevice->getFunction(mDevice, desc);
482 if (!pfn) {
483 LOG_ALWAYS_FATAL("failed to get hwcomposer2 function %d", desc);
484 }
485
486 func = reinterpret_cast<T>(pfn);
487}
488
489void HwcHal::initDispatch()
490{
491 initDispatch(mDispatch.acceptDisplayChanges,
492 HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES);
493 initDispatch(mDispatch.createLayer, HWC2_FUNCTION_CREATE_LAYER);
494 initDispatch(mDispatch.createVirtualDisplay,
495 HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY);
496 initDispatch(mDispatch.destroyLayer, HWC2_FUNCTION_DESTROY_LAYER);
497 initDispatch(mDispatch.destroyVirtualDisplay,
498 HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY);
499 initDispatch(mDispatch.dump, HWC2_FUNCTION_DUMP);
500 initDispatch(mDispatch.getActiveConfig, HWC2_FUNCTION_GET_ACTIVE_CONFIG);
501 initDispatch(mDispatch.getChangedCompositionTypes,
502 HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES);
503 initDispatch(mDispatch.getClientTargetSupport,
504 HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT);
505 initDispatch(mDispatch.getColorModes, HWC2_FUNCTION_GET_COLOR_MODES);
506 initDispatch(mDispatch.getDisplayAttribute,
507 HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE);
508 initDispatch(mDispatch.getDisplayConfigs,
509 HWC2_FUNCTION_GET_DISPLAY_CONFIGS);
510 initDispatch(mDispatch.getDisplayName, HWC2_FUNCTION_GET_DISPLAY_NAME);
511 initDispatch(mDispatch.getDisplayRequests,
512 HWC2_FUNCTION_GET_DISPLAY_REQUESTS);
513 initDispatch(mDispatch.getDisplayType, HWC2_FUNCTION_GET_DISPLAY_TYPE);
514 initDispatch(mDispatch.getDozeSupport, HWC2_FUNCTION_GET_DOZE_SUPPORT);
515 initDispatch(mDispatch.getHdrCapabilities,
516 HWC2_FUNCTION_GET_HDR_CAPABILITIES);
517 initDispatch(mDispatch.getMaxVirtualDisplayCount,
518 HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT);
519 initDispatch(mDispatch.getReleaseFences,
520 HWC2_FUNCTION_GET_RELEASE_FENCES);
521 initDispatch(mDispatch.presentDisplay, HWC2_FUNCTION_PRESENT_DISPLAY);
522 initDispatch(mDispatch.registerCallback, HWC2_FUNCTION_REGISTER_CALLBACK);
523 initDispatch(mDispatch.setActiveConfig, HWC2_FUNCTION_SET_ACTIVE_CONFIG);
524 initDispatch(mDispatch.setClientTarget, HWC2_FUNCTION_SET_CLIENT_TARGET);
525 initDispatch(mDispatch.setColorMode, HWC2_FUNCTION_SET_COLOR_MODE);
526 initDispatch(mDispatch.setColorTransform,
527 HWC2_FUNCTION_SET_COLOR_TRANSFORM);
528 initDispatch(mDispatch.setCursorPosition,
529 HWC2_FUNCTION_SET_CURSOR_POSITION);
530 initDispatch(mDispatch.setLayerBlendMode,
531 HWC2_FUNCTION_SET_LAYER_BLEND_MODE);
532 initDispatch(mDispatch.setLayerBuffer, HWC2_FUNCTION_SET_LAYER_BUFFER);
533 initDispatch(mDispatch.setLayerColor, HWC2_FUNCTION_SET_LAYER_COLOR);
534 initDispatch(mDispatch.setLayerCompositionType,
535 HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE);
536 initDispatch(mDispatch.setLayerDataspace,
537 HWC2_FUNCTION_SET_LAYER_DATASPACE);
538 initDispatch(mDispatch.setLayerDisplayFrame,
539 HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME);
540 initDispatch(mDispatch.setLayerPlaneAlpha,
541 HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA);
542
543 if (hasCapability(Capability::SIDEBAND_STREAM)) {
544 initDispatch(mDispatch.setLayerSidebandStream,
545 HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM);
546 }
547
548 initDispatch(mDispatch.setLayerSourceCrop,
549 HWC2_FUNCTION_SET_LAYER_SOURCE_CROP);
550 initDispatch(mDispatch.setLayerSurfaceDamage,
551 HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE);
552 initDispatch(mDispatch.setLayerTransform,
553 HWC2_FUNCTION_SET_LAYER_TRANSFORM);
554 initDispatch(mDispatch.setLayerVisibleRegion,
555 HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION);
556 initDispatch(mDispatch.setLayerZOrder, HWC2_FUNCTION_SET_LAYER_Z_ORDER);
557 initDispatch(mDispatch.setOutputBuffer, HWC2_FUNCTION_SET_OUTPUT_BUFFER);
558 initDispatch(mDispatch.setPowerMode, HWC2_FUNCTION_SET_POWER_MODE);
559 initDispatch(mDispatch.setVsyncEnabled, HWC2_FUNCTION_SET_VSYNC_ENABLED);
560 initDispatch(mDispatch.validateDisplay, HWC2_FUNCTION_VALIDATE_DISPLAY);
561}
562
563bool HwcHal::hasCapability(Capability capability) const
564{
565 return (mCapabilities.count(capability) > 0);
566}
567
568Return<void> HwcHal::getCapabilities(getCapabilities_cb hidl_cb)
569{
570 std::vector<Capability> caps(
571 mCapabilities.cbegin(), mCapabilities.cend());
572
573 hidl_vec<Capability> caps_reply;
574 caps_reply.setToExternal(caps.data(), caps.size());
575 hidl_cb(caps_reply);
576
577 return Void();
578}
579
580Return<void> HwcHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
581{
582 uint32_t len;
583 mDispatch.dump(mDevice, &len, nullptr);
584
585 std::vector<char> buf(len + 1);
586 mDispatch.dump(mDevice, &len, buf.data());
587 buf.resize(len + 1);
588 buf[len] = '\0';
589
590 hidl_string buf_reply;
591 buf_reply.setToExternal(buf.data(), len);
592 hidl_cb(buf_reply);
593
594 return Void();
595}
596
597void HwcHal::hotplugHook(hwc2_callback_data_t callbackData,
598 hwc2_display_t display, int32_t connected)
599{
600 auto hal = reinterpret_cast<HwcHal*>(callbackData);
601
602 {
603 std::lock_guard<std::mutex> lock(hal->mDisplayMutex);
604
605 if (connected == HWC2_CONNECTION_CONNECTED) {
606 hal->mDisplays.emplace(display, DisplayBuffers());
607 } else if (connected == HWC2_CONNECTION_DISCONNECTED) {
608 hal->mDisplays.erase(display);
609 }
610 }
611
612 hal->mCallback->onHotplug(display,
613 static_cast<IComposerCallback::Connection>(connected));
614}
615
616void HwcHal::refreshHook(hwc2_callback_data_t callbackData,
617 hwc2_display_t display)
618{
619 auto hal = reinterpret_cast<HwcHal*>(callbackData);
620 hal->mCallback->onRefresh(display);
621}
622
623void HwcHal::vsyncHook(hwc2_callback_data_t callbackData,
624 hwc2_display_t display, int64_t timestamp)
625{
626 auto hal = reinterpret_cast<HwcHal*>(callbackData);
627 hal->mCallback->onVsync(display, timestamp);
628}
629
630Return<void> HwcHal::registerCallback(const sp<IComposerCallback>& callback)
631{
632 std::lock_guard<std::mutex> lock(mCallbackMutex);
633
634 mCallback = callback;
635
636 mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
637 reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
638 mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
639 reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
640 mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
641 reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
642
643 return Void();
644}
645
646Return<uint32_t> HwcHal::getMaxVirtualDisplayCount()
647{
648 return mDispatch.getMaxVirtualDisplayCount(mDevice);
649}
650
651Return<void> HwcHal::createVirtualDisplay(uint32_t width, uint32_t height,
652 PixelFormat formatHint, createVirtualDisplay_cb hidl_cb)
653{
654 int32_t format = static_cast<int32_t>(formatHint);
655 hwc2_display_t display;
656 auto error = mDispatch.createVirtualDisplay(mDevice, width, height,
657 &format, &display);
658 if (error == HWC2_ERROR_NONE) {
659 std::lock_guard<std::mutex> lock(mDisplayMutex);
660
661 mDisplays.emplace(display, DisplayBuffers());
662 }
663
664 hidl_cb(static_cast<Error>(error), display,
665 static_cast<PixelFormat>(format));
666
667 return Void();
668}
669
670Return<Error> HwcHal::destroyVirtualDisplay(Display display)
671{
672 auto error = mDispatch.destroyVirtualDisplay(mDevice, display);
673 if (error == HWC2_ERROR_NONE) {
674 std::lock_guard<std::mutex> lock(mDisplayMutex);
675
676 mDisplays.erase(display);
677 }
678
679 return static_cast<Error>(error);
680}
681
682Return<Error> HwcHal::acceptDisplayChanges(Display display)
683{
684 auto error = mDispatch.acceptDisplayChanges(mDevice, display);
685 return static_cast<Error>(error);
686}
687
688Return<void> HwcHal::createLayer(Display display, createLayer_cb hidl_cb)
689{
690 hwc2_layer_t layer;
691 auto error = mDispatch.createLayer(mDevice, display, &layer);
692
693 hidl_cb(static_cast<Error>(error), layer);
694
695 return Void();
696}
697
698Return<Error> HwcHal::destroyLayer(Display display, Layer layer)
699{
700 auto error = mDispatch.destroyLayer(mDevice, display, layer);
701 return static_cast<Error>(error);
702}
703
704Return<void> HwcHal::getActiveConfig(Display display,
705 getActiveConfig_cb hidl_cb)
706{
707 hwc2_config_t config;
708 auto error = mDispatch.getActiveConfig(mDevice, display, &config);
709
710 hidl_cb(static_cast<Error>(error), config);
711
712 return Void();
713}
714
715Return<void> HwcHal::getChangedCompositionTypes(Display display,
716 getChangedCompositionTypes_cb hidl_cb)
717{
718 uint32_t count = 0;
719 auto error = mDispatch.getChangedCompositionTypes(mDevice, display,
720 &count, nullptr, nullptr);
721 if (error != HWC2_ERROR_NONE) {
722 count = 0;
723 }
724
725 std::vector<hwc2_layer_t> layers(count);
726 std::vector<Composition> types(count);
727 error = mDispatch.getChangedCompositionTypes(mDevice, display,
728 &count, layers.data(),
729 reinterpret_cast<std::underlying_type<Composition>::type*>(
730 types.data()));
731 if (error != HWC2_ERROR_NONE) {
732 count = 0;
733 }
734 layers.resize(count);
735 types.resize(count);
736
737 hidl_vec<Layer> layers_reply;
738 layers_reply.setToExternal(layers.data(), layers.size());
739
740 hidl_vec<Composition> types_reply;
741 types_reply.setToExternal(types.data(), types.size());
742
743 hidl_cb(static_cast<Error>(error), layers_reply, types_reply);
744
745 return Void();
746}
747
748Return<Error> HwcHal::getClientTargetSupport(Display display,
749 uint32_t width, uint32_t height,
750 PixelFormat format, Dataspace dataspace)
751{
752 auto error = mDispatch.getClientTargetSupport(mDevice, display,
753 width, height, static_cast<int32_t>(format),
754 static_cast<int32_t>(dataspace));
755 return static_cast<Error>(error);
756}
757
758Return<void> HwcHal::getColorModes(Display display, getColorModes_cb hidl_cb)
759{
760 uint32_t count = 0;
761 auto error = mDispatch.getColorModes(mDevice, display, &count, nullptr);
762 if (error != HWC2_ERROR_NONE) {
763 count = 0;
764 }
765
766 std::vector<ColorMode> modes(count);
767 error = mDispatch.getColorModes(mDevice, display, &count,
768 reinterpret_cast<std::underlying_type<ColorMode>::type*>(
769 modes.data()));
770 if (error != HWC2_ERROR_NONE) {
771 count = 0;
772 }
773 modes.resize(count);
774
775 hidl_vec<ColorMode> modes_reply;
776 modes_reply.setToExternal(modes.data(), modes.size());
777 hidl_cb(static_cast<Error>(error), modes_reply);
778
779 return Void();
780}
781
782Return<void> HwcHal::getDisplayAttribute(Display display,
783 Config config, Attribute attribute,
784 getDisplayAttribute_cb hidl_cb)
785{
786 int32_t value;
787 auto error = mDispatch.getDisplayAttribute(mDevice, display, config,
788 static_cast<int32_t>(attribute), &value);
789
790 hidl_cb(static_cast<Error>(error), value);
791
792 return Void();
793}
794
795Return<void> HwcHal::getDisplayConfigs(Display display,
796 getDisplayConfigs_cb hidl_cb)
797{
798 uint32_t count = 0;
799 auto error = mDispatch.getDisplayConfigs(mDevice, display,
800 &count, nullptr);
801 if (error != HWC2_ERROR_NONE) {
802 count = 0;
803 }
804
805 std::vector<hwc2_config_t> configs(count);
806 error = mDispatch.getDisplayConfigs(mDevice, display,
807 &count, configs.data());
808 if (error != HWC2_ERROR_NONE) {
809 count = 0;
810 }
811 configs.resize(count);
812
813 hidl_vec<Config> configs_reply;
814 configs_reply.setToExternal(configs.data(), configs.size());
815 hidl_cb(static_cast<Error>(error), configs_reply);
816
817 return Void();
818}
819
820Return<void> HwcHal::getDisplayName(Display display,
821 getDisplayName_cb hidl_cb)
822{
823 uint32_t count = 0;
824 auto error = mDispatch.getDisplayName(mDevice, display, &count, nullptr);
825 if (error != HWC2_ERROR_NONE) {
826 count = 0;
827 }
828
829 std::vector<char> name(count + 1);
830 error = mDispatch.getDisplayName(mDevice, display, &count, name.data());
831 if (error != HWC2_ERROR_NONE) {
832 count = 0;
833 }
834 name.resize(count + 1);
835 name[count] = '\0';
836
837 hidl_string name_reply;
838 name_reply.setToExternal(name.data(), count);
839 hidl_cb(static_cast<Error>(error), name_reply);
840
841 return Void();
842}
843
844Return<void> HwcHal::getDisplayRequests(Display display,
845 getDisplayRequests_cb hidl_cb)
846{
847 int32_t display_reqs;
848 uint32_t count = 0;
849 auto error = mDispatch.getDisplayRequests(mDevice, display,
850 &display_reqs, &count, nullptr, nullptr);
851 if (error != HWC2_ERROR_NONE) {
852 count = 0;
853 }
854
855 std::vector<hwc2_layer_t> layers(count);
856 std::vector<int32_t> layer_reqs(count);
857 error = mDispatch.getDisplayRequests(mDevice, display,
858 &display_reqs, &count, layers.data(), layer_reqs.data());
859 if (error != HWC2_ERROR_NONE) {
860 count = 0;
861 }
862 layers.resize(count);
863 layer_reqs.resize(count);
864
865 hidl_vec<Layer> layers_reply;
866 layers_reply.setToExternal(layers.data(), layers.size());
867
868 hidl_vec<uint32_t> layer_reqs_reply;
869 layer_reqs_reply.setToExternal(
870 reinterpret_cast<uint32_t*>(layer_reqs.data()),
871 layer_reqs.size());
872
873 hidl_cb(static_cast<Error>(error), display_reqs,
874 layers_reply, layer_reqs_reply);
875
876 return Void();
877}
878
879Return<void> HwcHal::getDisplayType(Display display,
880 getDisplayType_cb hidl_cb)
881{
882 int32_t type;
883 auto error = mDispatch.getDisplayType(mDevice, display, &type);
884
885 hidl_cb(static_cast<Error>(error), static_cast<DisplayType>(type));
886
887 return Void();
888}
889
890Return<void> HwcHal::getDozeSupport(Display display,
891 getDozeSupport_cb hidl_cb)
892{
893 int32_t support;
894 auto error = mDispatch.getDozeSupport(mDevice, display, &support);
895
896 hidl_cb(static_cast<Error>(error), support);
897
898 return Void();
899}
900
901Return<void> HwcHal::getHdrCapabilities(Display display,
902 getHdrCapabilities_cb hidl_cb)
903{
904 float max_lumi, max_avg_lumi, min_lumi;
905 uint32_t count = 0;
906 auto error = mDispatch.getHdrCapabilities(mDevice, display,
907 &count, nullptr, &max_lumi, &max_avg_lumi, &min_lumi);
908 if (error != HWC2_ERROR_NONE) {
909 count = 0;
910 }
911
912 std::vector<Hdr> types(count);
913 error = mDispatch.getHdrCapabilities(mDevice, display, &count,
914 reinterpret_cast<std::underlying_type<Hdr>::type*>(types.data()),
915 &max_lumi, &max_avg_lumi, &min_lumi);
916 if (error != HWC2_ERROR_NONE) {
917 count = 0;
918 }
919 types.resize(count);
920
921 hidl_vec<Hdr> types_reply;
922 types_reply.setToExternal(types.data(), types.size());
923 hidl_cb(static_cast<Error>(error), types_reply,
924 max_lumi, max_avg_lumi, min_lumi);
925
926 return Void();
927}
928
929Return<void> HwcHal::getReleaseFences(Display display,
930 getReleaseFences_cb hidl_cb)
931{
932 uint32_t count = 0;
933 auto error = mDispatch.getReleaseFences(mDevice, display,
934 &count, nullptr, nullptr);
935 if (error != HWC2_ERROR_NONE) {
936 count = 0;
937 }
938
939 std::vector<hwc2_layer_t> layers(count);
940 std::vector<int32_t> fences(count);
941 error = mDispatch.getReleaseFences(mDevice, display,
942 &count, layers.data(), fences.data());
943 if (error != HWC2_ERROR_NONE) {
944 count = 0;
945 }
946 layers.resize(count);
947 fences.resize(count);
948
949 // filter out layers with release fence -1
950 std::vector<hwc2_layer_t> filtered_layers;
951 std::vector<int> filtered_fences;
952 for (size_t i = 0; i < layers.size(); i++) {
953 if (fences[i] >= 0) {
954 filtered_layers.push_back(layers[i]);
955 filtered_fences.push_back(fences[i]);
956 }
957 }
958
959 hidl_vec<Layer> layers_reply;
960 native_handle_t* fences_reply =
961 native_handle_create(filtered_fences.size(), 0);
962 if (fences_reply) {
963 layers_reply.setToExternal(filtered_layers.data(),
964 filtered_layers.size());
965 memcpy(fences_reply->data, filtered_fences.data(),
966 sizeof(int) * filtered_fences.size());
967
968 hidl_cb(static_cast<Error>(error), layers_reply, fences_reply);
969
970 native_handle_close(fences_reply);
971 native_handle_delete(fences_reply);
972 } else {
973 NATIVE_HANDLE_DECLARE_STORAGE(fences_storage, 0, 0);
974 fences_reply = native_handle_init(fences_storage, 0, 0);
975
976 hidl_cb(Error::NO_RESOURCES, layers_reply, fences_reply);
977
978 for (auto fence : filtered_fences) {
979 close(fence);
980 }
981 }
982
983 return Void();
984}
985
986Return<void> HwcHal::presentDisplay(Display display,
987 presentDisplay_cb hidl_cb)
988{
989 int32_t fence = -1;
990 auto error = mDispatch.presentDisplay(mDevice, display, &fence);
991
992 NATIVE_HANDLE_DECLARE_STORAGE(fence_storage, 1, 0);
993 native_handle_t* fence_reply;
994 if (fence >= 0) {
995 fence_reply = native_handle_init(fence_storage, 1, 0);
996 fence_reply->data[0] = fence;
997 } else {
998 fence_reply = native_handle_init(fence_storage, 0, 0);
999 }
1000
1001 hidl_cb(static_cast<Error>(error), fence_reply);
1002
1003 if (fence >= 0) {
1004 close(fence);
1005 }
1006
1007 return Void();
1008}
1009
1010Return<Error> HwcHal::setActiveConfig(Display display, Config config)
1011{
1012 auto error = mDispatch.setActiveConfig(mDevice, display, config);
1013 return static_cast<Error>(error);
1014}
1015
1016Return<Error> HwcHal::setClientTarget(Display display,
1017 const native_handle_t* target,
1018 const native_handle_t* acquireFence,
1019 Dataspace dataspace, const hidl_vec<Rect>& damage)
1020{
1021 if (!sHandleImporter.importBuffer(target)) {
1022 return Error::NO_RESOURCES;
1023 }
1024
1025 int32_t fence;
1026 if (!sHandleImporter.importFence(acquireFence, fence)) {
1027 sHandleImporter.freeBuffer(target);
1028 return Error::NO_RESOURCES;
1029 }
1030
1031 hwc_region_t damage_region = { damage.size(),
1032 reinterpret_cast<const hwc_rect_t*>(&damage[0]) };
1033
1034 int32_t error = mDispatch.setClientTarget(mDevice, display,
1035 target, fence, static_cast<int32_t>(dataspace),
1036 damage_region);
1037 if (error == HWC2_ERROR_NONE) {
1038 std::lock_guard<std::mutex> lock(mDisplayMutex);
1039
1040 auto dpy = mDisplays.find(display);
1041 dpy->second.ClientTarget = target;
1042 } else {
1043 sHandleImporter.freeBuffer(target);
1044 sHandleImporter.closeFence(fence);
1045 }
1046
1047 return static_cast<Error>(error);
1048}
1049
1050Return<Error> HwcHal::setColorMode(Display display, ColorMode mode)
1051{
1052 auto error = mDispatch.setColorMode(mDevice, display,
1053 static_cast<int32_t>(mode));
1054 return static_cast<Error>(error);
1055}
1056
1057Return<Error> HwcHal::setColorTransform(Display display,
1058 const hidl_vec<float>& matrix, ColorTransform hint)
1059{
1060 auto error = mDispatch.setColorTransform(mDevice, display,
1061 &matrix[0], static_cast<int32_t>(hint));
1062 return static_cast<Error>(error);
1063}
1064
1065Return<Error> HwcHal::setOutputBuffer(Display display,
1066 const native_handle_t* buffer,
1067 const native_handle_t* releaseFence)
1068{
1069 if (!sHandleImporter.importBuffer(buffer)) {
1070 return Error::NO_RESOURCES;
1071 }
1072
1073 int32_t fence;
1074 if (!sHandleImporter.importFence(releaseFence, fence)) {
1075 sHandleImporter.freeBuffer(buffer);
1076 return Error::NO_RESOURCES;
1077 }
1078
1079 int32_t error = mDispatch.setOutputBuffer(mDevice,
1080 display, buffer, fence);
1081 if (error == HWC2_ERROR_NONE) {
1082 std::lock_guard<std::mutex> lock(mDisplayMutex);
1083
1084 auto dpy = mDisplays.find(display);
1085 dpy->second.OutputBuffer = buffer;
1086 } else {
1087 sHandleImporter.freeBuffer(buffer);
1088 }
1089
1090 // unlike in setClientTarget, fence is owned by us and is always closed
1091 sHandleImporter.closeFence(fence);
1092
1093 return static_cast<Error>(error);
1094}
1095
1096Return<Error> HwcHal::setPowerMode(Display display, PowerMode mode)
1097{
1098 auto error = mDispatch.setPowerMode(mDevice, display,
1099 static_cast<int32_t>(mode));
1100 return static_cast<Error>(error);
1101}
1102
1103Return<Error> HwcHal::setVsyncEnabled(Display display,
1104 Vsync enabled)
1105{
1106 auto error = mDispatch.setVsyncEnabled(mDevice, display,
1107 static_cast<int32_t>(enabled));
1108 return static_cast<Error>(error);
1109}
1110
1111Return<void> HwcHal::validateDisplay(Display display,
1112 validateDisplay_cb hidl_cb)
1113{
1114 uint32_t types_count = 0;
1115 uint32_t reqs_count = 0;
1116 auto error = mDispatch.validateDisplay(mDevice, display,
1117 &types_count, &reqs_count);
1118
1119 hidl_cb(static_cast<Error>(error), types_count, reqs_count);
1120
1121 return Void();
1122}
1123
1124Return<Error> HwcHal::setCursorPosition(Display display,
1125 Layer layer, int32_t x, int32_t y)
1126{
1127 auto error = mDispatch.setCursorPosition(mDevice, display, layer, x, y);
1128 return static_cast<Error>(error);
1129}
1130
1131Return<Error> HwcHal::setLayerBuffer(Display display,
1132 Layer layer, const native_handle_t* buffer,
1133 const native_handle_t* acquireFence)
1134{
1135 if (!sHandleImporter.importBuffer(buffer)) {
1136 return Error::NO_RESOURCES;
1137 }
1138
1139 int32_t fence;
1140 if (!sHandleImporter.importFence(acquireFence, fence)) {
1141 sHandleImporter.freeBuffer(buffer);
1142 return Error::NO_RESOURCES;
1143 }
1144
1145 int32_t error = mDispatch.setLayerBuffer(mDevice,
1146 display, layer, buffer, fence);
1147 if (error == HWC2_ERROR_NONE) {
1148 std::lock_guard<std::mutex> lock(mDisplayMutex);
1149
1150 auto dpy = mDisplays.find(display);
1151 dpy->second.LayerBuffers[layer] = buffer;
1152 } else {
1153 sHandleImporter.freeBuffer(buffer);
1154 sHandleImporter.closeFence(fence);
1155 }
1156
1157 return static_cast<Error>(error);
1158}
1159
1160Return<Error> HwcHal::setLayerSurfaceDamage(Display display,
1161 Layer layer, const hidl_vec<Rect>& damage)
1162{
1163 hwc_region_t damage_region = { damage.size(),
1164 reinterpret_cast<const hwc_rect_t*>(&damage[0]) };
1165
1166 auto error = mDispatch.setLayerSurfaceDamage(mDevice, display, layer,
1167 damage_region);
1168 return static_cast<Error>(error);
1169}
1170
1171Return<Error> HwcHal::setLayerBlendMode(Display display,
1172 Layer layer, BlendMode mode)
1173{
1174 auto error = mDispatch.setLayerBlendMode(mDevice, display, layer,
1175 static_cast<int32_t>(mode));
1176 return static_cast<Error>(error);
1177}
1178
1179Return<Error> HwcHal::setLayerColor(Display display,
1180 Layer layer, const Color& color)
1181{
1182 hwc_color_t hwc_color{color.r, color.g, color.b, color.a};
1183 auto error = mDispatch.setLayerColor(mDevice, display, layer, hwc_color);
1184 return static_cast<Error>(error);
1185}
1186
1187Return<Error> HwcHal::setLayerCompositionType(Display display,
1188 Layer layer, Composition type)
1189{
1190 auto error = mDispatch.setLayerCompositionType(mDevice, display, layer,
1191 static_cast<int32_t>(type));
1192 return static_cast<Error>(error);
1193}
1194
1195Return<Error> HwcHal::setLayerDataspace(Display display,
1196 Layer layer, Dataspace dataspace)
1197{
1198 auto error = mDispatch.setLayerDataspace(mDevice, display, layer,
1199 static_cast<int32_t>(dataspace));
1200 return static_cast<Error>(error);
1201}
1202
1203Return<Error> HwcHal::setLayerDisplayFrame(Display display,
1204 Layer layer, const Rect& frame)
1205{
1206 hwc_rect_t hwc_frame{frame.left, frame.top, frame.right, frame.bottom};
1207 auto error = mDispatch.setLayerDisplayFrame(mDevice, display, layer,
1208 hwc_frame);
1209 return static_cast<Error>(error);
1210}
1211
1212Return<Error> HwcHal::setLayerPlaneAlpha(Display display,
1213 Layer layer, float alpha)
1214{
1215 auto error = mDispatch.setLayerPlaneAlpha(mDevice, display, layer, alpha);
1216 return static_cast<Error>(error);
1217}
1218
1219Return<Error> HwcHal::setLayerSidebandStream(Display display,
1220 Layer layer, const native_handle_t* stream)
1221{
1222 if (!sHandleImporter.importBuffer(stream)) {
1223 return Error::NO_RESOURCES;
1224 }
1225
1226 int32_t error = mDispatch.setLayerSidebandStream(mDevice,
1227 display, layer, stream);
1228 if (error == HWC2_ERROR_NONE) {
1229 std::lock_guard<std::mutex> lock(mDisplayMutex);
1230
1231 auto dpy = mDisplays.find(display);
1232 dpy->second.LayerSidebandStreams[layer] = stream;
1233 } else {
1234 sHandleImporter.freeBuffer(stream);
1235 }
1236
1237 return static_cast<Error>(error);
1238}
1239
1240Return<Error> HwcHal::setLayerSourceCrop(Display display,
1241 Layer layer, const FRect& crop)
1242{
1243 hwc_frect_t hwc_crop{crop.left, crop.top, crop.right, crop.bottom};
1244 auto error = mDispatch.setLayerSourceCrop(mDevice, display, layer,
1245 hwc_crop);
1246 return static_cast<Error>(error);
1247}
1248
1249Return<Error> HwcHal::setLayerTransform(Display display,
1250 Layer layer, Transform transform)
1251{
1252 auto error = mDispatch.setLayerTransform(mDevice, display, layer,
1253 static_cast<int32_t>(transform));
1254 return static_cast<Error>(error);
1255}
1256
1257Return<Error> HwcHal::setLayerVisibleRegion(Display display,
1258 Layer layer, const hidl_vec<Rect>& visible)
1259{
1260 hwc_region_t visible_region = { visible.size(),
1261 reinterpret_cast<const hwc_rect_t*>(&visible[0]) };
1262
1263 auto error = mDispatch.setLayerVisibleRegion(mDevice, display, layer,
1264 visible_region);
1265 return static_cast<Error>(error);
1266}
1267
1268Return<Error> HwcHal::setLayerZOrder(Display display,
1269 Layer layer, uint32_t z)
1270{
1271 auto error = mDispatch.setLayerZOrder(mDevice, display, layer, z);
1272 return static_cast<Error>(error);
1273}
1274
1275IComposer* HIDL_FETCH_IComposer(const char*)
1276{
1277 const hw_module_t* module;
1278 int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
1279 if (err) {
1280 ALOGE("failed to get hwcomposer module");
1281 return nullptr;
1282 }
1283
1284 return new HwcHal(module);
1285}
1286
1287} // namespace implementation
1288} // namespace V2_1
1289} // namespace composer
1290} // namespace graphics
1291} // namespace hardware
1292} // namespace android