1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <hdi_session.h>
17 #include <cerrno>
18 #include <mutex>
19 #include "display_common.h"
20 #include "display_device.h"
21 #include "display_layer.h"
22 #include "hdi_netlink_monitor.h"
23 
24 namespace OHOS {
25 namespace HDI {
26 namespace DISPLAY {
GetInstance()27 HdiSession &HdiSession::GetInstance()
28 {
29     static HdiSession instance;
30     static std::once_flag once;
31     std::call_once(once, [&]() { instance.Init(); });
32     return instance;
33 }
34 
Init()35 void HdiSession::Init()
36 {
37     DISPLAY_DEBUGLOG();
38     mHdiDevices = HdiDeviceInterface::DiscoveryDevice();
39     DISPLAY_DEBUGLOG("devices size %{public}zd", mHdiDevices.size());
40     mHdiDisplays.clear();
41     for (auto device : mHdiDevices) {
42         auto displays = device->DiscoveryDisplay();
43         /* Register the connectors instead of display device.
44          * There are several connectors in one display device
45          * in rockchip platform.
46          */
47         for (auto display : displays) {
48             mHdiDisplays[display.first] = display.second;
49         }
50     }
51     mNetLinkMonitor = std::make_shared<HdiNetLinkMonitor>();
52     mNetLinkMonitor->Init();
53 }
54 
HandleHotplug(bool plugIn)55 void HdiSession::HandleHotplug(bool plugIn)
56 {
57     for (auto device : mHdiDevices) {
58         for (auto displayMap : mHdiDisplays) {
59             auto display = displayMap.second;
60             auto isSuccess = device->HandleHotplug(display->GetId(), plugIn);
61             if (isSuccess == true) {
62                 DoHotPlugCallback(display->GetId(), plugIn);
63             }
64         }
65     }
66 }
67 
RegHotPlugCallback(HotPlugCallback callback, void *data)68 int32_t HdiSession::RegHotPlugCallback(HotPlugCallback callback, void *data)
69 {
70     DISPLAY_CHK_RETURN((callback == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("the callback is nullptr"));
71     mHotPlugCallBacks.emplace(callback, data);
72     for (auto displayMap : mHdiDisplays) {
73         auto display = displayMap.second;
74         if (display->IsConnected()) {
75             DoHotPlugCallback(display->GetId(), true);
76         }
77     }
78     return DISPLAY_SUCCESS;
79 }
80 
DoHotPlugCallback(uint32_t devId, bool connect)81 void HdiSession::DoHotPlugCallback(uint32_t devId, bool connect)
82 {
83     DISPLAY_DEBUGLOG();
84     for (const auto &callback : mHotPlugCallBacks) {
85         callback.first(devId, connect, callback.second);
86     }
87 }
88 } // OHOS
89 } // HDI
90 } // DISPLAY
91 
92 using namespace OHOS::HDI::DISPLAY;
RegHotPlugCallback(HotPlugCallback callback, void *data)93 static int32_t RegHotPlugCallback(HotPlugCallback callback, void *data)
94 {
95     DISPLAY_DEBUGLOG();
96     HdiSession::GetInstance().RegHotPlugCallback(callback, data);
97     return DISPLAY_SUCCESS;
98 }
99 
GetDisplayCapability(uint32_t devId, DisplayCapability *info)100 static int32_t GetDisplayCapability(uint32_t devId, DisplayCapability *info)
101 {
102     DISPLAY_DEBUGLOG();
103     DISPLAY_CHK_RETURN(info == nullptr, DISPLAY_NULL_PTR, DISPLAY_LOGE("info is nullptr"));
104     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayCapability, info);
105 }
106 
GetDisplaySupportedModes(uint32_t devId, uint32_t *num, DisplayModeInfo *modes)107 static int32_t GetDisplaySupportedModes(uint32_t devId, uint32_t *num, DisplayModeInfo *modes)
108 {
109     DISPLAY_DEBUGLOG();
110     DISPLAY_CHK_RETURN(num == nullptr, DISPLAY_NULL_PTR, DISPLAY_LOGE("num is nullptr"));
111     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplaySupportedModes, num, modes);
112 }
113 
GetDisplayMode(uint32_t devId, uint32_t *mode)114 static int32_t GetDisplayMode(uint32_t devId, uint32_t *mode)
115 {
116     DISPLAY_DEBUGLOG();
117     DISPLAY_CHK_RETURN((mode == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("mode is nullptr"));
118     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayMode, mode);
119 }
120 
SetDisplayMode(uint32_t devId, uint32_t mode)121 static int32_t SetDisplayMode(uint32_t devId, uint32_t mode)
122 {
123     DISPLAY_DEBUGLOG();
124     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayMode, mode);
125 }
126 
GetDisplayPowerStatus(uint32_t devId, DispPowerStatus *status)127 static int32_t GetDisplayPowerStatus(uint32_t devId, DispPowerStatus *status)
128 {
129     DISPLAY_DEBUGLOG();
130     DISPLAY_CHK_RETURN((status == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("status is nullptr"));
131     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayPowerStatus, status);
132 }
133 
SetDisplayPowerStatus(uint32_t devId, DispPowerStatus status)134 static int32_t SetDisplayPowerStatus(uint32_t devId, DispPowerStatus status)
135 {
136     DISPLAY_DEBUGLOG();
137     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayPowerStatus, status);
138 }
139 
GetDisplayBacklight(uint32_t devId, uint32_t *value)140 static int32_t GetDisplayBacklight(uint32_t devId, uint32_t *value)
141 {
142     DISPLAY_DEBUGLOG();
143     DISPLAY_CHK_RETURN((value == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("value is nullptr"));
144     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayBacklight, value);
145 }
146 
SetDisplayBacklight(uint32_t devId, uint32_t value)147 static int32_t SetDisplayBacklight(uint32_t devId, uint32_t value)
148 {
149     DISPLAY_DEBUGLOG();
150     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayBacklight, value);
151 }
152 
GetDisplayProperty(uint32_t devId, uint32_t id, uint64_t *value)153 static int32_t GetDisplayProperty(uint32_t devId, uint32_t id, uint64_t *value)
154 {
155     DISPLAY_DEBUGLOG();
156     (void)id;
157     DISPLAY_CHK_RETURN((value == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("value is nullptr"));
158     return DISPLAY_NOT_SUPPORT;
159 }
160 
SetDisplayProperty(uint32_t devId, uint32_t id, uint64_t value)161 static int32_t SetDisplayProperty(uint32_t devId, uint32_t id, uint64_t value)
162 {
163     DISPLAY_DEBUGLOG();
164     (void)id;
165     return DISPLAY_NOT_SUPPORT;
166 }
167 
PrepareDisplayLayers(uint32_t devId, bool *needFlushFb)168 static int32_t PrepareDisplayLayers(uint32_t devId, bool *needFlushFb)
169 {
170     DISPLAY_DEBUGLOG();
171     DISPLAY_CHK_RETURN((needFlushFb == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("needFlushFb is nullptr"));
172     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::PrepareDisplayLayers, needFlushFb);
173 }
174 
GetDisplayCompChange(uint32_t devId, uint32_t *num, uint32_t *layers, int32_t *type)175 static int32_t GetDisplayCompChange(uint32_t devId, uint32_t *num, uint32_t *layers, int32_t *type)
176 {
177     DISPLAY_DEBUGLOG();
178     DISPLAY_CHK_RETURN((num == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("num is nullptr"));
179     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayCompChange, num, layers, type);
180 }
181 
SetDisplayClientCrop(uint32_t devId, IRect *rect)182 static int32_t SetDisplayClientCrop(uint32_t devId, IRect *rect)
183 {
184     DISPLAY_DEBUGLOG();
185     DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr"));
186     return DISPLAY_NOT_SUPPORT;
187 }
188 
SetDisplayClientDestRect(uint32_t devId, IRect *rect)189 static int32_t SetDisplayClientDestRect(uint32_t devId, IRect *rect)
190 {
191     DISPLAY_DEBUGLOG();
192     DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr"));
193     return DISPLAY_NOT_SUPPORT;
194 }
195 
SetDisplayClientBuffer(uint32_t devId, const BufferHandle *buffer, int32_t fence)196 static int32_t SetDisplayClientBuffer(uint32_t devId, const BufferHandle *buffer, int32_t fence)
197 {
198     DISPLAY_DEBUGLOG();
199     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayClientBuffer, buffer, fence);
200 }
201 
SetDisplayClientDamage(uint32_t devId, uint32_t num, IRect *rect)202 static int32_t SetDisplayClientDamage(uint32_t devId, uint32_t num, IRect *rect)
203 {
204     DISPLAY_DEBUGLOG();
205     (void)num;
206     DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr"));
207     return DISPLAY_NOT_SUPPORT;
208 }
209 
SetDisplayVsyncEnabled(uint32_t devId, bool enabled)210 static int32_t SetDisplayVsyncEnabled(uint32_t devId, bool enabled)
211 {
212     DISPLAY_DEBUGLOG();
213     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayVsyncEnabled, enabled);
214 }
215 
RegDisplayVBlankCallback(uint32_t devId, VBlankCallback callback, void *data)216 static int32_t RegDisplayVBlankCallback(uint32_t devId, VBlankCallback callback, void *data)
217 {
218     DISPLAY_DEBUGLOG();
219     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::RegDisplayVBlankCallback, callback, data);
220 }
221 
GetDisplayReleaseFence(uint32_t devId, uint32_t *num, uint32_t *layers, int32_t *fences)222 static int32_t GetDisplayReleaseFence(uint32_t devId, uint32_t *num, uint32_t *layers, int32_t *fences)
223 {
224     DISPLAY_DEBUGLOG();
225     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayReleaseFence, num, layers,
226         fences);
227 }
228 
Commit(uint32_t devId, int32_t *fence)229 static int32_t Commit(uint32_t devId, int32_t *fence)
230 {
231     DISPLAY_DEBUGLOG();
232     DISPLAY_CHK_RETURN((fence == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("fence is nullptr"));
233     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::Commit, fence);
234 }
235 
CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t *format, uint32_t *devId)236 static int32_t CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t *format, uint32_t *devId)
237 {
238     DISPLAY_DEBUGLOG();
239     return DISPLAY_NOT_SUPPORT;
240 }
DestroyVirtualDisplay(uint32_t devId)241 static int32_t DestroyVirtualDisplay(uint32_t devId)
242 {
243     DISPLAY_DEBUGLOG();
244     return DISPLAY_NOT_SUPPORT;
245 }
SetVirtualDisplayBuffer(uint32_t devId, BufferHandle *buffer, int32_t releaseFence)246 static int32_t SetVirtualDisplayBuffer(uint32_t devId, BufferHandle *buffer, int32_t releaseFence)
247 {
248     DISPLAY_DEBUGLOG();
249     return DISPLAY_NOT_SUPPORT;
250 }
251 
252 
253 // Layer function
CreateLayer(uint32_t devId, const LayerInfo *layerInfo, uint32_t *layerId)254 static int32_t CreateLayer(uint32_t devId, const LayerInfo *layerInfo, uint32_t *layerId)
255 {
256     DISPLAY_DEBUGLOG();
257     DISPLAY_CHK_RETURN((layerId == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("layerId is nullptr"));
258     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::CreateLayer, layerInfo, layerId);
259 }
260 
CloseLayer(uint32_t devId, uint32_t layerId)261 static int32_t CloseLayer(uint32_t devId, uint32_t layerId)
262 {
263     DISPLAY_DEBUGLOG();
264     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::CloseLayer, layerId);
265 }
266 
SetLayerSize(uint32_t devId, uint32_t layerId, IRect *rect)267 static int32_t SetLayerSize(uint32_t devId, uint32_t layerId, IRect *rect)
268 {
269     DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr"));
270     DISPLAY_DEBUGLOG();
271     return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerSize, rect);
272 }
273 
SetLayerCrop(uint32_t devId, uint32_t layerId, IRect *rect)274 static int32_t SetLayerCrop(uint32_t devId, uint32_t layerId, IRect *rect)
275 {
276     DISPLAY_DEBUGLOG();
277     DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr"));
278     return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerCrop, rect);
279 }
280 
SetLayerZorder(uint32_t devId, uint32_t layerId, uint32_t zorder)281 static int32_t SetLayerZorder(uint32_t devId, uint32_t layerId, uint32_t zorder)
282 {
283     DISPLAY_DEBUGLOG();
284     return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetLayerZorder, layerId, zorder);
285 }
286 
SetLayerPreMulti(uint32_t devId, uint32_t layerId, bool preMul)287 static int32_t SetLayerPreMulti(uint32_t devId, uint32_t layerId, bool preMul)
288 {
289     DISPLAY_DEBUGLOG();
290     return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerPreMulti, preMul);
291 }
292 
SetLayerAlpha(uint32_t devId, uint32_t layerId, LayerAlpha *alpha)293 static int32_t SetLayerAlpha(uint32_t devId, uint32_t layerId, LayerAlpha *alpha)
294 {
295     DISPLAY_DEBUGLOG();
296     DISPLAY_CHK_RETURN((alpha == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("alpha is nullptr"));
297     return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerAlpha, alpha);
298 }
299 
SetTransformMode(uint32_t devId, uint32_t layerId, TransformType type)300 static int32_t SetTransformMode(uint32_t devId, uint32_t layerId, TransformType type)
301 {
302     DISPLAY_DEBUGLOG();
303     return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetTransformMode, type);
304 }
305 
SetLayerDirtyRegion(uint32_t devId, uint32_t layerId, IRect *region)306 static int32_t SetLayerDirtyRegion(uint32_t devId, uint32_t layerId, IRect *region)
307 {
308     DISPLAY_DEBUGLOG();
309     DISPLAY_CHK_RETURN((region == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("region is nullptr"));
310     return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerDirtyRegion, region);
311 }
312 
SetLayerVisibleRegion(uint32_t devId, uint32_t layerId, uint32_t num, IRect *rect)313 static int32_t SetLayerVisibleRegion(uint32_t devId, uint32_t layerId, uint32_t num, IRect *rect)
314 {
315     DISPLAY_DEBUGLOG();
316     DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr"));
317     return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerVisibleRegion, num, rect);
318 }
319 
SetLayerBuffer(uint32_t devId, uint32_t layerId, const BufferHandle *buffer, int32_t fence)320 static int32_t SetLayerBuffer(uint32_t devId, uint32_t layerId, const BufferHandle *buffer, int32_t fence)
321 {
322     DISPLAY_DEBUGLOG();
323     return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerBuffer, buffer, fence);
324 }
325 
SetLayerCompositionType(uint32_t devId, uint32_t layerId, CompositionType type)326 static int32_t SetLayerCompositionType(uint32_t devId, uint32_t layerId, CompositionType type)
327 {
328     DISPLAY_DEBUGLOG();
329     return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerCompositionType, type);
330 }
331 
SetLayerBlendType(uint32_t devId, uint32_t layerId, BlendType type)332 static int32_t SetLayerBlendType(uint32_t devId, uint32_t layerId, BlendType type)
333 {
334     DISPLAY_DEBUGLOG();
335     return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerBlendType, type);
336 }
337 
338 
339 extern "C" {
DeviceInitialize(DeviceFuncs **funcs)340 int32_t DeviceInitialize(DeviceFuncs **funcs)
341 {
342     DISPLAY_CHK_RETURN((funcs == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in funcs is null"));
343     DeviceFuncs *dFuncs = (DeviceFuncs *)calloc(1, sizeof(DeviceFuncs));
344     DISPLAY_CHK_RETURN((dFuncs == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not calloc"));
345 
346     dFuncs->RegHotPlugCallback = RegHotPlugCallback;
347     dFuncs->GetDisplayCapability = GetDisplayCapability;
348     dFuncs->GetDisplaySupportedModes = GetDisplaySupportedModes;
349     dFuncs->GetDisplayMode = GetDisplayMode;
350     dFuncs->SetDisplayMode = SetDisplayMode;
351     dFuncs->GetDisplayPowerStatus = GetDisplayPowerStatus;
352     dFuncs->SetDisplayPowerStatus = SetDisplayPowerStatus;
353     dFuncs->PrepareDisplayLayers = PrepareDisplayLayers;
354     dFuncs->GetDisplayBacklight = GetDisplayBacklight;
355     dFuncs->SetDisplayBacklight = SetDisplayBacklight;
356     dFuncs->GetDisplayProperty = GetDisplayProperty;
357     dFuncs->GetDisplayCompChange = GetDisplayCompChange;
358     dFuncs->SetDisplayClientCrop = SetDisplayClientCrop;
359     dFuncs->SetDisplayClientDestRect = SetDisplayClientDestRect;
360     dFuncs->SetDisplayClientBuffer = SetDisplayClientBuffer;
361     dFuncs->SetDisplayClientDamage = SetDisplayClientDamage;
362     dFuncs->SetDisplayVsyncEnabled = SetDisplayVsyncEnabled;
363     dFuncs->RegDisplayVBlankCallback = RegDisplayVBlankCallback;
364     dFuncs->GetDisplayReleaseFence = GetDisplayReleaseFence;
365     dFuncs->CreateVirtualDisplay = CreateVirtualDisplay;
366     dFuncs->DestroyVirtualDisplay = DestroyVirtualDisplay;
367     dFuncs->SetVirtualDisplayBuffer = SetVirtualDisplayBuffer;
368     dFuncs->SetDisplayProperty = SetDisplayProperty;
369     dFuncs->Commit = Commit;
370     *funcs = dFuncs;
371     DISPLAY_DEBUGLOG("%{public}s: device initialize success", __func__);
372     HdiSession::GetInstance();
373     return DISPLAY_SUCCESS;
374 }
375 
DeviceUninitialize(DeviceFuncs *funcs)376 int32_t DeviceUninitialize(DeviceFuncs *funcs)
377 {
378     DISPLAY_CHK_RETURN((funcs == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in funcs is null"));
379     free(funcs);
380     return DISPLAY_SUCCESS;
381 }
382 
383 
LayerInitialize(LayerFuncs **funcs)384 int32_t LayerInitialize(LayerFuncs **funcs)
385 {
386     DISPLAY_CHK_RETURN((funcs == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("the in funcs is nullptr"));
387     LayerFuncs *lFuncs = (LayerFuncs *)calloc(1, sizeof(LayerFuncs));
388     DISPLAY_CHK_RETURN((lFuncs == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not calloc errno: %{public}d", errno));
389     lFuncs->SetLayerAlpha = SetLayerAlpha;
390     lFuncs->CreateLayer = CreateLayer;
391     lFuncs->CloseLayer = CloseLayer;
392     lFuncs->SetLayerSize = SetLayerSize;
393     lFuncs->SetLayerCrop = SetLayerCrop;
394     lFuncs->SetLayerZorder = SetLayerZorder;
395     lFuncs->SetLayerPreMulti = SetLayerPreMulti;
396     lFuncs->SetTransformMode = SetTransformMode;
397     lFuncs->SetLayerDirtyRegion = SetLayerDirtyRegion;
398     lFuncs->SetLayerVisibleRegion = SetLayerVisibleRegion;
399     lFuncs->SetLayerBuffer = SetLayerBuffer;
400     lFuncs->SetLayerCompositionType = SetLayerCompositionType;
401     lFuncs->SetLayerBlendType = SetLayerBlendType;
402 
403     *funcs = lFuncs;
404     DISPLAY_DEBUGLOG("%{public}s: layer initialize success", __func__);
405     return DISPLAY_SUCCESS;
406 }
407 
LayerUninitialize(LayerFuncs *funcs)408 int32_t LayerUninitialize(LayerFuncs *funcs)
409 {
410     DISPLAY_CHK_RETURN((funcs == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("the funcs is nullptr"));
411     free(funcs);
412     DISPLAY_DEBUGLOG("%{public}s: layer uninitialize success", __func__);
413     return DISPLAY_SUCCESS;
414 }
415 }
416